Spring Boot 统一功能处理

这篇具有很好参考价值的文章主要介绍了Spring Boot 统一功能处理。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

✏️作者:银河罐头
📋系列专栏:JavaEE

🌲“种一棵树最好的时间是十年前,其次是现在”


Spring Boot 统⼀功能处理模块,也是 AOP 的实战环节。

⽤户登录权限效验

Spring Boot 拦截器

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

  1. 创建⾃定义拦截器,实现 HandlerInterceptor 接⼝的 preHandle(执⾏具体⽅法之前的预处理)方 法。
  2. 将⾃定义拦截器加⼊ WebMvcConfigurer 的 addInterceptors ⽅法中。

自定义拦截器

Spring Boot 统一功能处理

public class LoginInterceptor implements HandlerInterceptor {
    // 调用目标方法之前执行的方法
    // 此方法会返回一个 boolean 类型的值,
    // 返回 true 表示拦截器验证成功,继续走后续流程,执行目标方法;
    // 返回 false 表示拦截器验证失败,后续流程和目标方法不用执行
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        //用户登录校验
        HttpSession session = request.getSession(false);
        if(session != null && session.getAttribute("session_userinfo") != null){
            return true;
        }
        //        response.setStatus(401);
        response.setContentType("application/json;charset=utf8");
//        response.setCharacterEncoding("utf8");
        response.getWriter().println("{\"code\": -1, \"msg\": \"登录失败\", \"data\": \"\"}");
        return false;
    }
}

将自定义拦截器加入到系统配置

@Configuration
public class MyConfig implements WebMvcConfigurer {
    @Autowired
    private LoginInterceptor loginInterceptor;
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(loginInterceptor)
                .addPathPatterns("/**")// 拦截所有 url
                .excludePathPatterns("/user/login") // 排除 登录 不拦截
                .excludePathPatterns("/user/reg") // 排除 注册 不拦截
                .excludePathPatterns("/image/**")
        ;
    }
}

验证下拦截功能:

@RestController
@RequestMapping("/user")
public class UserController {
    @RequestMapping("/login")
    public String login(){
        return "login";
    }

    @RequestMapping("/index")
    public String index(){
        return "index";
    }

    @RequestMapping("/reg")
    public String reg(){
        return "reg";
    }
}

Spring Boot 统一功能处理

Spring Boot 统一功能处理

Spring Boot 统一功能处理

login() 和 reg() 没有被拦截,index() 被拦截。

拦截器实现原理

正常情况下的调⽤顺序:

Spring Boot 统一功能处理

然⽽有了拦截器之后,会在调⽤ Controller 之前进⾏相应的业务处理,执⾏的流程如下图所示:

Spring Boot 统一功能处理

Spring Boot 拦截器的实现原理是基于 Spring MVC 框架的拦截器机制,当客户端发送请求时,请求会经过一系列的组件处理,其中就包括拦截器。

统一异常处理

如果不做统一的异常处理,后端抛异常,返回前端的状态码就是 500。

如果不想返回的是这个 500 状态码,可以对异常做统一处理,降低前端程序员和后端程序员的沟通成本。

创建一个异常处理类

@ControllerAdvice// 随着 spring Boot 项目的启动而启动 + 检测 controller 的异常
public class MyExceptionAdvice {

}

创建异常监测的类和处理的方法

@ControllerAdvice
@ResponseBody
public class MyExceptionAdvice {
    @ExceptionHandler(NullPointerException.class)
    public HashMap<String, Object> doNullPointerException(NullPointerException e){
        HashMap<String, Object> result = new HashMap<>();
        result.put("code",-1);
        result.put("msg","空指针: " + e.getMessage());
        result.put("data",null);
        return result;
    }
}
@RestController
@RequestMapping("/user")
public class UserController {
    @RequestMapping("/login")
    public int login(){
        Object obj = null;
        System.out.println(obj.hashCode());
        return 1;
    }
}

Spring Boot 统一功能处理

但是这里只是处理了"空指针"异常,如果有其他的异常呢?比如"算数异常"

@RestController
@RequestMapping("/user")
public class UserController {
    @RequestMapping("/login")
    public int login(){
        int num = 10/0;
        return 1;
    }
}

Spring Boot 统一功能处理

有一个办法,是再去写一个处理"算数异常"的类,但是异常类型太多,这样很麻烦。

可以写一个类,处理所有异常的父类-“Exception”.

@ControllerAdvice
@ResponseBody
public class MyExceptionAdvice {
    @ExceptionHandler(Exception.class)
    public HashMap<String, Object> doException(Exception e){
        HashMap<String, Object> result = new HashMap<>();
        result.put("code",-1);
        result.put("msg","Exception: " + e.getMessage());
        result.put("data",null);
        return result;
    }
}

Spring Boot 统一功能处理

  • 如果子类异常(空指针)和父类异常都存在的情况下,出现"空指针"的情况会触发子类还是父类异常处理?
