浅谈 Spring AOP框架 (2)——Spring统一功能处理

一、AOP实战——SpringBoot统一功能处理

1.1、使用拦截器实现用户登录权限的统一验证

以前进行用户登陆权限的验证方法:

@RestController
@Reques tMapping("/user")
public class UserController {
/**
*某方法1
*/
@RequestMapping("/m1")
public object method (HttpServletRequest request) {
	  //有session 就获取,没有不会创建
	  HttpSession session = request. getSession(false);
	  if (session != null && session.getAttribute ("userinfo") != null) {
	  //说明已经登录,业务处理
	  return true;
	} else {
	//未登录
	  return false;
	  }
}
/**
*某方法2
*/
@RequestMapping ("/m2")
public object method2(HttpServletRequest request) {
  //有session 就获取,没有不会创建
  HttpSession session = request.getSession(false);
  if (session != null && sess ion.getAttribute("userinfo") != null) {
  //说明已经登录,业务处理
  return true;
} else {
//未登录
  return false;
  }
}
// 其他方法...

1.1.1、使用原生Spring AOP实现统一拦截的难点

前面已经学习了AOP知识知道可以通过AOP规则拦截未登录页面(除了拦截接口,还有前端页面…),但是使用原生的Spring AOP实现同意拦截有一些难点:
(1)、切点的拦截表达式规则复杂,难以定义
(2)、在切面类里拿到 HttpSession类 比较难

1.1.2、Spring 拦截器

Spring 引入 拦截器 解决Spring AOP上述所说的这些问题。

1.1.2.1、Spring拦截器 使用步骤

(1)、自定义一个拦截器类(随意命名),该类必须实现 HandlerInterceptor,并且该自定义类里必须重写preHandle()方法。
在这里插入图片描述
(2)、将⾃定义拦截器加⼊到系统配置
再自定义一个配置类(命名随意),此配置类必须实现 WebMvcConfigurer ,并且当前这个配置类是需要随着Spring的启动而启动,因此配置类必须加上注解@Configuration,然后配置类里必须重写addInterceptors()方法,然后将上面自定义的拦截类加入到该配置类中,此时我们自定义的拦截类才能生效。
在这里插入图片描述

早期的项目数据交互流程:
在这里插入图片描述

拦截器出现之后:
在这里插入图片描述

1.1.2.2、拦截器实现原理

那为什么拦截器可以在controller执行之前先执行??

所有的Controller执行时都会通过一个调度器 DispatcherServlet 来实现:
在这里插入图片描述
而程序中所有方法都会执行 DispatcherServlet 中的 doDispatch() 调度方法,doDispatch()源码中在开始执行 Controller 之前,首先是调用了预处理方法 applyPreHandle(),而applyPreHandle的源码中,首先是获取到所有的拦截器HandlerInterceptor,并执行拦截器中的preHandle()方法,因此拦截器的预处理会比Controller先执行。

如果大家感兴趣 doDispatch() 、applyPreHandle的源码的话,可以自己去搜索看看,由于篇幅太长,我就不放在这里了。

1.2、统一数据格式返回

1.2.1、为什么要返回统一的数据格式

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

1.2.2、返回统一数据格式的步骤

1.2.2.1、创建一个类,并在类上添加注解@ControllerAdvice

在这里插入图片描述

1.2.2.2、且该类要实现接口ResponseBodyAdvice,并重写supports、beforeBodyWrite方法(统一对象是在此方法中实现的)

例子:
在这里插入图片描述

num接口下前端接收到的数据格式:
test接口下前端接收到的数据格式:
在这里插入图片描述

当程序中设置了统一的数据返回格式后:
在这里插入图片描述

注意一个知识点
在这里插入图片描述
那为什么会出现这个异常信息呢?其实是因为:只要你的返回类型不是String,都能被统一数据返回格式转成标准的json格式返回给前端。String和其他类型都不一样:
在这里插入图片描述
所以我们在统一返回时,对于String,不能再借助Spring把HashMap转成json字符串格式了,需要对String进行单独的处理:先判断当前body是否为String,如果是,使用jackson将HashMap手动转为json字符串才行。
在这里插入图片描述
在这里插入图片描述
但是其实我们的统一数据返回格式还有其他问题:
在这里插入图片描述

1.2.3、最终版统一数据格式返回

待补充。

1.3、统一异常处理

1.3.1、感知系统异常

如何感知到异常??使用注解:@ControllerAdvice 感知到异常:即自己定义的异常类上加上该注解,加上该注解之后,当前类会随着项目的启动而启动。注解@ControllerAdvice表示控制器通知类。

然后该自定义的异常类里的方法需要加上注解 @ExceptionHandler(异常管理器),加上这个注解之后,相当于订阅了系统的异常事件了。如果项目出了异常,加了该注解的方法就能够获取到项目的异常。 @ExceptionHandler(这里面写的是什么异常的反射,就能拿到什么异常),比如说:@ExceptionHandler(Exception.class) 那就能拿到所有异常,如果是:@ExceptionHandler(IOException.class) 就能拿到IO产生的异常…

在这里插入图片描述
但其实虽然我们定义了统一处理的异常类,上述图片我们定义了空指针异常统一处理、算数异常统一处理,但是其实如果程序代码中若还出现了其他异常如:越界异常、栈溢出异常…这些异常我们还是没办法统一处理到,这该怎么办?要么继续添加定义该异常的统一异常处理方法,要么定义一个保底的异常方法。比较推荐第二种办法。
在这里插入图片描述

1.3.2、统一返回异常对象。

感知到异常之后,再将异常封装成统一对象返回给前端。

上述项目例子链接,自行下载练习。

  • 8
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值