Spring Boot 系列4 -- 统一功能处理

news2024/9/26 5:18:17

目录

前言

1. Spring AOP 用户统⼀登录验证的问题

1.1 自定义拦截器

1.2 配置拦截器并配置拦截的规则

1.3 拦截器的原理源码分析

2. 统一异常处理

2.1 实现统一异常处理

2.2 测试统一异常处理

3. 统一的数据格式返回

3.1 统⼀数据返回格式的实现

3.2 测试统一的数据返回


前言

        Spring AOP是一个面向切面编程的框架,可以同设置要做处理的类为切面,设置切点进行设置拦截规则,然后定义通知,实现一定的拦截规则.但是我们原生的Spring AOP的框架使用起来比较繁琐.为了解决如此之类的Spring AOP的问题.对于Spring AOP的实战,本文将介绍三种功能.

1. 统一用户登录权限验证

2. 统一数据返回格式

3. 统一异常处理

1. Spring AOP 用户统⼀登录验证的问题

假设我们要实现这样一个功能,在多个页面进行判断用户的登录状态,然后发现当前用户的登录状态为空的时候进行跳转到登录页.

        我们之前的做法是,在每个页面的路由中进行判断用户的登录状态,显然这些操作是重复的,后来我们又学习了Spring AOP,我们试想可以将需要进行验证的类进行设置为切面,在需要地方进行配置拦截的规则,然后进行设置前置通知.这个思想是可以的,但是我们实现起来会遇到两个问题.

1.  没办法获取到 HttpSession 对象(我们需要对Session进行判断当前的用户登录状态)

2.  我们要对⼀部分方法进行拦截,而另⼀部分方法不拦截,如注册⽅法和登录方法是不拦截的,这样的话排除⽅法的规则很难定义,甚至没办法定义。

针对一以上的问题,Spring 框架为我们提供了一个具体实现的拦截器:HandlerInterceptor

而我们要使用这个拦截器实现自己的功能,可以具体分为两步:

 下面我们使用代码进行实现上述的功能:

1.1 自定义拦截器

具体代码:

public class LoginInterceptor implements HandlerInterceptor {
    /**
     * 此方法返回一个boolean类型的值,返回true表示验证成功,继续执行后续流程
     */
    //  重写preHandle方法实现自己的业务代码
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        // 用户登录登录业务判断
        HttpSession session = request.getSession(false);
        if (session != null && session.getAttribute("userinfo") != null){
            // 用户已经登录
            return true;
        }
        // 没有登录,可以进行跳转到登录页面,或者返回一个401 或者403 没有权限码
        response.sendRedirect("/login1.html");
//        response.setStatus(403);
        // 上面两者取一个即可
        return false;
    }

}

1.2 配置拦截器并配置拦截的规则

红色部分就是将自定义的拦截器添加到项目中,然后绿色是一个扩展,就是在路由前面加前缀.

 具体代码:

package com.example.demo.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.PathMatchConfigurer;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

/**
 * Created with IntelliJ IDEA.
 * Description:将自定义拦截器加入到WebMvcConfigurer中,重写addInterceptors方法进行设置拦截规则
 * User: YAO
 * Date: 2023-07-14
 * Time: 15:04
 */
@Configuration
public class AppConfig implements WebMvcConfigurer {
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new LoginInterceptor())
                .addPathPatterns("/**")  // 拦截规则设置,此处进行拦截所有请求
                .excludePathPatterns("/user/login")
                .excludePathPatterns("/user/reg")
                .excludePathPatterns("/user/get-num")
                .excludePathPatterns("/user/get-string")
                .excludePathPatterns("/img/**")
                .excludePathPatterns("/**/*.html");
    }

    // 所有的接⼝添加 api 前缀
      // 给路由进行添加前缀 ,设置为 true 表示启动前缀
//    @Override
//    public void configurePathMatch(PathMatchConfigurer configurer) {
//        configurer.addPathPrefix("api", c -> true);
//    }
}

