• 博客系统(升级(Spring))(二)获取当前用户信息、对密码进行加密、设置统一数据格式、设置未登录拦截、线程池


    博客系统

    博客系统是干什么的?
    CSDN就是一个典型的博客系统。而我在这里就是通过模拟实现一个博客系统,这是一个较为简单的博客系统,但是主要功能一个不缺,不过就是 UI 有些 low,我学习前端是为了写后端更加顺手。不至于前后端完全分离,但是有个问题设计的 web 页面不是很好看。

    首先我将整体的业务流程展现
    在这里插入图片描述
    我们继博客系统(一)继续,编写

    获取当前用户的信息

    根据项目结构图可以知道,我们无论是登录还是查询必须要获取当前的用户的信息。

    根据session的特点,他会自己生成一个cooker值,我们这里只需要获取信息,但是session是一个 key:value 结构的值,所以还需要的一个公共的,全局变量 ,key值。用来保存和查找对应的value值

    /**
     * 全局变量
     */
    public class Variable {
        public  static final String SESSION_USERINFO_KEY="SESSION_USERINFO";
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    在这里插入图片描述

    接下来我们就可以根据key去寻找当前的用户信息了。

    /**
     * 得到当前的用户信息
     */
    
    public class SessionUtis {
    
        public static Userinfo getUser(HttpServletRequest request){
            HttpSession httpSession=request.getSession(false);
            if (httpSession!=null&&httpSession.getAttribute(Variable.SESSION_USERINFO_KEY)!=httpSession){
                return (Userinfo) httpSession.getAttribute(Variable.SESSION_USERINFO_KEY);
            }
            return null;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    在这里插入图片描述

    对密码进行加密和解密的操作

    首先 UUID 这个类是可以生产出世界上唯一的值(目前是),市面上的加密工具,有很多,我们用 MD5(C级)的就够了,毕竟是个小网站。

    我规定:

    1. 最终密码生成为65位字符
    2. UUID生成的唯一值与用户所注册的密码合并通过加密工具进行加密。得到一个唯一的值
    3. 将这个唯一的值与UUID数生成的唯一的值合并。二者通过 @ 分隔
      • 因为在MD5只能正向加密不能反向解密,所以我们要将唯一的UUID进行保存,从而在解密以及验证密码正确性上有操作空间
      • java基本库里为我们提供了UUID生成类,要搭配方法 randomUUID 使用,且生成的uuid有一些特殊字符,需要我们手动去除,此时得到的是一个32位的唯一字符串
      • java基本库里为我们提供了MD5的加密工具类,DigestUtils,搭配md5DigestAsHex()使用,但是参数是一个二进制数组所以,需要getBytes转换。
    /**
     * 对密码进行加密,解密
     */
    public class PasswordUtils {
        /**
         * 加密
         */
        public  String encryption(String password){
            //uuid生成为唯一值
            String salt= UUID.randomUUID().toString().replace("-","");
            //将uuid和password经过MD5加密得到密码
            String finalPassword=
                    DigestUtils.md5DigestAsHex((salt+password).getBytes(StandardCharsets.UTF_8));
            return salt+"@"+finalPassword;
        }
        /**
         * 解密,并验证密码正确
         */
        public static boolean decrypt(String password,String dbPassword){
            if (!StringUtils.hasLength(password)||!StringUtils.hasLength(dbPassword)||dbPassword.length()!=65){
                return false;
            }
            String [] dbPasswordArray=dbPassword.split("@");
            if (dbPasswordArray.length!=2){
                return false;
            }
            //获取唯一的uuid
            String salt=dbPasswordArray[0];
            //获取生成的md5的密码
            String finalDBpassword=dbPasswordArray[1];
            //通过同样的uuid 和 密码生成出来的值是唯一的。
            String finalPassword=DigestUtils.md5DigestAsHex((salt+password).getBytes(StandardCharsets.UTF_8));
            if (finalDBpassword.equals(finalPassword)){
                return false;
            }
            return true;
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37

    在这里插入图片描述

    设置统一的数据返回格式

    设置这个的目的很简单,在开发的时候有很多人,一起开发,使得数据格式会不一样,我们在这里做一个保底策略。
    这里我们需要添加一个拦截,将返回出去的数据进行统一的格式规划,这里我用常见的j son 格式

    1. ResponseBodyAdvice 接口允许在执行 @ResponseBody 或 ResponseEntity 控制器方法之后,但在使用HttpMessageConverter 写入响应体之前自定义响应,进行功能增强。通常用于 加密,签名,统一数据格式等。

    2. instanceof 是Java中的二元运算符,左边是对象,右边是类;当对象是右边类或子类所创建对象时,返回true;否则,返回false。

      • 类的实例包含本身的实例,以及所有直接或间接子类的实例

      • instanceof左边显式声明的类型与右边操作元必须是同种类或存在继承关系,也就是说需要位于同一个继承树,否则会编译错误

    注意,这里返回的 object 类,但是对于ResponseBodyAdvice 来说,是没有String类型的说法所以需要自己去判断,不然就会报错

    @ControllerAdvice
    public class ResponseAdvice implements ResponseBodyAdvice {
        //格式生成唯一json格式
        @Resource
        private ObjectMapper objectMapper;
    
        @Override
        public boolean supports(MethodParameter returnType, Class converterType) {
            return true;
        }
    
        @Override
        public Object beforeBodyWrite(Object body, MethodParameter returnType,
                                      MediaType selectedContentType,
                                      Class selectedConverterType,
                                      ServerHttpRequest request, ServerHttpResponse response) {
            //格式符合要求,就不用转换格式直接返回
            if (body instanceof ResultAjax){
                return body;
            }
            //格式为String类型,属于特殊类,需要我们手动调换
            if (body instanceof String){
                ResultAjax resultAjax=ResultAjax.success(body);
                try {
                    //将格式转换层json格式,然后返回
                    return objectMapper.writeValueAsString(resultAjax);
                } catch (JsonProcessingException e) {
                    e.printStackTrace();
                }
            }
            
            return ResultAjax.success(body);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34

    这里有不明白的可以去看我的博客-----Spring AOP (拦截器)

    在这里插入图片描述

    设置未登录拦截

    上述一样不知道原理的可以去看我的 博客 Spring AOP (拦截器)

    HandlerInterceptor 和 WebMvcConfigurer搭配使用,前者设置规则,设置拦截的网页

    /**
     * 设置登录拦截规则
     */
    public class LoginIntercept implements HandlerInterceptor {
        @Override
        public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
            HttpSession httpSession=request.getSession(false);
            if (httpSession!=null&&httpSession.getAttribute(Variable.SESSION_USERINFO_KEY)!=null){
                return true;
            }
            response.sendRedirect("/login.html");
            return false;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    /**
     * 拦截的网页和资源
     */
    @Configuration
    public class MyConfig implements WebMvcConfigurer {
        @Override
        public void addInterceptors(InterceptorRegistry registry) {
            registry.addInterceptor(new LoginIntercept())
                    .addPathPatterns("/**")
                    .excludePathPatterns("/css/*");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    在这里插入图片描述

    设置线程池

    这里用的线程池是Spring下的,不用像java本库中的线程池,填入参数,只需要调用set方法写入(不知道线程池可以看我的多线程文章)

    @Configuration
    public class ThreadPoolUltisConfig {
        public ThreadPoolTaskExecutor taskExecutor(){
            ThreadPoolTaskExecutor executor=new ThreadPoolTaskExecutor();
            executor.setCorePoolSize(5);
            executor.setMaxPoolSize(10);
            executor.setQueueCapacity(10000);
            executor.setThreadNamePrefix("MyThread-");
            executor.initialize();
            return executor;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
  • 相关阅读:
    山西电力市场日前价格预测【2023-10-05】
    什么是区块链的“智能合约”
    【非BAT】不需要写BAT批处理:文件也能批量查找与复制,也能完成批量图片的查找,批量的文件查找,查找后复制到指定位置
    【ACL 2022】用于多标签文本分类的对比学习增强最近邻机制
    idea中maven自带Bundled (Maven 2)和Bundled (Maven 3)的文件目录位置
    【CSP-J 2022】上升点列
    学习ASP.NET Core Blazor编程系列十四——修改
    【ShuQiHere】探索人工智能核心:机器学习的奥秘
    Oracle/PLSQL: Extract Function
    业内人士真心话:只会测试没有前途的,我慌了......
  • 原文地址:https://blog.csdn.net/Cheer_RIO/article/details/132783660