【Java项目】—— 基于SpringMVC+SpringBoot+MyBatis的博客系统

基于SpringMVC+SpringBoot+MyBatis的博客系统

  • 一、项目简介
  • 二、功能分析
    • 网页博客系统支持以下核心功能:
    • 1. 注册登录
    • 2. 编写发表文章
    • 3. 主页列表
    • 4. 修改文章
    • 5. 密码加盐
    • 6. 修改密码
    • 7. 存为草稿
  • 三、相关技术
    • 1. SpringBoot
    • 2. Mybatis
    • 3. SpringMVC
  • 四、核心设计代码
    • 统一返回数据格式的封装
    • 统一异常的处理
    • 拦截器
    • 基本的注册功能
    • 修改文章
    • 密码加盐
  • 五、具体实现
  • 六、基本页面展示

一、项目简介

博客系统

  1. 该博客系统的的平台开发语言是基于面向对象思想的Java语言,在windows环境下,集成了SpringBoot 框架作为项目的骨架,使用CSS,HTML等前端技术,并使用MySQL作为本项目的后台数据库。
  2. 本系统有3个数据库表,用户信息表userinfo ,文章信息表articleinfo,评论表commentinfo
  3. 将项目部署在云服务器上: 部署
  4. 访问项目

【Java项目】—— 基于SpringMVC+SpringBoot+MyBatis的博客系统_第1张图片

二、功能分析

网页博客系统支持以下核心功能:

  • 用户注册、登录、退出功能
  • 已登录用户编辑进行发布、修改、查看详情、删除功能,同时也可以进入其他用户的主页,查看其发表文章.
  • 未登录用户可以使用博客列表页,查看所有用户的文章详情
  • 文章评论功能
  • 文章保存草稿功能.
  • 使用 HandlerInterceptor 实现了统一登录拦截器.
  • 使用 ResponseBodyAdvice 实现了统一数据格式返回

1. 注册登录

    注册使用确认密码,使用MD5+盐值的方式将用户密码加密存储在数据库中
    登录时在数据库里面查询对比用户名,调用解密函数成功登录后将用户信息存储在session里面

2. 编写发表文章

     用户登录以后,可以使用MarkDown编辑器编辑博客,然后发表博客

3. 主页列表

     未登录也可以浏览博客,查看别人发表的博客

  • 添加了分页功能: 分页实现

4. 修改文章

    修改必须是建立在已登录的基础上,点击修改按钮,跳转到编辑页面,文章标题和内容都不为空,点击修改,即可成功

5. 密码加盐

    使用MD5加密。每次加密之前,给密码加上不同的盐值(32)生成一个最终密码(32)
存储在数据库里面的密码(64)=盐值+最终密码

6. 修改密码

7. 存为草稿

草稿功能和发表文章类似,但是也有稍微的区别

  • 新文章,发表和草稿一样,但是存入数据库时,将草稿文章状态state设为2
  • 对于已有的文章,修改文章时,将草稿文章状态state设为2
<insert id="SaveDraft">
        insert into articleinfo (title,content,uid,state) values(#{title},#{content},#{uid},2)
</insert>

三、相关技术

1. SpringBoot

  • 快速集成框架,Spring Boot 提供了启动添加依赖的功能,用于集成各种框架
  • 内置运行容器,无需配置 Tomcat 等 Web 容器,直接运行和部署程序
  • 快速部署项目,无需外部容器即可启动并运行项目
  • 抛弃繁琐的 XML,使用注解和配置的方式进行开发
  • RequestMapping,是用来注册接口的路由

2. Mybatis

    MyBatis 是一款优秀的持久层框架,MyBatis 去除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作
    MyBatis 也是一个 ORM 框架,会将数据库模型的每张表都映射为一个 Java 类,把字段映射为对象的属性,也就是说使用 MyBatis 可以像操作对象一样来操作数据库中的表

3. SpringMVC

四、核心设计代码

统一返回数据格式的封装

public class AjaxResult {

    public static HashMap<String, Object> success(Object data) {
        HashMap<String, Object> result = new HashMap<>();
        result.put("code", 200);
        result.put("msg", "");
        result.put("data", data);
        return result;
    }
public static HashMap<String, Object> fail(int code,String msg) {
        HashMap<String, Object> result = new HashMap<>();
        result.put("code", code);
        result.put("msg", msg);
        result.put("data", "");
        return result;
    }

统⼀的数据返回格式可以使用 @ControllerAdvice ,
类实现ResponseBodyAdvice 接口,重写supports() 方法和beforeBodyWrite() 方法实现



@ControllerAdvice
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 HashMap){//本身已经封装好
            return body;
        }
        if(body instanceof String){//返回类型是String(特殊类型)
            ObjectMapper objectMapper = new ObjectMapper();
            return objectMapper.writeValueAsString(AjaxResult.success(body));
        }
        return AjaxResult.success(body);
    }
}

统一异常的处理

@ControllerAdvice 表示控制器通知类,@ExceptionHandler 是异常处理器,两个结合表示当出现异常的时候执行某个方法事件

@ControllerAdvice
@ResponseBody
public class ExceptionAdvice {

    @ExceptionHandler(Exception.class)
    public  Object exceptionAdvice(Exception e){

        return AjaxResult.fail(-1,e.getMessage());//程序报错的时候返回给前端的一个对象
    }
    
}

拦截器

