个人博客系统[SpringBoot+SpringMVC+MyBais]

文章目录

  • 前言
  • 1.项目目录介绍
  • 2.项目前准备
    • 2.1 使用到的第三方库
    • 2.1 配置文件(application.properties)
    • 2.2 数据库介绍
  • 3.common目录工具类介绍
    • 3.1 AjaxResult类
    • 3.2 AppVariable类
    • 3.3 CaptchaUtils类
    • 3.4 PasswordUtils类
    • 3.5 UserSessionUtils类
  • 4.config目录
    • 4.1 LoginInterceptor---登录拦截器
    • 4.2 ResponseAdvice类
  • 5.功能演示
    • 5.1 UserController类
      • 5.1.1 注册功能
      • 5.1.2 登录功能
      • 5.1.3 显示左边个人信息
      • 5.1.4 注册功能
      • 5.1.5 根据文章中UID查询用户
    • 5.2 CaptchaController类
    • 5.3 ArticleController类
      • 5.3.1 获取登录用户的所有文章
      • 5.3.2 删除文章
      • 5.3.3 根据 文章id 返回文章
      • 5.3.4 修改文章阅读量
      • 5.3.5 用户写博客添加博客
      • 5.3.6 修改博客
      • 5.3.7 分页功能
  • 总结

前言

这个项目是一个基于SSM的个人博客系统项目,项目一个前后端分离的项目,目前已经完工。它的主要技术包含SpringAOP、手动实现的加盐算法、登录验证码、Redis存储Session等.
这个项目已开源,我会将项目的gitee连接放到最下面。

1.项目目录介绍

个人博客系统[SpringBoot+SpringMVC+MyBais]_第1张图片

  • common 目录 : 存放工具类、统一返回格式和全局变量
  • config 目录 : 配置相关的东西,例如:登录拦截器
  • controller 目录 : 处理前端返回的数据
  • entity 目录 : 存放实体类
  • mapper 目录 : 里面是提供给 MyBatis 的接口
  • service 目录 : 这个是统一调用 mapper 的接口
  • resources/Mybatis 目录 : 实现 mapper 中接口,对接数据库
  • resources/static 目录 : 存放前端的内容
  • dp.sql: 存放使用的sql语句

2.项目前准备

2.1 使用到的第三方库

Lombok、Spring Web、Spring Session、MyBatis Framework、MySQL Driver、Hutool、Slf4j

2.1 配置文件(application.properties)

# 数据库连接
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/mycnblog?characterEncoding=utf8&useSSL=false&serverTimezone=UTC
spring.datasource.username=root
spring.datasource.password=9root
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver

## 设置时间格式 对 LocalDateTime 和 LocalDate 不起作用
spring.jackson.date-format=yyyy-MM-dd HH:mm:ss
spring.jackson.time-zone=GMT+8

# mybatis xml 配置
mybatis.mapper-locations=classpath:Mybatis/*Mapper.xml

#   控制台打印mybatis 执行的sql语句
mybatis.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
logging.level.com.example.demo=debug


# redisd配置代码
spring.redis.port=6379
spring.redis.password=
spring.redis.database=0 #默认数据库编号是0
spring.session.store-type=redis
server.servlet.session.timeout=1800
spring.session.redis.flush-mode=on_save
spring.session.redis.namespace=spring:session
spring.redis.host=127.0.0.1

2.2 数据库介绍

数据库中一共有三个表,分别是:用户表(userinfo)、文章表(articleinfo)。用户表用来存储用户信息,文章表就是用来存储文章。

3.common目录工具类介绍

3.1 AjaxResult类

该类是对返回数据进行统一的封装,为什么要统一封装呢?对于前端来说,它们是不懂后端的代码的,因此我们需要将它的数据统一进行封装返回前端,这里使用的方法就是将内容封装成一个类,在需要返回的数据的时候,将这个类实例化,然后将它转化为 Json 的形式传给前端。

package com.example.demo.common;

import lombok.Data;

import java.io.Serializable;

/**
 *  统一数据返回类型
 *
 */
