7天学完Spring:AOP实战,SpringMVC统一处理

2023-11-08

前言

接下来是 Spring Boot 统一功能处理模块了,也是 AOP 的实战环节,要实现的课程目标有以下 3 个:

  1. 统一用户登录权限验证;
  2. 统一数据格式返回;
  3. 统一异常处理。

一丶用户登录权限效验

用户登录权限的发展从之前每个方法中自己验证用户登录权限,到现在统一的用户登录验证处理,它是 一个逐渐完善和逐渐优化的过程。

<1>最初用户登录验证

我们先来回顾一下最初用户登录验证的实现方法:

@RestController
@RequestMapping("/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 && session.getAttribute("userinfo") != null) {
            // 说明已经登录,业务处理
            return true;
       } else {
            // 未登录
            return false;
       }
   }
    // 其他方法...
}

这是我们刚开始的用法,就是刚刚学习完SpringBoot时候的用法,用Session来判断当前的登录状态。但是问题是什么呢?
1. 每个方法中都要单独写用户登录验证的方法,即使封装成公共方法,也一样要传参调用和在方法中进行判断。
2. 添加控制器越多,调用用户登录验证的方法也越多,这样就增加了后期的修改成本和维护成本。
3. 这些用户登录验证的方法和接下来要实现的业务几何没有任何关联,但每个方法中都要写一遍。

所以就很麻烦,但是小伙伴们灵机一动,诶,上节课不是学了AOP吗?刚才切面编程是处理这个问题的好手呀

<2>Spring AOP 用户统一登录验证的问题

竟我们上节课刚学,但是这里有一个问题

然后就又有小伙伴说了,我们可以这么写呀

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;
@Aspect
@Component
public class UserAspect {
    // 定义切点方法 controller 包下、子孙包下所有类的所有方法
    @Pointcut("execution(* com.example.demo.controller..*.*(..))")
    public void pointcut(){ }
    // 前置方法
    @Before("pointcut()")
    public void doBefore(){
       
   }
    
    // 环绕方法
    @Around("pointcut()")
    public Object doAround(ProceedingJoinPoint joinPoint){
        Object obj = null;
        System.out.println("Around 方法开始执行");
        try {
            // 执行拦截方法
           obj = joinPoint.proceed();
       } catch (Throwable throwable) {
            throwable.printStackTrace();
       }
        System.out.println("Around 方法结束执行");
        return obj;
   }
}

对,没错,你是判断了是否登录,但是,是有问题的!在这里插入图片描述

<3>拦截器

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

  1. 创建自定义拦截器,实现 HandlerInterceptor 接口的 preHandle(执行具体方法之前的预处理)方法。
  2. 将自定义拦截器加入 WebMvcConfigurer 的 addInterceptors 方法中。

如下
在这里插入图片描述

拦截功能演示

首先,我们原本的代码是没有登录验证的,这里先随便写一个登录功能
在这里插入图片描述
在这里插入图片描述
然后开始书写我们的拦截器
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
嗯?怎么回事?怎么回事空呢?这没有道理,但是仔细想想,我们当前的代码,是在AOP基础上书写的,然后前面的AOP代码有没有什么问题,仔细一想,好像有点!
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

<4>拦截器原理

所有的 Controller 执行都会通过一个调度器 DispatcherServlet 来实现,这一点可以从 Spring Boot 控制台的打印信息看出,如下图所示:
在这里插入图片描述
而所有方法都会执行 DispatcherServlet 中的 doDispatch 调度方法。
执行 Controller 之前,会先调用 预处理方法 applyPreHandle,而applyPreHandle 方法的实现源码如下:

boolean applyPreHandle(HttpServletRequest request, HttpServletResponse
response) throws Exception {
    for(int i = 0; i < this.interceptorList.size(); this.interceptorIndex =
i++) {
        // 获取项目中使用的拦截器 HandlerInterceptor
        HandlerInterceptor interceptor =
(HandlerInterceptor)this.interceptorList.get(i);
        if (!interceptor.preHandle(request, response, this.handler)) {
            this.triggerAfterCompletion(request, response, (Exception)null);
            return false;
       }
   }
    return true;
}

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