@ControllerAdvice
@ResponseBody
public class MyExceptionAdvice {
    @ExceptionHandler(NullPointerException.class)
    public HashMap<String, Object> doNullPointerException(NullPointerException e){
        HashMap<String, Object> result = new HashMap<>();
        result.put("code",-1);
        result.put("msg","空指针: " + e.getMessage());
        result.put("data",null);
        return result;
    }

    @ExceptionHandler(Exception.class)
    public HashMap<String, Object> doException(Exception e){
        HashMap<String, Object> result = new HashMap<>();
        result.put("code",-1);
        result.put("msg","Exception: " + e.getMessage());
        result.put("data",null);
        return result;
    }
}
@RestController
@RequestMapping("/user")
public class UserController {
    @RequestMapping("/login")
    public int login(){
        Object obj = null;
        System.out.println(obj.hashCode());
        return 1;
    }
    @RequestMapping("/login2")
    public int login2(){
        int num = 10/0;
        return 1;
    }
}

Spring Boot 统一功能处理

优先触发子类异常。

统一数据返回格式

强制性统一数据返回。(在返回数据之前进行数据重写)

统⼀数据返回格式的优点:⽅便前端程序员更好的接收和解析后端数据接⼝返回的数据。 降低前端程序员和后端程序员的沟通成本,按照某个格式实现就⾏了,因为所有接⼝都是这样返回 的。有利于后端技术部⻔的统⼀规范的标准制定,不会出现稀奇古怪的返回内容。

//统一数据格式处理
@ControllerAdvice
public class ResponseAdvice implements ResponseBodyAdvice {

    @Override
    public boolean supports(MethodParameter returnType, Class converterType) {
        return true;// true => 调用 beforeBodyWrite() 方法
    }

    //返回数据之前进行重写
    @Override
    public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {
        // 假定标准格式是 HashMap<String, Object> -> {code, msg, data}
        if(body instanceof HashMap) {
            return body;
        }
        HashMap<String, Object> result = new HashMap<>();
        result.put("code", 200);
        result.put("msg","");
        result.put("data",body);
        return result;
    }
}
@RestController
@RequestMapping("/user")
public class UserController {
    @RequestMapping("/login")
    public int login(){
        return 1;
    }
    @RequestMapping("/login2")
    public int login2(){
        return 1;
    }

    @RequestMapping("/reg")
    public HashMap<String, Object> reg(){
        HashMap<String, Object> result = new HashMap<>();
        result.put("code",200);
        result.put("msg","");
        result.put("data",1);
        return result;
    }
}

Spring Boot 统一功能处理

Spring Boot 统一功能处理

保证始终返回的都是标准的格式。

StringHttpMessageConverter

  • 再来看一个例子:
@RequestMapping("/sayHi")
public String sayHi(){
    return "say hi";
}

Spring Boot 统一功能处理

//默认异常处理(当具体的异常匹配不到时,会走这个方法)
@ExceptionHandler(Exception.class)
public HashMap<String, Object> doException(Exception e){
    HashMap<String, Object> result = new HashMap<>();
    result.put("code",-1);
    result.put("msg","Exception: " + e.getMessage());
    result.put("data",null);
    return result;
}

返回流程:

1.返回 String

2.统一数据格式处理:String -> HashMap

3.HashMap -> application/json 给前端

报错就是 第 3 步出错了。

Spring Boot 统一功能处理

到 第 3 步之后就会对原 body 的类型进行判断:

1.是 String -> StringHttpMessageConverter 进行类型转换

就这个例子而言,它就会用第 2 步得到的 HashMap -> String, 就出现类型转换异常。

2.非 String -> HttpMessageConverter 进行类型转换

解决方案:

1.将 StringHttpMessageConverter 转化器去掉。

package com.example.demo.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import java.util.List;

@Configuration
public class MyConfig implements WebMvcConfigurer {
    @Override
    public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
        converters.removeIf(converter->converter instanceof StringHttpMessageConverter);
    }
}

2.在统一数据重写时,单独处理 String 类型,让其返回一个 String 类型而不是 HashMap.

//返回数据之前进行重写
    @SneakyThrows
    @Override
    public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {
       // 假定标准格式是 HashMap<String, Object> -> {code, msg, data}
        if(body instanceof HashMap) {
            return body;
        }
        HashMap<String, Object> result = new HashMap<>();
        result.put("code", 200);
        result.put("msg","");
        result.put("data",body);
        if(body instanceof String){
//            return "{\"code\": 200, \"msg\": \"\", \"data\": \"" + body + "\"}";
            //将对象转换成 json 字符串
            return objectMapper.writeValueAsString(result);
        }
        return result;
    }

Spring Boot 统一功能处理文章来源地址https://www.toymoban.com/news/detail-475083.html