我们对上述实现的拦截器进行验证

 当进行点击的时候,因为没有Session所以直接跳转到我们设置的登录页面了.

可以看出没有进行设置过Cookie的,就是没有Session连接. 

1.3 拦截器的原理源码分析

所有的方法都会执行 DispatcherServlet 中的 doDispatch 调度方法,观察源码发现:

  点击这个applyPreHandle,applyPreHandle 中会获取所有拦截器 HandlerInterceptor 并执行拦截器中的 preHandle 方法,这与之前我们实现拦截器的步骤对应.

2. 统一异常处理

        统一异常处理是指 在应用程序中定义一个公共的异常处理机制,用来处理所有的异常情况。 这样可以避免在应用程序中分散地处理异常,降低代码的复杂度和重复度,提高代码的可维护性和可扩展性.\

        统⼀异常处理使⽤的是 @ControllerAdvice + @ExceptionHandler 来实现的,@ControllerAdvice 表示控制器通知类,@ExceptionHandler 是异常处理器,两个结合表示当出现异常的时候执行某个通知,也就是执行某个方法事件.

2.1 实现统一异常处理

2.2 测试统一异常处理

我们自己创建一个路由,其中内容出现一个空指针异常,我们查看是否能进行返回给前端处理. 

我们设置的异常处理起到作用了.那么如果不设置,异常的处理,会出现什么样的现象?

就会直接将控制台打印的异常返回给前端,前端拿到数据就很懵.所以统一的异常处理还是很有必要的.

3. 统一的数据格式返回

3.1 统⼀数据返回格式的实现

下述是我们一般的统一返回的数据的格式

实现统一的数据返回格式可以使用 @ControllerAdvice + ResponseBodyAdvice 的方式实现,具体步骤如下:

  1. 创建一个类,并添加 @ControllerAdvice 注解;
  2. 实现 ResponseBodyAdvice 接口,并重写 supports 和 beforeBodyWrite 方法.

 上述部分就是记性统一的数据格式返回.

其中需要注意的是,当返回的类型为String类型的时候,我们需要使用Jackson将String转换成json再进行返回.也就是绿色的部分.

package com.example.demo.config;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
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;

import java.util.HashMap;

/**
 * Created with IntelliJ IDEA.
 * Description:
 * User: YAO
 * Date: 2023-07-14
 * Time: 17:25
 */
@ControllerAdvice
public class ResponseAdvice implements ResponseBodyAdvice {

    @Autowired
    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) {
        HashMap<String, Object> result = new HashMap<>();
        result.put("state",1);
        result.put("msg", "");
        result.put("data", body);
        if (body instanceof String){
            // 需要特殊进行处理,因为String比较特殊,既不是基础类型也不是对象,进行重写的时候String用的格式化工具是自己独有的
            // 在body返回之前没有加载好.需要将String进行单独进行处理.使用Jackson将String转换成json再进行返回.
            try {
                return objectMapper.writeValueAsString(result);
            } catch (JsonProcessingException e) {
                e.printStackTrace();
            }
        }
        return result;
    }
}

3.2 测试统一的数据返回

可以看出返回的格式是我们规定好的格式.这就变得更加统一.


 好啦本文就总结到这了,点个赞吧,谢谢!!!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/832782.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

struct iovec结构体使用

参考 struct iovec 结构体定义与使用 iovec介绍 是一个I/O向量。是与readv和writev操作相关的结构体&#xff0c;readv和writev函数用于在一次函数调用中读、写多个非连续缓冲区。有时也将这两个函数称为散布读&#xff08;scatter read&#xff09;和聚集写&#xff08;gath…

爬虫008_流程控制语句_if_if else_elif_for---python工作笔记026

