当前位置: 首页 > news >正文

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

文章目录

  • 一、AOP实战——SpringBoot统一功能处理
    • 1.1、使用拦截器实现用户登录权限的统一验证
      • 1.1.1、使用原生Spring AOP实现统一拦截的难点
      • 1.1.2、Spring 拦截器
        • 1.1.2.1、Spring拦截器 使用步骤
        • 1.1.2.2、拦截器实现原理
    • 1.2、统一数据格式返回
      • 1.2.1、为什么要返回统一的数据格式
      • 1.2.2、返回统一数据格式的步骤
        • 1.2.2.1、创建一个类,并在类上添加注解@ControllerAdvice
        • 1.2.2.2、且该类要实现接口ResponseBodyAdvice,并重写supports、beforeBodyWrite方法(统一对象是在此方法中实现的)
      • 1.2.3、最终版统一数据格式返回
    • 1.3、统一异常处理
      • 1.3.1、感知系统异常
      • 1.3.2、统一返回异常对象。

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

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

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

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 24.8.5数据结构|栈
  • vscode ssh-remote 疑似内存泄漏问题
  • 两轮电动车行业竞争激烈,九号公司如何破局
  • uniapp点击图片预览,关闭预览图片后自动触发onshow生命周期,怎么解决?
  • Windows 环境使用 Docker 安装 ES Kibana 8.12.2 及analysis-ik插件
  • 【黑马】MyBatis
  • pythonUI自动化008::allure测试报告(安装及应用)
  • sed命令笔记
  • 基于SpringBoot+Vue校园失物招领系统的设计与实现
  • 【将Python程序打包成一个可执行文件】
  • Spring Data JPA 自动创建时间的相关注解和用法
  • vue前后端交互学习问题记录2
  • LeetCode 第二十三天 2024.8.9
  • NPM使用教程
  • Halcon玩转机器视觉专栏特殊声明
  • Codepen 每日精选(2018-3-25)
  • Git的一些常用操作
  • iOS动画编程-View动画[ 1 ] 基础View动画
  • Java多态
  • PAT A1017 优先队列
  • php面试题 汇集2
  • TypeScript实现数据结构(一)栈,队列,链表
  • ubuntu 下nginx安装 并支持https协议
  • 程序员最讨厌的9句话,你可有补充?
  • 第十八天-企业应用架构模式-基本模式
  • 机器人定位导航技术 激光SLAM与视觉SLAM谁更胜一筹?
  • 名企6年Java程序员的工作总结,写给在迷茫中的你!
  • 那些年我们用过的显示性能指标
  • 浅谈web中前端模板引擎的使用
  • 悄悄地说一个bug
  • 深入浅出Node.js
  • 使用API自动生成工具优化前端工作流
  • 收藏好这篇,别再只说“数据劫持”了
  • 你对linux中grep命令知道多少?
  • ionic入门之数据绑定显示-1
  • ​草莓熊python turtle绘图代码(玫瑰花版)附源代码
  • # wps必须要登录激活才能使用吗?
  • # 睡眠3秒_床上这样睡觉的人,睡眠质量多半不好
  • #100天计划# 2013年9月29日
  • #1015 : KMP算法
  • $分析了六十多年间100万字的政府工作报告,我看到了这样的变迁
  • (21)起落架/可伸缩相机支架
  • (Matlab)使用竞争神经网络实现数据聚类
  • (webRTC、RecordRTC):navigator.mediaDevices undefined
  • (二)测试工具
  • (附源码)spring boot校园健康监测管理系统 毕业设计 151047
  • (附源码)基于SpringBoot和Vue的厨到家服务平台的设计与实现 毕业设计 063133
  • (论文阅读31/100)Stacked hourglass networks for human pose estimation
  • (南京观海微电子)——示波器使用介绍
  • (四)React组件、useState、组件样式
  • (未解决)jmeter报错之“请在微信客户端打开链接”
  • (一)appium-desktop定位元素原理
  • (转)Linux下编译安装log4cxx
  • (转)自己动手搭建Nginx+memcache+xdebug+php运行环境绿色版 For windows版
  • (自适应手机端)行业协会机构网站模板