@Data
public class AjaxResult implements Serializable {
    //Serializable接口是为了实现序列化和反序列化不报错
    //状态码
    private Integer code;
    //状态码描述
    private String msg;
    //返回的数据
    private Object data;

    /**
     * 操作成功返回的结果
     * 进行多次重载提供选择
     */
    public static AjaxResult success(Object data) {
        AjaxResult result = new AjaxResult();
        result.setCode(200);
        result.setMsg("");
        result.setData(data);
        return result;
    }

    public static AjaxResult success(int code,Object data) {
        AjaxResult result = new AjaxResult();
        result.setCode(code);
        result.setMsg("");
        result.setData(data);
        return result;
    }

    public static AjaxResult success(int code,String msg,Object data) {
        AjaxResult result = new AjaxResult();
        result.setCode(code);
        result.setMsg(msg);
        result.setData(data);
        return result;
    }

    /**
     * 返回失败结果
     * 进行多次重载提供选择
     *
     */
    public static AjaxResult fail(int code,String msg) {
        AjaxResult result = new AjaxResult();
        result.setCode(code);
        result.setMsg(msg);
        result.setData(null);
        return result;
    }
    public static AjaxResult fail(int code,String msg,Object data) {
        AjaxResult result = new AjaxResult();
        result.setCode(code);
        result.setMsg(msg);
        result.setData(data);
        return result;
    }
}

3.2 AppVariable类

这个就类就简单描述;主要就是存储一些全局变量;为啥要单独使用一个类?这样是为了降低代码的耦合度。

package com.example.demo.common;

/**
 * 保存全局变量
 */
public class AppVariable {

    // 定义 session 的key值
    public static final String USER_SESSION_KEY = "USER_SESSION_KEY";
    // 图片存储在 session 的key值
    public static final String CAPTCHA_SESSION_KEY = "CAPTCHA";

}

3.3 CaptchaUtils类

这个类是配合Hutool库使用的,主要的作用是生成验证码图片和验证验证码的正确性。

package com.example.demo.common;

import cn.hutool.captcha.CaptchaUtil;
import cn.hutool.captcha.LineCaptcha;
import javax.imageio.ImageIO;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;


public class CaptchaUtils {

	// 生成验证码
    public static void generateCaptcha(HttpServletRequest request, HttpServletResponse response) throws IOException {
        LineCaptcha captcha = CaptchaUtil.createLineCaptcha(200, 50);

        // 将验证码存储在Session中用于验证
        request.getSession().setAttribute(AppVariable.CAPTCHA_SESSION_KEY, captcha.getCode());

        // 设置响应头
        response.setContentType("image/png");
        response.setHeader("Pragma", "no-cache");
        response.setHeader("Cache-Control", "no-cache");
        response.setDateHeader("Expires", 0L);

        // 将验证码图片写入响应流
        ServletOutputStream outputStream = response.getOutputStream();
        ImageIO.write(captcha.getImage(), "png", outputStream);
        outputStream.flush();
        outputStream.close();
    }

    /**
     * 判断输入的验证码的正确性
     *
     * @param request
     * @param userInput 用户输入的密码
     * @return
     */
    public static boolean validateCaptcha(HttpServletRequest request, String userInput) {
        String storedCaptcha = (String) request.getSession().getAttribute(AppVariable.CAPTCHA_SESSION_KEY);
        return userInput != null && userInput.equalsIgnoreCase(storedCaptcha);
    }
}

3.4 PasswordUtils类

这个类中实现了加盐算法,这里解释一下加盐算法。我们规定的加盐算法是65位,前32为是盐值通过UUID生成,中间加一个分隔符,之后后面是使用盐值加上明文(密码)再使用MD5加密。具体看下图:
个人博客系统[SpringBoot+SpringMVC+MyBais]_第2张图片
对于解密,我们可以通过分隔符提取出盐值,将盐值传给辅助方法,通过之前一样加盐的方式进行加盐,因为我们同一个数据,我们使用相同的操作,故如果输入的密码和设置的密码一样,那么两次操作后的数据应该是一样的。

package com.example.demo.common;


import org.springframework.util.DigestUtils;
import org.springframework.util.StringUtils;

import java.util.UUID;

/**
 * 实现加盐算法
 *
 */