<5>统一访问前缀添加

这个是个挺简单的语法
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
那可能会有铁子问了,你这么搞的意义在哪里呢?还特意加个访问前缀
在这里插入图片描述

二丶统一异常处理

统一异常处理使用的是 @ControllerAdvice + @ExceptionHandler 来实现的,@ControllerAdvice 表示控制器通知类,@ExceptionHandler 是异常处理器,两个结合表示当出现异常的时候执行某个通知,也就是执行某个方法事件
此时我们给个异常事件
在这里插入图片描述
这个时候应该会有一个异常信息
在这里插入图片描述
但是此时,就很难受不是嘛?我们换种方法来写
在这里插入图片描述
这种也可以,可是就很不现实不是嘛?一个错误来一个异常?每个错误都给你加一个?
在这里插入图片描述
看我下面的写法,当前类加上@ControllerAdvice注解
在这里插入图片描述
在这里插入图片描述此时打印信息如下:
在这里插入图片描述
在这里插入图片描述

<1>重改1/0异常

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

<2>重改登录异常

所以这里修改一下登录报错的信息
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

<3>写法小梳理

在这里插入图片描述

在这里插入图片描述

三丶统一数据格式封装

<1>为什么需要统一的数据格式封装呢?

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


如果感觉有点迷的话,那就不看上面这个,看我下面的图示
在这里插入图片描述

<2>怎么实现呢?

这个不难,看我下面图示的步骤
在这里插入图片描述
然后之后返回的内容如下
在这里插入图片描述
然后到了这里,就讲完啦,不对,还有个问题要忘了说了
在这里插入图片描述
就是返回值不能是你要统一返回的不能是null值嗷

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

7天学完Spring:AOP实战,SpringMVC统一处理 的相关文章