然后我们再来看一下这里的,判断,可以看到 再看一个判断,这里的布尔类型 第二行有4个空格,python的格式 注意这里,输入的age是字符串,需要转一下才行 int可以写到int(intput("阿斯顿法师打发地方")) 这样也可以

【算法心得】C++map用不着map.find(arr[j])!=map.end();js的map是map不是哈希;编译器选GNU

https://leetcode.com/problems/count-of-range-sum/ https://vjudge.csgrandeur.cn/problem/CodeForces-459D 这两题都是线段树&#xff0c;很明显的单点修改区间查询 leetcode那题我觉得map用hashmap就行&#xff0c;但是好像js里没有hashmap&#xff0c;那就 Map() 也行吧…

webpack复习

webpack webpack复习 webpack基本配置 拆分配置 - 公共配置 生产环境配置 开发环境配置 使用merge webpack-dev-server 启动本地服务 在公共中引入babel-loader处理es6 webpack高级配置 多入口文件 enty 入口为一个对象 里面的key为入口名 value为入口文件路径 例如 pa…

【EI/SCOPUS征稿】第三届智能电网与能源互联网国际会议(SGEI 2023)

第三届智能电网与能源互联网国际会议&#xff08;SGEI 2023&#xff09; 2023 3rd International Conference on Smart Grid and Energy Internet 为交流近年来国内外在智能电网和能源互联网领域的理论、技术和应用的最新进展&#xff0c;展示最新成果&#xff0c;2023年第三…

TSINGSEE青犀视频安防监控EasyCVR视频汇聚平台电子地图定位偏移的排查与解决

安防监控EasyCVR视频汇聚综合管理平台具有强大的数据接入、处理及分发能力&#xff0c;平台可提供视频监控直播、云端录像、云存储、录像检索与回看、告警上报与查询、平台级联、云台控制、语音对讲、电子地图、轨迹跟踪、H.265自动转码等视频能力。 在视频监控管理平台TSINGSE…

第二章:多态

系列文章目录 文章目录 系列文章目录前言多态的概念概念 多态的定义及实现多态的构成条件虚函数虚函数的重写C11 override 和 final重载、覆盖(重写)、隐藏(重定义)的对比 抽象类概念接口继承和实现继承 多态的原理虚函数表多态的原理动态绑定与静态绑定 单继承和多继承关系的虚…

外网渗透信息收集漏洞挖掘

外网渗透信息收集&漏洞挖掘 信息收集一、“资产收集”的重要性二、企业信息收集之域名信息收集2.1、通过域名找到公司2.2、通过公司找到域名3.3、收集每个域名的⼦域名 三、企业信息信息收集之移动资产3.1、移动端APP收集3.2、微信⼩程序收集 四、信息收集流程漏洞挖掘一、…

《面试1v1》ElasticSearch 和 Lucene

&#x1f345; 作者简介&#xff1a;王哥&#xff0c;CSDN2022博客总榜Top100&#x1f3c6;、博客专家&#x1f4aa; &#x1f345; 技术交流&#xff1a;定期更新Java硬核干货&#xff0c;不定期送书活动 &#x1f345; 王哥多年工作总结&#xff1a;Java学习路线总结&#xf…

自动化应用杂志自动化应用杂志社自动化应用编辑部2023年第11期目录

数据处理与人工智能 大数据视域下无轨设备全生命周期健康管理技术的研究 赖凡; 1-3 三维激光扫描结合无人机倾斜摄影在街区改造测绘中的技术应用 张睿; 4-6 井上变电站巡检机器人的设计与应用 刘芳; 7-9 《自动化应用》投稿邮箱&#xff1a;cnqikantg126.com 基于机…

出现一次的数字(其他数字出现三次,两次)

位运算的知识点&#xff1a; 异或运算具有以下几个重要性质 交换律&#xff1a;a ^ b b ^ a 结合律&#xff1a;a ^ (b ^ c) (a ^ b) ^ c 任何数与0异或等于它本身&#xff1a;a ^ 0 a 任何数与自身异或等于0&#xff1a;a ^ a 0 对于数组中所有元素进行异或运算&#xf…

