【Spring】SpringBoot 统一功能处理

Spring Boot 统⼀功能处理模块是 AOP 的实战环节

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

  2. 统一异常处理

  3. 统一数据格式返回

一. 用户登录权限效验

1.1 最初用户登录验证

最初用户登录验证的实现方法:每个方法中都有相同的用户登录验证权限,它的缺点是:

  1. 每个方法中都要单独写用户登录验证的方法,即使封装成公共方法,也一样要传参调用和在方法中进行判断。
  2. 添加控制器越多,调用用户登录验证的方法也越多,这样就增加了后期的修改成本和维护成本。
  3. 这些用户登录验证的方法和接下来要实现的业务几何没有任何关联,但每个方法中都要写一遍。

1.2 Spring AOP 用户统一登录验证的问题

统⼀的用户登录验证,我们想到的第⼀个实现方案是 Spring AOP 前置通知或环绕通知来实现,前面一篇文章已作出了代码详解

如果要在以上 Spring AOP 的切面中实现用户登录权限效验的功能,有以下两个问题:

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

1.3 Spring 拦截器

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

  1. 创建自定义拦截器,实现 HandlerInterceptor 接口的 preHandle(执行具体方法之前的预处理)方法。(实现自定义拦截器,实现 HandlerInterceptor 重写 preHandle (返回 boolean )方法。)
  2. 将自定义拦截器加入 WebMvcConfigureraddInterceptors 方法中。(配置拦截规则)
  • 先模拟三个路由网址
    在这里插入图片描述
  • 实现自定义拦截器
    在这里插入图片描述
  • 配置拦截规则
    在这里插入图片描述
  • addPathPatterns:表示需要拦截的 URL,“**”表示拦截任意方法(也就是所有方法)。
  • excludePathPatterns:表示需要排除的 URL

于是可以看到不拦截 /user/login 路由和 /user/reg 路由,拦截了 userinfo 路由

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在浏览器 URL 中挂载 session 看看

在这里插入图片描述

再来访问 getinfo

在这里插入图片描述

此处就说明了 session 成功挂载上了,session 是依赖浏览器里面的 cookie 来实现存储的,当登录成功写入 session 之后,拦截的页面可正常访问,如果此时再换个浏览器访问就访问不到

1.4 拦截器实现原理

正常情况下的调⽤顺序:

在这里插入图片描述

然而有了拦截器之后,会在调用 Controller 之前进行相应的业务处理,执行的流程如下图所示:

在这里插入图片描述

所有的 Controller 执行都会通过⼀个调度器 DispatcherServlet 来实现,这⼀点可以从 Spring Boot 控制台的打印信息看出

在这里插入图片描述

而所有方法都会执行 DispatcherServlet 中的 doDispatch 调度方法

从源码可以看出在开始执行 Controller 之前,会先调用预处理方法 applyPreHandle

从源码可以看出,在 applyPreHandle 中会获取所有的拦截器 HandlerInterceptor 并执行拦截器中的 preHandle 方法,这样就会和咱们前面定义的拦截器对应上了

此时用户登录权限的验证方法就会执行


二.统一异常处理

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

在这里插入图片描述

以上方法表示,如果出现了异常就返回给前端⼀个 HashMap 的对象,其中包含的字段如代码中定义的那样。

我们可以针对不同的异常,返回不同的结果,如以下代码所示:

@ControllerAdvice
@ResponseBody
public class ExceptionAdvice {
	 @ExceptionHandler(Exception.class)
	 public Object exceptionAdvice(Exception e) {
		 HashMap<String, Object> result = new HashMap<>();
		 result.put("success", -1);
		 result.put("message", "总的异常信息:" + e.getMessage());
		 result.put("data", null);
		 return result;
	 }
	 @ExceptionHandler(NullPointerException.class)
	 public Object nullPointerexceptionAdvice(NullPointerException e) {
		 HashMap<String, Object> result = new HashMap<>();
		 result.put("success", -1);
		 result.put("message", "空指针异常:" + e.getMessage());
		 result.put("data", null);
		 return result;
	 }
}

三.统一数据返回格式

3.1 为什么需要统⼀数据返回格式?

统⼀数据返回格式的优点有很多,比如以下几个:

  1. 方便前端程序员更好的接收和解析后端数据接⼝返回的数据。
  2. 降低前端程序员和后端程序员的沟通成本,按照某个格式实现就⾏了,因为所有接口都是这样返回的。
  3. 有利于项目统一数据的维护和修改。
  4. 有利于后端技术部门的统一规范的标准制定,不会出现稀奇古怪的返回内容

3.2 统一数据返回格式的实现

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

在这里插入图片描述

  • 20
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Redamancy丶早晚

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值