小工具知识网

当前位置: 首页 > 行业知识 > 博客系统(SSM)

行业知识

博客系统(SSM)

2026-11-10 21:05:43 来源:互联网转载

前���页面http://t.csdnimg.cn/zwKyG以上是之前写过的博客前端页面的内容,下面是通过SSM实现的后端内容。

目录

一.准备工作

1.1数据准备

1.2修改配置版本文件

1.3配置数据库

二.项目公共模块

2.1实体类

2.2操作数据库部分

三.功能开发

3.1博客列表

获取博客列表

修改日期格式

3.2博客详情

3.3实现登录(使用令牌)

账号密码登录

强制登录

3.4实现显示用户信息

3.5实现用户退出

3.6实现发博客

3.7实现删除、编辑博客

编辑按钮

编辑博客

​编辑

删除博客

3.8加密(盐值)


一.准备工作

1.1数据准备

建表SQL

-- 建表SQLcreate database if not exists java_blog_spring charset utf8mb4;
-- ⽤⼾表DROP TABLE IF EXISTS java_blog_spring.user;CREATE TABLE java_blog_spring.user( `id` INT NOT NULL AUTO_INCREMENT, `user_name` VARCHAR ( 128 ) NOT NULL, `password` VARCHAR ( 128 ) NOT NULL, `github_url` VARCHAR ( 128 ) NULL, `delete_flag` TINYINT ( 4 ) NULL DEFAULT 0, `create_time` DATETIME DEFAULT now(), `update_time` DATETIME DEFAULT now(), PRIMARY KEY ( id ),UNIQUE INDEX user_name_UNIQUE ( user_name ASC )) ENGINE = INNODB DEFAULT CHARACTERSET = utf8mb4 COMMENT = '⽤⼾表';-- 博客表drop table if exists java_blog_spring.blog;CREATE TABLE java_blog_spring.blog ( `id` INT NOT NULL AUTO_INCREMENT, `title` VARCHAR(200) NULL,  `content` TEXT NULL, `user_id` INT(11) NULL, `delete_flag` TINYINT(4) NULL DEFAULT 0, `create_time` DATETIME DEFAULT now(), `update_time` DATETIME DEFAULT now(), PRIMARY KEY (id))ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 COMMENT = '博客表';-- 新增⽤⼾信息insert into java_blog_spring.user (user_name, password,github_url)values("zhangsan","123456","https://gitee.com/Roylele-java-j");insert into java_blog_spring.user (user_name, password,github_url)values("lisi","123456","https://gitee.com/Roylele-java-j");insert into java_blog_spring.blog(title,content,user_id) values("第一篇博客","111我是博客正文我是博客正文我是博客正文",1);insert into java_blog_spring.blog(title,content,user_id) values("第一篇博客","222我是博客正文我是博客正文我是博客正文",2);

1.2创建项目

以JDK17创建,改成JDK8的版本

修改pom文件

1.2修改配置版本文件

1.3配置数据库

 配置application.yml文件

#数据库连接配置spring:  datasource:    url: jdbc:mysql://127.0.0.1:3306/java_blog_spring?characterEncoding=utf8&useSSL=false    username: root    password: root    driver-class-name: com.mysql.cj.jdbc.Drivermybatis:  configuration:    map-underscore-to-camel-case: true #配置驼峰⾃动转换    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl #打印sql语句  mapper-locations: classpath:mapper/**Mapper.xml# 设置⽇志⽂件的⽂件名logging:  file:   name: logger/spring-blog.log

二.项目公共模块

项目分为控制层(Controller), 服务层(Service), 持久层(Mapper). 各层之间的调用关系如下:

2.1实体类

@Datapublic class UserInfo {    private Integer id;    private String userName;    private String password;    private String githubUrl;    private Byte deleteFlag;    private Date createTime;    private Date updateTime;}
@Datapublic class BlogInfo {    private Integer id;    private String title;    private String content;    private Integer userId;    private Integer deleteFlag;    private Date createTime;    private Date updateTime;}

2.2操作数据库部分

涉及到数据库的部分:

1.用户登录,校验用户名和密码是否正确

SQL:根据用户名,查询用户信息

2.博客列表页

SQL:根据ID名,查询用户信息

SQL:获取博客列表

3.博客详情页··

SQL:根据博客ID,获取博客详情

SQL:根据博客ID,编辑博客

SQL:根据博客ID,删除博客

4.博客添加/修改

SQL:根据输入内容,添加博客