public class PasswordUtils {

    /**
     * 1.给用户传过来的明文密码加密
     *
     * @param password 明文密码
     * @return  保存在数据库中的密码
     */
    public static String encrypt(String password) {
        // 1.生成盐值(32位)
        String salt = UUID.randomUUID().toString().replace("-","");
        // 2.加盐后的密码:(盐值+明文)再用MD5加密
        String saltPassword = DigestUtils.md5DigestAsHex((salt+password).getBytes());
        // 3.最终密码:【盐值+$+加盐后的密码】(65位)
        String finalPassword = salt+"$"+saltPassword;
        return finalPassword;

    }

    /**
     *  2.辅助解密方法;方法1的重载
     *
     * @param password 用户输入的密码
     * @param salt      盐值(需要从数据库中的密码提取出来)
     * @return
     */
    private static String encrypt(String password,String salt) {
        // 1.加盐后的密码 (32位)
        String saltPassword = DigestUtils.md5DigestAsHex((salt+password).getBytes());
        // 2.最终密码:【盐值+$+加盐后的密码】(65位)
        String finalPassword = salt+"$"+saltPassword;
        return finalPassword;
    }

    /**
     * 3.解密方法
     *
     * @param inputPassword // 用户输入的密码
     * @param sqlPassword // 数据库中的密码
     * @return
     */
    public static boolean check(String inputPassword,String sqlPassword) {
        // 参数校验
        if(StringUtils.hasLength(inputPassword) && StringUtils.hasLength(sqlPassword)
                && sqlPassword.length() == 65) {
            // 获取盐值
            String salt = sqlPassword.substring(0,32);
            // 通过方法1的方式加密
            String confirmPassword = encrypt(inputPassword,salt);
            // 比较两次的结果
            if(confirmPassword.equals(sqlPassword)) {
                return true;
            }
        }
        return false;
    }
}

3.5 UserSessionUtils类

这个类辅助我们获得session中的用户,以及判断是否登录。

package com.example.demo.common;


import com.example.demo.entity.UserInfo;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

/**
 * 操作当前session的工具类
 */
public class UserSessionUtils {

    /**
     * 得到当前用户
     *
     * @param request
     * @return
     */
    public static UserInfo getSessUser(HttpServletRequest request) {
        HttpSession session = request.getSession(false);
        // 判断是否登录
        if (session!=null && session.getAttribute(AppVariable.USER_SESSION_KEY)!= null) {
            // 两个都不为空,标准登录了
            return (UserInfo) session.getAttribute(AppVariable.USER_SESSION_KEY);
        }
        return null;
    }
}

4.config目录

这个目录中主要是实现了一个登录拦截器和 统一返回数据的保底类

4.1 LoginInterceptor—登录拦截器

它是实现原理用到了AOP的思想;这个类需要实现HandlerInterceptor接口,并且重写preHandle方法,判断是否用户登录,如果没有登录,无法访问我们配置之外的接口和网页。
这里的配置是指的AppConfig这个类中的数据

package com.example.demo.config;

import com.example.demo.common.AppVariable;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

/**
 * 登录拦截器
 *
 */
public class LoginInterceptor implements HandlerInterceptor {

    /**
     * true -》 用户已登录
     * false -》用户未登录
     * @param request
     * @param response
     * @param handler
     * @return
     * @throws Exception
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        HttpSession session =request.getSession(false);
        //判断session不为空,并且session的key不为空,说明用户已登录
        if(session != null && session.getAttribute(AppVariable.USER_SESSION_KEY) != null) {
            //用户已登录
            return true;
        }
        // 未登录,跳转到登录页
        response.sendRedirect("/login.html");
        return false;
    }
}

4.2 ResponseAdvice类

这个类是统一返回类型的保底机制,如果我们忘了统一返回类型,那么他会帮我们包装成Json格式。
他是相当于一个控制增强器@ControllerAdvice,我们通过实现ResponseBodyAdvice接口来完成这个功能,它主要重写两个方法,一个是supports方法:它相当于一个开关,true表示需要执行beforeBodyWrite方法,false表现不需要执行beforeBodyWrite方法;然后beforeBodyWrite方法内就是逻辑的具体实现了。

package com.example.demo.config;


import com.example.demo.common.AjaxResult;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.SneakyThrows;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;

/**
 * 实现统一返回数据的保底类
 * 说明:如果返回数据时,检查是否为统一返回类型,如果不是就改为统一类型
 *
 */
@ControllerAdvice
public class ResponseAdvice implements ResponseBodyAdvice {