Spring 中提供了具体的实现拦截器:HandlerInterceptor,拦截器的实现分为以下两个步骤:

  1. 创建自定义拦截器loginInterceptor(添加注解@Component),实现 HandlerInterceptor 接口,然后重写 preHandle方法
  2. 自定义拦截规则Config(加上@Configuration注解),这个类实现 WebMvcConfigurer 接口,然后重写addInterceptors 方法中,使用@Autowired注入拦截器loginInterceptor
@Component
public class LoginInterceptor implements HandlerInterceptor {
    @Override
    public  boolean preHandle(HttpServletRequest request, HttpServletResponse response,Object handler)throws Exception{
        //有session 就得到,没有也不创建,和controller 里面的session 不一样
        HttpSession session = request.getSession(false);
        if(session!= null && session.getAttribute(Constant.SESSION_USERINFO_KEY) != null){
            //从session中得到userinfo 对象,表示已经登录
            //不等于空,表示当前已经登录
            return  true;
        }
        response.setStatus(401);//401表示没有登录,403表示登录但是没有权限
        return false;
    }
}

基本的注册功能

  @RequestMapping("reg")//注册功能
    public Object reg(String username,String password){//返回的是包装的数据类型

        //1.非空校验
        if(!StringUtils.hasLength(username) || !StringUtils.hasLength(password)){
            return AjaxResult.fail(-1,"非法的参数请求");
        }
        //2.添加操作
        int result = userService.add(username,password);
        if(result == 1){
            return  AjaxResult.success("添加成功!",1);
        }else {
            return AjaxResult.fail(-1,"数据库添加出错!");
        }
    }

修改文章

 @RequestMapping("/update")//更新文章内容
    public  int update(HttpServletRequest request,Integer aid,String title,String content){
        //1.非空校验
        if(aid == null || title == null || content == null){
            return 0;
        }
        UserInfo userInfo = SessionUtil.getLoginUser(request);
        if(userInfo != null && userInfo.getId() >0){
            return articleService.update(aid,userInfo.getId(),title,content);
        }
        return  0;
    }

密码加盐


    public  static String encrypt(String password ) {
        //每次生成内容不同的,但长度固定的32位的盐值
        String salt = UUID.randomUUID().toString().replace("-","");
        //最终密码=md5(盐值+密码)
        String finalPassword = DigestUtils.md5DigestAsHex((salt+password).getBytes());
        return salt + finalPassword;

    }
 function getURLParam(key){
                var params = location.search;
                if(params.indexOf("?") >=0){
                    params = params.substring(params.indexOf("?")+1);
                    var paramArr = params.split('&');
                    for(var i=0; i<paramArr.length;i++){
                        var namevalues = paramArr[i].split("=");
                        if(namevalues[0]==key){
                            return namevalues[1];
                        }
                    }
                }else{
                    return "";
                }
            }

五、具体实现

【Java项目】—— 基于SpringMVC+SpringBoot+MyBatis的博客系统_第2张图片

  • 创建好一个SpringMVC项目
  • application.yml,在里面配置连接字符串,配置 MyBatis 中的 XML 路径
spring:
  datasource:
    url: jdbc:mysql://localhost:3306/mycnblog?characterEncoding=utf8&useSSL=false
    username: root
    password: 942599
    driver-class-name: com.mysql.cj.jdbc.Driver

mybatis:
  mapper-locations: classpath:mapper/**Mapper.xml
  configuration: # 配置打印 MyBatis 执行的 SQL
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
  • 使用MyBatis 的方式实现功能
    1.添加@Mapper接口
    2.添加XML实现接口的文件(具体的SQL)
  • 添加实体层(model)
    user和article 两个实体类,使用@Data 注解,使用数据库表进行属性的创建
  • 添加控制层(controller)
    UserController 和ArticleController 两个控制,使用@RestController和@RestMapping 注解,负责前后端交互,调用service层返回的数据
  • 添加服务层service
    UserService 和ArticleService 两个服务,使用@Service 注解,本层不直接操作数据库,调用mapper层,提供controller层调用的方法
  • 持久层(mapper)
    这层是接口,UserMapper和ArticleMapper,不是类,使用@Mapper注解
    在resource 层添加对应的mapper,此处的mapper用来编写SQL语句实现增删改查,添加MyBatis .xml模板语句,注意修改相应的mapper名称
    【Java项目】—— 基于SpringMVC+SpringBoot+MyBatis的博客系统_第3张图片
    【Java项目】—— 基于SpringMVC+SpringBoot+MyBatis的博客系统_第4张图片

六、基本页面展示

  • 用户首先进行注册,注册成功以后跳转至登录页面
  • 登录成功跳转至博客列表页面
  • 在自己的博客页面,可以编写新的博客,查看已发布的博客内容详情,修改已发布的博客等
  • 编写,修改博客的时候,可以直接发表,或者存为草稿(使用文章的状态 state 来区分)
  • 主页浏览文章详情使得该篇文章阅读量+1
    【Java项目】—— 基于SpringMVC+SpringBoot+MyBatis的博客系统_第5张图片
    【Java项目】—— 基于SpringMVC+SpringBoot+MyBatis的博客系统_第6张图片
    【Java项目】—— 基于SpringMVC+SpringBoot+MyBatis的博客系统_第7张图片
    【Java项目】—— 基于SpringMVC+SpringBoot+MyBatis的博客系统_第8张图片
    【Java项目】—— 基于SpringMVC+SpringBoot+MyBatis的博客系统_第9张图片

【Java项目】—— 基于SpringMVC+SpringBoot+MyBatis的博客系统_第10张图片

你可能感兴趣的:(项目,mybatis,java,spring,boot,spring)