【前端实习生备战秋招】—HTML 和 CSS面试题总结(一)

【前端实习生备战秋招】—HTML 和 CSS面试题总结&#xff08;一&#xff09; 1. 你做的页面在哪些流览器测试过&#xff1f;这些浏览器的内核分别是什么? IE:trident内核 Firefox&#xff1a;gecko内核 Safari:webkit内核 Opera:以前是presto内核&#xff0c;Opera现已改用Goo…

接口测试如何在json中引用mock变量

在测试接口的时候&#xff0c;有的接口需要测试随机传入大量数据&#xff0c;查看数据库是否正常&#xff0c;但是大量的随机数据全靠自己手写会很慢&#xff0c;而且是通过json传递的数据。 这里我们就可以使用mock生成随机变量&#xff0c;然后在json中引用mock变量 首先看…

LeetCode面向运气之Javascript—第2500题-删除每行中的最大值-93.51%

LeetCode第2500题-删除每行中的最大值 题目要求 一个 m x n 大小的矩阵 grid &#xff0c;由若干正整数组成。 执行下述操作&#xff0c;直到 grid 变为空矩阵&#xff1a; 从每一行删除值最大的元素。如果存在多个这样的值&#xff0c;删除其中任何一个。 将删除元素中的最…

地址空间细致入微+深入了解页表

目录 地址空间保存了什么&#xff1f; 页表到底是怎么存储的 我们都知道&#xff0c;我们进程看到的空间其实是虚拟内存&#xff0c;真正的内存是需要页表的映射才能找到真正的物理内存&#xff0c;那么我我们有两个问题的引出那么进程地址空间是保存了什么呢&#xff1f;页表…

Android 获取网络连接状态新方法

一. 问题背景 Android12上&#xff0c;有的app模块判断当前网络的类型和连接状态时&#xff0c;还是使用的旧的API&#xff0c;导致返回的结果不准确&#xff0c;影响代码逻辑判断&#xff0c;本篇文章就这一问题&#xff0c;整理一下判断网络类型和连接状态的新方法。 二. 原因…

Dockerfile面试题(CMD、ENTRYPOINT与RUN命令对比)

目录 Dockerfile面试题 CMD、ENTRYPOINT与RUN命令对比 &#xff08;一&#xff09;CMD命令 &#xff08;二&#xff09;RUN命令 &#xff08;三&#xff09;ENTRYPOINT &#xff08;四&#xff09;RUN和CMD、ENTRYPOINT支持参数形式命令 &#xff1a; Dockerfile面试题 …

新一代的自动化测试利器?puppeteer生态一览

puppeteer是chrome官方出品的无界面浏览器&#xff0c;我们一般称为无头浏览器。 这种浏览器具有普通版浏览器的完备功能&#xff0c;并且可以运行在无界面的服务端&#xff0c;比如远程的linux服务器上&#xff0c;是做ui自动化测试的一个不错的选择。 我们今天就来看一下pu…

智慧林业~经典开源项目数字孪生智慧林业——开源工程及源码

东北林业局的工程和源码免费赠送&#xff0c;帮您实现深林防火的智慧林业。 项目介绍 东北林业局作为东北地区林业管理的重要机构&#xff0c;致力于森林资源保护和防火工作。他们的项目通过先进的技术手段&#xff0c;为林业管理提供可靠的解决方案。 本项目使用数字孪生技术&…

2.3 网络安全协议

数据参考&#xff1a;CISP官方 目录 OSI七层模型TCP/IP体系架构TCP/IP安全架构 一、OSI七层模型 简介 开放系统互连模型&#xff08;Open System Interconnection Reference Model&#xff0c;OSI&#xff09;是国际标准化组织&#xff08;ISO&#xff09;于1977年发布的…