    @Autowired
    private ObjectMapper objectMapper;

    @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 AjaxResult) return body;
        // 如果是String类型的特殊处理,手动将String转换成json格式
        if(body instanceof String) {
            return objectMapper.writeValueAsString(AjaxResult.success(body));
        }
        //如果不是ajax的格式,并且不上String类型
        return AjaxResult.success(body);
    }
}

5.功能演示

5.1 UserController类

5.1.1 注册功能

前端通过Ajax的方式以Json形式将数据发送给后端,如果注册成功就会询问你是否跳转页面。

/**
     * 注册功能
     *
     * @param userInfo
     * @return
     */
    @RequestMapping("/reg")
    public AjaxResult reg(UserInfo userInfo){
        //非空校验和参数有效性校验
        if(userInfo==null ||  !StringUtils.hasLength(userInfo.getUsername())
                ||  !StringUtils.hasLength(userInfo.getPassword())) {
            return AjaxResult.fail(-1,"参数非法");
        }
        // 对密码加盐加密
        userInfo.setPassword(PasswordUtils.encrypt(userInfo.getPassword()));
        return AjaxResult.success(userService.reg(userInfo));
    }

5.1.2 登录功能

登录我们需要输入用户名和密码和验证码,必须三个都正确才能登录,登录后会直接跳转到个人博客的列表页。

/**
     * 登录功能
     *
     * @param username
     * @param password
     * @param request
     * @return
     */
    @RequestMapping("/login")
    public AjaxResult login(String username,String password,HttpServletRequest request,String captcha) {
        // 非空验证和参数合法性验证
        if(!StringUtils.hasLength(username) || !StringUtils.hasLength(password)) {
            return  AjaxResult.fail(-1,"参数非法");
        }
        // 查询出来数据库中的对象
        UserInfo userInfo = userService.getUserByName(username);
        // 判断验证码的正确性
        boolean isCaptchaValid = CaptchaUtils.validateCaptcha(request, captcha);
        // 判断用户有效性
        if(userInfo !=null && userInfo.getId()>0 && isCaptchaValid) {
            if(PasswordUtils.check(password,userInfo.getPassword())) {
                // 登录成功
                userInfo.setPassword("");//返回数据,隐藏敏感(密码)信息
                // 存储 session
                HttpSession session = request.getSession(true);
                session.setAttribute(AppVariable.USER_SESSION_KEY,userInfo);
                return AjaxResult.success(userInfo);
            }
        }
        return  AjaxResult.success(0,null);
    }

5.1.3 显示左边个人信息

我们通过session读取当前登录的用户,之后再统计这个用户写的文章用户,我们创建一个新的实体类UserInfoVO,这个类主要是辅助我们统计用户的文章数量。
个人博客系统[SpringBoot+SpringMVC+MyBais]_第3张图片

5.1.4 注册功能

直接删除session中的键就算是注销了,我们通过调用session中的removeAttribute方法实现

/**
     * 注销功能
     *
     * @param session
     * @return
     */
    @RequestMapping("/logout")
    public AjaxResult logOut(HttpSession session) {
        session.removeAttribute(AppVariable.USER_SESSION_KEY);
        return AjaxResult.success(1);
    }

5.1.5 根据文章中UID查询用户

当我们点击查看全文的时候,我们需要加载根据文章作者加载作者,我们下方这个方法实现。
个人博客系统[SpringBoot+SpringMVC+MyBais]_第4张图片

 /**
     * 根据文章中UID查询用户
     *
     * @param uid
     * @return
     */
    @RequestMapping("/getuserbyid")
    public AjaxResult getUserById(Integer uid) {
        if(uid==null && uid<=0) {
            return  AjaxResult.fail(-1,"用户id非法!");
        }
        UserInfoVO userInfoVO = new UserInfoVO();
        // 通过前端传的uid查出用户
        UserInfo userInfo = userService.getUserById(uid);
        // 传值方便查询文章篇数
        BeanUtils.copyProperties(userInfo,userInfoVO);
        // 存储文章篇数
        userInfoVO.setArtCount(articleService.getArtCountByUid(uid));
        userInfoVO.setPassword("");// 屏蔽密码
        return AjaxResult.success(userInfoVO);
    }