到了这里,关于Spring Boot 统一功能处理的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【Spring Boot】拦截器与统一功能处理:统一登录验证、统一异常处理与统一数据返回格式

     Spring AOP是一个基于面向切面编程的框架,用于将横切性关注点(如日志记录、事务管理)与业务逻辑分离,通过代理对象将这些关注点织入到目标对象的方法执行前后、抛出异常或返回结果时等特定位置执行,从而提高程序的可复用性、可维护性和灵活性。但使用原生Sp

    2024年02月16日
    浏览(45)
  • 【Spring Boot统一功能处理】统一异常处理,统一的返回格式,@ControllerAdvice简单分析,即将走进SSM项目的大门! ! !

    前言: 大家好,我是 良辰丫 ,在上一篇文章中我们已经学习了一些统一功能处理的相关知识,今天我们继续深入学习这些知识,主要学习统一异常处理,统一的返回格式,@ControllerAdvice简单分析.💌💌💌 🧑个人主页:良辰针不戳 📖所属专栏:javaEE进阶篇之框架学习 🍎励志语句:生

    2024年02月16日
    浏览(39)
  • Spring Boot 统一功能处理(拦截器实现用户登录权限的统一校验、统一异常返回、统一数据格式返回)

    目录 1. 用户登录权限校验 1.1 最初用户登录权限效验 1.2 Spring AOP 用户统⼀登录验证 1.3 Spring 拦截器 (1)创建自定义拦截器 (2)将自定义拦截器添加到系统配置中,并设置拦截的规则 1.4 练习:登录拦截器 (1)实现 UserController 实体类 (2)返回的登录页面:login.html (3)实

    2024年02月12日
    浏览(48)
  • Spring Boot 优雅实现统一数据返回格式+统一异常处理+统一日志处理

            在我们的项目开发中,我们都会对数据返回格式进行统一的处理,这样可以方便前端人员取数据,当然除了正常流程的数据返回格式需要统一以外,我们也需要对异常的情况进行统一的处理,以及项目必备的日志。         在项目开发中返回的是json格式的数据

    2024年01月19日
    浏览(42)
  • Spring Boot实现统一异常处理的技术解析

    引言 在软件开发过程中,异常处理是非常重要的一环。一个好的异常处理机制可以帮助我们更好地定位问题,提高代码的可维护性和稳定性。Spring Boot作为一款轻量级的Java开发框架,提供了一种简单而高效的方式来实现统一异常处理。本文将详细介绍如何使用Spring Boot实现统

    2024年01月21日
    浏览(40)
  • Spring Boot 统一数据返回格式 分析 和 处理

    目录 实现统一数据格式  测试   原因分析  解决方案 🎥 个人主页:Dikz12 📕格言:吾愚多不敏,而愿加学 欢迎大家👍点赞✍评论⭐收藏 统⼀的数据返回格式使⽤ @ControllerAdvice 和 ResponseBodyAdvice 的⽅式实现; @ControllerAdvice : 表⽰控制器通知类. 比如:添加类 ResponseAdvic

    2024年04月08日
    浏览(47)
  • Spring统一功能处理

    获取参数复杂 AOP的规则相对简单 2.1.1. 自定义拦截器 新建interceptor文件夹 2.1.2. 将自定义拦截器加入到系统配置 新建config文件夹 2.1.3. 业务代码 方法1 方法2 2.3.1. 总体思路 2.3.2. 部分源码分析 拦截器是基于AOP实现的 (AOP基于动态代理(JDK|CGLIB)) 参考上一节 拦截器的应用 对于下面

    2024年02月11日
    浏览(29)
  • 【Spring Boot 使用Filter统一处理请求数据转换】

    Spring Boot Filter 使用场景 身份验证和授权 场景描述: 在用户访问应用程序的敏感资源之前,需要验证用户的身份并授权用户访问特定的内容。 实现方式: 使用Filter拦截请求,检查HTTP请求中的身份验证令牌(如JWT),并确定用户是否具有执行操作的权限。 日志记录和审计 场景

    2024年02月21日
    浏览(43)
  • 【Spring】SpringBoot 统一功能处理

    在日常使用 Spring 框架进行开发的时候,对于一些板块来说,可能需要实现一个相同的功能,这个功能可以是验证你的登录信息,也可以是其他的,但是由于各个板块实现这个功能的代码逻辑都是相同的,如果一个板块一个板块进行添加的话,开发效率就会很低,所以 Spring

    2024年01月18日
    浏览(38)
  • Spring 统一功能处理(拦截器)

    SpringBoot统一功能处理。也就是AOP的具体实现。 最原始的用户登录验证方法,我们通过封装了一个方法来判断用户是否登录,但如果实现的功能多了,那么每一个需要登录的功能都要在对应的接口中来调用这个函数来判读是否登录。 上面的代码虽然已经封装成了方法,但是如

    2024年02月03日
    浏览(53)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包