Spring统一功能

一、什么是统一功能

  1. 什么是统一功能:大家都要做的事情,每一个接口都要执行这个操作
  2. 统一功能包含两个部分
    • (1)Spring本身提供的统一功能
    • (2)Spring本身并没有提供某个统一功能,但我们又需要,如何去自定义

二、拦截器

2.1 什么是拦截器

  1. 什么是拦截器:主要用来拦截用户的请求,在指定方法前后,根据业务需要执行预先设定的代码。
    • 统一功能之一:是Spring提供的统一功能的其中之一,可以公共地对一个信息进行处理
    • 作用维度:拦截器的作用维度是URL,像Service代码没有配置我们是拦截不了的
  2. 使用拦截器后的执行流程
    • 请求:之前请求过来,先进入Controller,如果有拦截器,是先进入拦截器看有没有需要预先执行的方法,如果有且拦截器放行了,才会去执行Controller里的代码
    • 响应:返回时,当Controller里的方法全部执行完,会被拦截器拦截,执行拦截器中设置的【响应后的代码】
      在这里插入图片描述

2.2 拦截器的使用

在这里插入图片描述

@Configuration
public class webConfig implements WebMvcConfigurer { //WebMvcConfigurer是一个Mvc的配置器
    @Autowired
    private LoginInterceptor loginInterceptor;

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(loginInterceptor)  //添加拦截器
                .addPathPatterns("/**")	   //要拦截哪些方法
                .excludePathPatterns("");  //哪些不进行拦截
    }
}
@Component
@Slf4j
public class LoginInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        log.info("目标方法执行前");
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        log.info("目标方法执行后");
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        HandlerInterceptor.super.afterCompletion(request, response, handler, ex);
    }
}
  1. 关于路径的定义:addPathPatterns 和 excludePathPatterns里放的是网络路径,而非文件路径
    • /*:一级路径
      • 能匹配/user、/book
      • 不能匹配/user/login
    • /**:任意级路径
      • 能匹配/user、/user/login、/book/addBook,所有路径都能匹配
    • /book/*:/book下的一级路径
      • 能匹配/book/addBook
      • 不能匹配/book/addBook/1,/book
    • /book/**:/book下的任意级路径
      • 能匹配/book、/book/addBook
      • 不能匹配/user/login

2.3 案例:不拦截前端的请求

  1. 问题描述
    • 因为此时除了【/user/login】这个后端请求,所有的请求都被拦截了,这包括了前端的所有请求(甚至图片的访问都被拦截了)
    • 比如我们无法通过在浏览器输入【http://127.0.0.1:8080/login.html】来访问这个网页并进行后续的登录操作
@Configuration
public class webConfig implements WebMvcConfigurer {
    @Autowired
    private LoginInterceptor loginInterceptor;

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(loginInterceptor)
                .addPathPatterns("/**")
                .excludePathPatterns("/user/login");
    }
}
  1. 解决方法:把前端的访问路径通过【excludePathPatterns()】排除掉
    在这里插入图片描述
    在这里插入图片描述
  2. 关于excludePathPatterns()的其他写法
    在这里插入图片描述

2.4 拦截器是如何实现的 ---- >分析DispatcherServlet源码分析

  1. 源码如何阅读:找核心代码,不要钻牛角尖。一行一行地细细研究,很快就会忘记当前在哪了。
    • 阅读方法:切忌从头到尾一行一行地去读代码,一点一点去研究,一定要找到关键代码后,在宏观上对整个流程或整个原理有一个认识后,有时间再去看里面的细节
    • 快捷键:如果我们看调用代码时,忘记了前后调用的顺序,可以通过下面两个快捷键来操作
      • ctrl + [:回到上一步操作
      • ctrl + ]:来到下一步操作
  2. 步骤
    • 程序启动后,拦截器会初始化DispatcherServlet
      在这里插入图片描述
      在这里插入图片描述

    • DispatcherServlet的 init 阶段
      在这里插入图片描述
      在这里插入图片描述
      在这里插入图片描述

    • DispatcherServlet的 service 阶段
      在这里插入图片描述
      在这里插入图片描述
      在这里插入图片描述

    • DispatcherServlet的 destory 阶段

三、适配器模式

  1. 什么是适配器模式
    在这里插入图片描述
    在这里插入图片描述

  2. 适配器模式的实现

    • 此处我们模拟Slf4j:@Slif4j既是一个典型的模型模式,也是一个适配器模式
      • 一个框架用到的模式是非常多的,可能源码的短短几行代码就能体现出2,3种设计模式
    • 代码
      • 为什么用户不能直接调log4j和slf4j:不能保证所有的人都用所有的日志框架,项目之间可能会有冲突,需要有一个门面
        在这里插入图片描述
  3. 应用场景:版本升级

    • 适配器模式是一种补偿模式,不是一开始就有的,是后期设计上的缺陷没办法修改了的打补丁式的无奈之举
    • 所以适配器的应用场景主要是对正在运行的代码进行改造,并且希望复用原有代码实现新的功能,比如版本升级等

四、统一数据返回格式

  1. 效果:使每一个接口返回的数据都是同种格式的

  2. 实现方法:使用@ControllerAdvice注解 + ResponseBodyAdvice接口 + 重写两个方法
    在这里插入图片描述

  3. 当前代码存在的问题
    在这里插入图片描述
    在这里插入图片描述

  4. 为什么返回结果为String时,后端无法正确执行
    在这里插入图片描述
    在这里插入图片描述

  5. 上述问题的解决方法
    在这里插入图片描述

  6. 为什么用了ObjectMapper后,可以解决String的问题
    在这里插入图片描述

  7. 统一数据返回格式的优点

    • 由于返回的数据都变成了Result,方便前后端沟通,前端人员知道返回的数据是什么样的
    • 后端代码不需要太多的改动,就可以统一返回格式

五、统一异常

  1. 为什么要有统一异常:自己的错误自己知道即可,不给外界知道

    • 对于后端而言:我们不希望把一些诸如空指针的错误放给前端看
    • 对于前端而言:也希望不给用户看太细致的错误,而是统一跳转到一个页面,比如内部出错了,找不到页面之类的
  2. 什么时候统一异常不会生效:如果代码已经手动用try-catch捕获了,就不会被我们写的【统一异常处理】捕获到了,如果没有手动捕获,才会被统一处理

  3. 针对的对象:主要针对的是运行时异常

  4. 代码

    • 固定的三个注解:@ResponseBody、@ControllerAdvice、@ExceptionHandler
    • @Slf4j:建议加上日志,方便后续找错
      在这里插入图片描述
  5. @ControllerAdvice注解分析
    在这里插入图片描述

  6. 为什么统一异常代码能生效
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

  7. 如何阅读源码:注意源码的版本匹配

    • 方式一:IDEA上点击Download Source
    • 方式二: 去Spring的github上查看

六、案例:在图书管理系统使用统一功能

  1. 登录:登录没有进行拦截,所以没有连接失败的情况(不需要写error),只需要更改前端代码即可
    在这里插入图片描述
  2. 返回图书列表
    在这里插入图片描述
  3. 添加图书
    在这里插入图片描述
  • 31
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值