5.2 CaptchaController类

这个类中主要是配合Hutool库来使用,调用工具类来生成验证码。

package com.example.demo.controller;


import com.example.demo.common.CaptchaUtils;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@Controller
@RequestMapping("/captcha")
public class CaptchaController {

    @GetMapping("/generate")
    public void generateCaptcha(HttpServletRequest request, HttpServletResponse response) throws IOException {
        CaptchaUtils.generateCaptcha(request, response);
    }

    @GetMapping("/validate")
    @ResponseBody
    public boolean validateCaptcha(HttpServletRequest request, String userInput) {
        return CaptchaUtils.validateCaptcha(request, userInput);
    }
}

5.3 ArticleController类

5.3.1 获取登录用户的所有文章

通过session获得当前登录的用户,然后查询他的所有文章,并返回给前端。
个人博客系统[SpringBoot+SpringMVC+MyBais]_第5张图片

/**
     * 获取登录用户的所有文章
     *
     * @param request
     * @return
     */
    @PostMapping("/mylist")
    public AjaxResult getMyList(HttpServletRequest request) {
        // 1.得到用户
        UserInfo userInfo = UserSessionUtils.getSessUser(request);
        // 判断用户是否成功登录
        if (userInfo == null) {
            // 登录失败的情况
            return AjaxResult.fail(-1,"非法请求");
        }
        // 2.查询用户所有文章
        List<ArticleInfo> list = articleService.getAllArtByUId(userInfo.getId());
        for (ArticleInfo a:list) {
            String s = a.getContent();
            s=s.replaceAll("#","");
            if(s.length()>50) {
                a.setContent(s.substring(0,50)+"...");
            }else {
                a.setContent(s);
            }

        }
        return AjaxResult.success(list);
    }

5.3.2 删除文章

删除文章时,我们需要判断登录的这个人是不是这篇文章的作者,如果这篇文章是张三写的,李四把他删了,那就杯具了!!

 /**
     * 这里需要注意,我们在删除的时候,需要确认删除的这篇文章是现在登录用户的文章
     *
     * @param request
     * @param id 文章id
     * @return
     */
    @RequestMapping("/del")
    public AjaxResult delArtById(HttpServletRequest request,Integer id) {
        // 1.得到用户
        UserInfo userInfo = UserSessionUtils.getSessUser(request);
        // 判断用户是否成功登录
        if (userInfo == null || userInfo.getId()<=0) {
            // 登录失败的情况
            return AjaxResult.fail(-1,"非法请求");
        }
        // 判断文章id 的合法性
        if(id<=0 || id==null) {
            return AjaxResult.fail(-1,"非法参数");
        }
        // 这个表示影响的行数
        int res = articleService.delArtById(id,userInfo.getId());
        return AjaxResult.success(res);
    }

5.3.3 根据 文章id 返回文章

前端发送过来文章的id,我们通过文章id 返回文章。

/**
     * 根据 文章id 返回文章
     *
     * @param id 文章id
     * @return
     */
    @RequestMapping("/detail")
    public AjaxResult getArtDetailById(Integer id) {
        if(id==null || id<=0) {
            return  AjaxResult.fail(-1,"文章id非法");
        }
        // 通过文章id 查询文章
        ArticleInfo articleInfo = articleService.getArtDetailById(id);
        return AjaxResult.success(articleInfo);
    }

5.3.4 修改文章阅读量

前端发过来文章id,为了保证操作的原子性,我们通过数据库操作来对阅读量加一。

/**
     * 修改文章阅读量
     *
     * @param id 文章id
     * @return
     */
    @RequestMapping("/updatercount")
    public AjaxResult inCrRCount(Integer id) {
        if(id==null || id<=0) {
            return  AjaxResult.fail(-1,"文章id非法");
        }
        return AjaxResult.success(articleService.inCrRCount(id));
    }