随机推荐

  • 如何在手机上运行c语言,各位前辈这两个程序怎么在手机上运行

    该楼层疑似违规已被系统折叠 隐藏此楼查看此楼 made by ebhrz include include include include include include include global define int cfd 文件描述符
  • Python mailmerge库

    Python mailmerge库 本文使用环境 win10 python3 7 office2016 第0步 按装mailmerge pip install mailmerge 第1步 引用库 from mailmerge import
  • 测试用例设计(增量测试)

    增量测试 在执行模块测试过程中 我们主要有两点考虑 第一 如何设计一个有效的测试用例集 第二 将模块组装成工作程序的方式 第二点考虑很重要 因为它涉及模块测试用例编写的形式 可能用到的测试工具类型 模块编码和测试的顺序 生成测试用例的成本以
  • Markdown的十个常用标志符号

    Markdown 是一种轻量级的 标记语言 它的优点很多 目前也被越来越多的写作爱好者 撰稿者广泛使用 看到这里请不要被 标记 语言 所迷惑 Markdown 的语法十分简单 常用的标记符号也不超过十个 这种相对于更为复杂的HTML 标记语
  • Flutter开发之数据存储-2-文件存储(33)

    数据存储部分在移动开发中是非常重要的部分 无论是一些轻量级的数据 如用户信息 APP配置信息等 还是把需要长期存储的数据写入本地文件或者Sqlite3 都离不开数据存储 上一篇SharedPreferences的使用 今天就练习一下文件存储
  • python求平均数、方差、中位数

    CalStatistics py def getNum 获取用户不定长度的输入 nums iNumStr input 请输入数字 回车退出 while iNumStr nums append eval iNumStr iNumStr inp
  • java mysql差异导出_java 如何从零实现一个数据库差异对比工具?

    对比数据的痛苦 不知道你是否也像我一样 在快乐编写代码的时候 必须进行一些数据库的数据对比工作 诚然 一般的数据差异 比如是每一行的内容不同 市场上有比较成熟的 compare2 等对比工具 但是如果是对比数据的每一列是否相同 这个就会变得
  • 机器人教育和编程教育,家长纠结发问:该选哪一个?

    机器人教育和编程教育 家长纠结发问 该选哪一个 很多家长对于机器人教育和编程教育二者之间的关系都不太懂 究竟二者有何不同 学机器人和学编程有冲突吗 孩子要如何选择呢 我们来一一剖析 1机器人教育与编程教育的区别 涵盖范围不一 机器人教育 机
  • eclipse创建webapp 类型的maven项目

    Eclipse配置maven 配置maven的安装目录 打开Eclipse属性设置面板 Window gt Preferences gt Maven 展开Maven配置界面 选择Installations 如下图 add已经下载好的mave
  • 虚拟机配置之系统网络及防火墙配置

    1 查看网络IP和网关 一般不用修改 在此不作说明 2 配置网络IP地址 1 修改IP地址 root hadoop102 vim etc sysconfig network scripts ifcfg eth0 修改并添加为 3 配置主机名
  • C#中的数据库配置

    初用C 做项目的时候将数据库连接字符串放在注册表中 并且专门写一个窗体让用户能够修改 因为用户不可能自己到注册表中去设置 现在想来 其实没必要 在工程中添加新项 选择 应用程序配置文件 默认名是App config 里面的代码如下
  • PAT-1059 C语言竞赛

    1059 C语言竞赛 20 分 C 语言竞赛是浙江大学计算机学院主持的一个欢乐的竞赛 既然竞赛主旨是为了好玩 颁奖规则也就制定得很滑稽 0 冠军将赢得一份 神秘大奖 比如很巨大的一本学生研究论文集 1 排名为素数的学生将赢得最好的奖品 小黄
  • ECCV22 最新论文汇总(目标检测、图像分割、监督学习、GAN等)

    强烈感谢极市平台提供的论文资源 ECCV 2022 已经放榜 共有1629篇论文中选 录用率还不到20 为了让大家更快地获取和学习到计算机视觉前沿技术 作者对ECCV2022最新论文进行追踪 包括分研究方向的论文及代码汇总 本次更新的 EC
  • springboot在集成多数据源+mybatis-plus无法进行分页的BUG

    springboot在集成多数据源 mysql psql 解决多数据源mybatis plus无法进行分页的BUG 1 springboot在集成多数据源 1 1引入依赖 1 2配置yml文件 1 3创建config包 这个只要让Sprin
  • py 语法操作小计

    list只能加 a b set 只能减 a b parser 传参数 test py import argparse parser argparse ArgumentParser description Training GNN on Pa
  • Linux系统编程-终端、进程组、会话

    一 终端的概念 在UNIX系统中 用户通过终端登录系统后得到一个Shell进程 这个终端成为Shell进程的控制终端 Controlling Terminal 进程中 控制终端是保存在PCB中的信息 而fork会复制PCB中的信息 因此由S
  • 百度地图根据经纬度获取实际地理位置Api接口

    1 接口URL http api map baidu com reverse geocoding v3 ak 密钥 output json coordtype bd09ll location 33 35194364323275 117 39
  • 【附源码】单点登录的两种实现方式

    概念 单点登录 Single Sign On SSO 是一种身份验证服务 允许用户使用单个标识来登录多个应用程序或系统 如下图所示 用户只需要用户名 密码登陆一次就可以访问系统A 系统B和系统C 在传统的登录方式中 用户必须为每个应用程序或
  • 目录扫描,请求重发,漏洞扫描等工具的使用

    本专栏是笔者的网络安全学习笔记 一面分享 同时作为笔记 工欲善其事必先利其器 本篇讲解一些常用工具的使用 前文链接 WAMP DVWA sqli labs 搭建 burpsuite工具抓包及Intruder暴力破解的使用 用到的工具 bur
  • 7天学完Spring:AOP实战,SpringMVC统一处理

    目录 前言 一丶用户登录权限效验 lt 1 gt 最初用户登录验证 lt 2 gt Spring AOP 用户统一登录验证的问题 lt 3 gt 拦截器 拦截功能演示 lt 4 gt 拦截器原理 lt 5 gt 统一访问前缀添加 二丶统一异