0


Spring Boot——统一功能处理

1. 拦截器

拦截器主要用来拦截用户的请求,在指定方法前后,根据业务需要执行设定好的代码,也就是提前定义一些逻辑,在用户的请求响应前后执行,也可以在用户请求前阻止其执行,例如登录操作,只有登录成功之后用户才可以访问应用页面,这时就可以使用拦截器来拦截前端发来的请求,判断 session 中是否有登录用户的信息,如果没有就拦截,有的话就放行

1.1. 快速开始

首先需要定义拦截器,定义好之后注册并配置拦截器

自定义拦截器需要实现 HandlerInterceptor 接口,并重写它的方法

  1. @Slf4j
  2. @Component
  3. public class LoginInterceptor implements HandlerInterceptor {
  4. @Override
  5. public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
  6. log.info("preHandle...");
  7. return true;
  8. }
  9. @Override
  10. public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
  11. log.info("postHandle...");
  12. }
  13. @Override
  14. public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
  15. log.info("afterCompletion...");
  16. }
  17. }

注册配置拦截器需要实现 WebMvcConfigurer 接口,并重写 addInterceptors 方法

  1. @Configuration
  2. public class WebConfig implements WebMvcConfigurer {
  3. @Autowired
  4. private LoginInterceptor loginInterceptor;
  5. @Override
  6. public void addInterceptors(InterceptorRegistry registry) {
  7. registry.addInterceptor(loginInterceptor)//注册拦截器
  8. .addPathPatterns("/**")//对哪些路径生效
  9. .excludePathPatterns("/user/login");//对哪些路径不生效
  10. }
  11. }

拦截路径

含义

举例

/*

一级路径

能匹配 /user,/book,/login,不能匹配 /user/login

/**

任意级路径

能匹配 /user,/user/login,/user/reg

/book/*

/book 下的一级路径

能匹配 /book/addBook,不能匹配 /book/addBook/1,/book

/book/**

/book 下的任意级路径

能匹配 /book,/book/addBook,/book/addBook/2,不能匹配 /user/login

2. 统一数据返回格式

以之前的图书管理系统为例,之前是手动封装了一层返回结果的

对于多个接口,如果都进行封装的话,肯定是非常麻烦的,所以就可以对返回格式进行统一

首先定义一个类,实现

  1. ResponseBodyAdvice

接口并重写其中的方法,然后还要加上

  1. @ControllerAdvice

注解来交给 Spring 管理

  1. @ControllerAdvice
  2. public class ResponseAdvice implements ResponseBodyAdvice {
  3. @Override
  4. public boolean supports(MethodParameter returnType, Class converterType) {
  5. return true;// false:不处理 true:处理
  6. }
  7. @Override
  8. public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {
  9. return Result.success(body);
  10. }
  11. }

来介绍一下这两个方法:

supports:用于判断是否要对该方法的返回值进行处理,可以根据返回类型等条件来自定义,false:不处理 true:处理

beforeBodyWrite:在将返回值写入响应体之前调用,可以在这里对返回值进行统一的包装或者修改

上面的代码中表示所有方法都进行处理,处理的逻辑就是再封装一层之前定义的 Result 类成功的方法

响应的 body 中也封装好了

但是有一个问题,原来封装好的类型又封装了一层

就可以加个判断,如果已经是 Result 类型的就直接返回 body

除此之外,还有一个错误,当访问更新图书的接口之后报错了,而数据库中的信息还是成功修改了

具体的报错信息是类型匹配时的错误

在 Spring 中,返回值会经过

  1. HttpMessageConverter

转换为 HTTP 响应的内容 ,字符串类型和非字符串类型的处理流程是不同的

对于

  1. String

类型的返回值,Spring 使用

  1. StringHttpMessageConverter

将其直接作为字符 串写入到 HTTP 响应中,而不会进一步封装或序列化。 非字符串类型的返回值会通过

  1. MappingJackson2HttpMessageConverter

等转换器,序列化为 JSON 字符串。

此时 body 如果是字符串类型,

  1. StringHttpMessageConverter

会尝试直接将

  1. Result.success(body)

转换为字符串,导致类型不匹配。

解决办法:

3. 统一异常处理

在之前写的代码中,每一个模块都有需要处理异常的地方,就可以把这些异常进行统一处理,统一异常处理是通过

  1. @ControllerAdvice

注解和

  1. @ExceptionHandler

注解来实现的

  1. @Slf4j
  2. @ResponseBody
  3. @ControllerAdvice
  4. public class ExceptionAdvice {
  5. @ExceptionHandler
  6. public Object handler(Exception e) {
  7. log.error("发生异常:e" + e);
  8. return Result.fail();
  9. }
  10. }

来造几个常见的异常进行演示:

还可以通过重载的方式,细分具体发生的是什么异常,通过修改 fail 方法也可以自定义返回的错误信息

不过,在测试时发现最终返回的状态码是 200,这就不太合理

可以通过

  1. @ResponseStatus

注解来设置返回的状态码,传入的参数必须是 HttpStatus 的常量

标签: spring boot 后端 java

本文转载自: https://blog.csdn.net/2202_76097976/article/details/144052096
版权归原作者 2的n次方_ 所有, 如有侵权,请联系我们删除。

“Spring Boot——统一功能处理”的评论:

还没有评论