5.3.5 用户写博客添加博客

我们直接使用使用通过ArticleInfo类来接收前端发送的信息,这样的好处是不管别人传的什么,我们都不要取修改参数的个数。

/**
     * 用户写博客添加博客
     *
     * @param request
     * @param articleInfo
     * @return
     */
    @RequestMapping("/add")
    public AjaxResult add(HttpServletRequest request,ArticleInfo articleInfo) {
        // 1.参数效验
        if(articleInfo ==null || !StringUtils.hasLength(articleInfo.getTitle())
                || !StringUtils.hasLength(articleInfo.getContent())) {
            return AjaxResult.fail(-1,"非法参数");
        }
        // 2.给文章添加上uid
        // a.获得user对象
        UserInfo userInfo = UserSessionUtils.getSessUser(request);
        // b.user的合法性验证
        if(userInfo==null || userInfo.getId()<=0){
            return AjaxResult.fail(-1,"参数非法");
        }
        // b.赋值art的uid
        articleInfo.setUid(userInfo.getId());
        return AjaxResult.success(articleService.add(articleInfo));
    }

5.3.6 修改博客

我们得先获得当前的登录对象,得到登录对象是为了给修改后的文章添加UID,为啥不让前端直接传输UID呢,这是因为有风险(防止别人抓包恶搞),因此我们通过session获取用户再写入UID

/**
     * 修改博客
     *
     * @param articleInfo
     * @param request
     * @return
     */
    @RequestMapping("/update")
    public AjaxResult upDate(ArticleInfo articleInfo,HttpServletRequest request) {
        // 1.参数效验
        if(articleInfo==null || !StringUtils.hasLength(articleInfo.getTitle())
        || !StringUtils.hasLength(articleInfo.getContent()) || articleInfo.getId()==null) {
            return AjaxResult.fail(-1,"参数非法");
        }
        // 2.修改数据库中的数据
        // a.获得 user 对象
        UserInfo userInfo = UserSessionUtils.getSessUser(request);
        // 判断 user 对象和合法性
        if(userInfo == null || userInfo.getId()<=0) {
            return AjaxResult.fail(-1,"无效用户");
        }
        // 这里不能让前端传uid,别人抓包可以抓到,有风险
        articleInfo.setUid(userInfo.getId());
        // 修改时间
        articleInfo.setUpdatetime(LocalDateTime.now());
        // b.将数据保存到数据库中
        return AjaxResult.success(articleService.upDate(articleInfo));
    }

5.3.7 分页功能

前端需要给我们传过来页码和一页的文章数量,这样是为了方便我们计算到底需要共几页。

/**
     * 分页功能的实现
     *
     * @param pindex 页码(从一开始)
     * @param psize 一页所展现的文章数量
     * @return
     */
    @RequestMapping("/listbypage")
    public AjaxResult getListByPage(Integer pindex,Integer psize) {
        // 1.参数矫正
        if(pindex==null || pindex<=1) {
            pindex =1;
        }
        if(psize==null || psize<=1) {
            psize = 2;
        }
        // 分页公式
        int offsize =(pindex-1)*psize;
        List<ArticleInfo> list = articleService.getListByPage(psize,offsize);
        // 获取总页数
        // a.获得文章总条数
        int artCount = articleService.getCountALLArt();
        // b.计算页数: 文章文章总条数/一页所展现的文章数量(无论获得的值小数点多小,都需要进1)
        double pcountdb = artCount/(psize*1.0);
        int pcount = (int) Math.ceil(pcountdb);
        HashMap<String,Object> result = new HashMap<>();
        result.put("list",list);
        result.put("pcount",pcount);
        return AjaxResult.success(result);
    }

总结

总的来说,这个项目内容的覆盖率非常大,项目的亮点在于登录拦截器的实现、登录验证码的实现、文章分页、手动实现加盐算法、Redis存储Session。

最后附上代码仓库:点击跳转:个人博客项目代码

如果你有任何疑问,可以添加下方微信!

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