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

文章目录

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

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

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

java 复制代码
@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方法(统一对象是在此方法中实现的)

例子:

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、统一返回异常对象。

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

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

相关推荐
Monodye16 分钟前
【Java】网络编程:TCP_IP协议详解(IP协议数据报文及如何解决IPv4不够的状况)
java·网络·数据结构·算法·系统架构
一丝晨光22 分钟前
逻辑运算符
java·c++·python·kotlin·c#·c·逻辑运算符
无名指的等待7121 小时前
SpringBoot中使用ElasticSearch
java·spring boot·后端
Tatakai251 小时前
Mybatis Plus分页查询返回total为0问题
java·spring·bug·mybatis
武子康1 小时前
大数据-133 - ClickHouse 基础概述 全面了解
java·大数据·分布式·clickhouse·flink·spark
.生产的驴1 小时前
SpringBoot 消息队列RabbitMQ 消费者确认机制 失败重试机制
java·spring boot·分布式·后端·rabbitmq·java-rabbitmq
Code哈哈笑2 小时前
【C++ 学习】多态的基础和原理(10)
java·c++·学习
chushiyunen2 小时前
redisController工具类
java
A_cot2 小时前
Redis 的三个并发问题及解决方案(面试题)
java·开发语言·数据库·redis·mybatis
AskHarries2 小时前
Spring Boot利用dag加速Spring beans初始化
java·spring boot·后端