对数据库的操作

@Mapperpublic interface UserInfoMapper {//    根据用户名,查询用户信息    @Select("select * from user where user_name=#{userName} and delete_flag=0")    UserInfo queryByName(String userName);//    根据用户ID,查询用用户信息    @Select("select * from user where id=#{id} and delete_flag=0")    UserInfo queryById(Integer id);}
@Mapperpublic interface BlogInfoMapper {//    获取博客列表    @Select("select * from blog where delete_flag=0")    List queryBlogList();//    根据博客ID,获取博客详情    @Select("select * from blog where id=#{id} and delete_flag=0")    BlogInfo queryById(Integer id);    @Update("update blog set title=#{title},content=#{content} where id=#{id}")//    根据博客ID,编辑博客    Integer update(BlogInfo blogInfo);    @Update("update blog set delete_flag=1 where id=#{id}")//    根据博客ID,删除博客    Integer deleteBlog(Integer id);//    根据输入内容,添加博客    @Insert("insert into blog(title,content,user_id) values(#{title},#{content},#{userId})")    Integer insertBlog(BlogInfo blogInfo);}

测试操作数据库功能

@SpringBootTestclass UserInfoMapperTest {    @Autowired    private UserInfoMapper userInfoMapper;    @Test    void queryByName() {        System.out.println(userInfoMapper.queryByName("zhangsan"));    }    @Test    void queryById() {        System.out.println(userInfoMapper.queryById(2));    }}
@SpringBootTestclass BlogInfoMapperTest {    @Autowired    private BlogInfoMapper blogInfoMapper;    @Test    void queryBlogList() {        System.out.println(blogInfoMapper.queryBlogList());    }    @Test    void queryById() {        System.out.println(blogInfoMapper.queryById(1));    }    @Test    void update() {        BlogInfo blogInfo=new BlogInfo();        blogInfo.setTitle("test11111");        blogInfo.setContent("好想躺平");        blogInfo.setId(3);        blogInfoMapper.update(blogInfo);    }    @Test    void deleteBlog() {        blogInfoMapper.deleteBlog(3);    }    @Test    void insertBlog() {        BlogInfo blogInfo=new BlogInfo();        blogInfo.setTitle("test");        blogInfo.setContent("好好学习,天天向上");        blogInfo.setUserId(1);        blogInfoMapper.insertBlog(blogInfo);    }}

定义返回结果的类型Result

//定义统一的返回结果@Datapublic class Result {    private int code;//200-成功 -1失败    private String errorMsg;//    private T data;        public static  Result success(T data){        Result result=new Result();        result.setCode(Constants.RESULT_SUCCESS);        result.setData(data);        return result;    }    public static  Result fail(String errorMsg,T data){        Result result=new Result();        result.setCode(Constants.RESULT_FAIL);        result.setErrorMsg(errorMsg);        result.setData(data);        return result;    }}

把常量对应放在一个类Constants中:

public class Constants {    public static final Integer RESULT_SUCCESS=200;    public static final Integer RESULT_FAIL=-1;}

使用AOP的方式完成统一返回结果处理:

@ControllerAdvice//AOP统一返回结果public class ResponseAdvice implements ResponseBodyAdvice {    @Override    public boolean supports(MethodParameter returnType, Class converterType) {        return true;    }    @SneakyThrows    @Override    public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {        if(body instanceof Result){            return body;        }        //返回结果是String类型需要单独处理        if (body instanceof String){            ObjectMapper objectMapper=new ObjectMapper();            return objectMapper.writeValueAsString(Result.success(body));        }        return Result.success(body);    }}

统一异常处理:

//统一异常处理 拦截异常@ResponseBody//返回的是对象,而不是页面@ControllerAdvicepublic class ErrorAdvice {    @ExceptionHandler//捕获到异常的注释    public Result errorHandler(Exception e){        Result result=new Result();    //  写法一    //  result.setErrorMsg(e.getMessage());    //  写法二        result.setErrorMsg("内部发生错误,请联系管理员");        result.setCode(Constants.RESULT_FAIL);        return result;    }}

三.功能开发

3.1博客列表

获取博客列表

约定前后端交互接口:

请求:blog/getList

响应:''code'':200 , ''msg'':" " data:

@RequestMapping("/blog")@RestControllerpublic class BlogController {    @Autowired    private BlogService blogService;    //获取博客列表    @RequestMapping("/getList")    public List getBlogList(){        return  blogService.getBlogList();    }}
@Servicepublic class BlogService {    @Autowired    private BlogInfoMapper blogInfoMapper;    public List getBlogList() {        return blogInfoMapper.queryBlogList();    }}
@Mapperpublic interface BlogInfoMapper {//    获取博客列表    @Select("select * from blog where delete_flag=0")    List queryBlogList();

前端交互部分:

         getBlogList();        function getBlogList(){            $.ajax({                type:"get",                url:"/blog/getList",                success:function(result){                if(result.code==200 && result.data!=null){                    var blogList=result.data;                    //拼接字符串                    var finalHtml="";                    //对每一条博客,拼接成一个p                    for(var blog of blogList){                        finalHtml +='';                        finalHtml +=''+blog.title+'';                            finalHtml +=''+blog.createTime+'';                            finalHtml +=''+blog.content+'';                            finalHtml +='查看全文>>';                            finalHtml +=' ';                        }                    $(".right").html(finalHtml);                }            }            });        }    

此时查看页面:

修改日期格式

对日期格式进行修改:使用SimpleDataFormat

创建一个日期工具类

//日期工具类public class DateUtils {    //日期转换成2024-02-28 16;02这种格式    public static String formatDate(Date date){        SimpleDateFormat simpleDateFormat=new SimpleDateFormat("yyyy-MM-dd HH:mm");        return simpleDateFormat.format(date);    }}

对BlogInfo中的 private Date createTime;

自己重新定义想要的get方法

@Datapublic class BlogInfo {    private Integer id;    private String title;    private String content;    private Integer userId;    private Integer deleteFlag;    private Date createTime;    private Date updateTime;    //自定义Date的get方法    public String getCreateTime() {        return DateUtils.formatDate(createTime);    }}

3.2博客详情

通过点击博客列表页的产看全文进入到详细的博客详情页。

后端代码:

约定前后端交互接口:

请求:/blog/getBlogDetail?blogId=1

BlogController类中添加BlogService类中添加

 //获取博客详情    @RequestMapping("/getBlogDetail")    public BlogInfo getBlogDetail(Integer blogId){        return blogService.getBlogDetail(blogId);    }
BlogService类中添加
  public BlogInfo getBlogDetail(Integer id) {        return blogInfoMapper.queryById(id);    }

测试后端代码:

前端代码:

blog_detail.html

 //获取博客详情        $.ajax({            type:"get",            url:"/blog/getBlogDetail"+location.search,            success:function(result){                if(result.code==200 && result.data!=null){                    var blog=result.data;                    $(".title").text(blog.title);                    $(".date").text(blog.creatTime);                    $(".detail").text(blog.content);                }            }        });

3.3实现登录(使用令牌)

账号密码登录

以前使用的方式:

1.根据用户名和密码,验证密码是否正确

2.如果密码正确,存储session

3.后续访问时,携带cookie(携带sessionId)

现在使用token的方式:

1.根据用户名和密码,验证密码是否正确

2.如果密码正确,后端生成token,并返回给前端(可以放在cookie中,也可以放在本地存储中)

3.后续访问,携带token,后端校验token的合法性(通常放在http请求的header中)

约定前后端交互接口:

/user/login

参数username=xxx&&password=xxx

创建JwtUtils工具类
//JWT工具类public class JwtUtils {    private static final String secretString="yvc+h4mLEjn0+7s1XQNUp8q71z5kuYgn2JnAvLXK8Hg=";    private static final long expiration=30*60*1000;    private static final Key key= Keys.hmacShaKeyFor(Decoders.BASE64.decode(secretString));//签名的编码方式    public static String genToken(Map claim){        String token= Jwts.builder()                .setClaims(claim)//设置载荷                .setExpiration(new Date(System.currentTimeMillis()+expiration))//生成过期时间                .signWith(key)//设置签名                .compact();//生成token        return token;    }}
UserController中添加
@RequestMapping("/user")@RestControllerpublic class UserController {    @Autowired    private UserService userService;    @RequestMapping("/login")    public Result login(String username, String password){        //1.参数校验        //2.密码校验        //3.生成token并返回        if(!StringUtils.hasLength(username) || !StringUtils.hasLength(password)){            return Result.fail("用户名或密码为空");        }        //获取数据库中的密码        UserInfo userInfo=userService.queryByName(username);        if(userInfo==null ||userInfo.getId()

上一篇:网站源码授权破解揭秘,违法行为警示与深度剖析

下一篇:轻松上手!iPhone下载歌曲与播放教程