Spring Boot统一功能处理(拦截器, 统一数据返回格式, 统一异常处理)

简介: Spring Boot统一功能处理(拦截器, 统一数据返回格式, 统一异常处理)

Spring Boot 中的几种统一功能处理方式 (共性下沉, 个性提取)

  1. 拦截器
  2. 统一数据返回格式
  3. 统一异常处理

拦截器

Spring MVC 中的一个组件, 用来拦截用户的请求, 在指定方法前后, 根据业务需要执行预先设定的代码

拦截器的使用步骤

  1. 定义拦截器
  2. 注册配置拦截器

定义拦截器

实现 HandlerInterceptor 接口, 并重写其所有方法

preHandler() 方法 : 在目标方法执行前执行 , 返回值 true 表示允许继续执行目标方法, 返回值 false 表示中断目标方法的执行

postHandler() 方法 : 目标方法执行后执行


afterCompletion() 方法 : 视图渲染完成后, 执行该方法内容

@Slf4j
@Component
public class LoginInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        log.info("LoginInterceptor 目标方法执行前, 执行代码 ...");
        return true; // 默认全部放行
    }

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

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        log.info("LoginInterceptor 视图渲染完成后, 执行代码 ...");
    }
}

注册配置拦截器

实现 WebMvcConfigurer 接口, 并重写 addInterceptors 方法


@Configuration
public class WebConfig implements WebMvcConfigurer {
    // 获取拦截器对象
    @Autowired
    private LoginInterceptor loginInterceptor;

    private List<String> excludePath = Arrays.asList(
            "user/login",
            "/**/**.html",
            "/css/**",
            "/js/**",
            "/img/**"
    );
    
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        // 注册自定义拦截对象
        registry.addInterceptor(loginInterceptor)
                .addPathPatterns("/**")  // 设置拦截器的拦截路径
                .excludePathPatterns("/login.html") // 设置拦截器的放行路径
                .excludePathPatterns(excludePath);
    }
}


常见拦截路径的设置 :

/* : 一级路径

/** : 任意级路径

/book/* : /book 下的一级路径

/book/** : /book 下的任意级路径

添加拦截器之后的执行流程

  1. 添加拦截器后, 在执行每个方法之前, 都会先进行判定是否在拦截路径 / 放行路径中, 并判定是否执行拦截器内容
  2. 被拦截住的请求, 会先执行 preHandler() 方法, 该方法返回一个布尔值. 返回 true 代表该方法被放行, 返回 false 表示该方法不会被放行(即不会执行)
  3. 请求执行完毕后, 再执行 postHandler() 方法
  4. 待视图渲染完成后, 再执行afterComletion() 方法

统一数据返回格式

统一数据返回格式使用 @ControllerAdvice 和 实现 ResponseBodyAdvice 接口的方式实现

@ControllerAdvice : 表示该类为 控制器通知类

ResponseBodyAdvice 接口 : 内含 supports 方法beforeBodyWrite 方法

  • supports : 判断是否执行 beforeBodyWtire 方法, 返回值为 true 为执行, false 为不执行.
  • ResponseBodyWrite : 对 response 方法进行具体操作处理

统一数据返回格式优点

  1. 方便前端程序员接收和解析后端数据接口返回的数据
  1. 方便后端部门的统一规范的标准执行
  2. 有利于项目统一数据的维护和修改

首先得有一个数据返回格式

@Data
public class Result<T> {
    private int status;
    private String err = "";
    private T data;

    //成功
    public static <T>Result<T> success(T data) {
        Result<T> result = new Result<T>();
        result.setStatus(200);
        result.setData(data);
        return result;
    }

    // 失败
    public static <T>Result<T> fail(T data, String err) {
        Result<T> result = new Result<T>();
        result.setStatus(-1);
        result.setErr(err);
        result.setData(data);
        return result;
    }
    public static <T>Result<T> fail(String err) {
        Result<T> result = new Result<T>();
        result.setStatus(-1);
        result.setErr(err);
        return result;
    }

    // 未登录
    public static <T>Result<T> unlogin() {
        Result<T> result = new Result<T>();
        result.setStatus(-2);
        result.setErr("用户未登录");
        return result;
    }
}

统一数据格式 具体执行代码

@ControllerAdvice
public class ResponseAdvice implements ResponseBodyAdvice {
    @Autowired
    private ObjectMapper objectMapper;

    @Override
    public boolean supports(MethodParameter returnType, Class converterType) {
        // 表示对哪些请求执行 统一数据返回格式处理 (这里就简单的全部执行)
        return true;
    }

    @SneakyThrows
    @Override
    public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {
        if(body instanceof Result) {
            return body;
        }
        if(body instanceof String) {
            // 需要对 String 类型的 body 进行序列化处理 (使用 Spring Boot 内置的 Jackson 工具)
            return objectMapper.writeValueAsString(Result.success(body));
        }
        return Result.success(body);
    }
}

统一异常处理

统一异常处理使用 @ControllerAdvice@ExceptionHandler 注解实现

@ControllerAdvice : 表示控制器通知类

@ExceptionHandler : 表示异常处理器

两个注解搭配使用, 表示当出现某个异常的时候, 执行对应的方法事件

@ResponseBody
@ControllerAdvice
public class ErrorAdvice {
    @ExceptionHandler
    public Result handler(Exception e) {
        return Result.fail(e.getMessage());
    }

    @ExceptionHandler
    public Result handler(NullPointerException e) {
        return Result.fail("发生空指针异常: " + e.getMessage());
    }

    @ExceptionHandler
    public Result handler(ArithmeticException e) {
        return Result.fail("发生算数异常:" + e.getMessage());
    }
}

目录
相关文章
|
1月前
|
消息中间件 缓存 Java
手写模拟Spring Boot启动过程功能
【11月更文挑战第19天】Spring Boot自推出以来,因其简化了Spring应用的初始搭建和开发过程,迅速成为Java企业级应用开发的首选框架之一。本文将深入探讨Spring Boot的背景历史、业务场景、功能点以及底层原理,并通过Java代码手写模拟Spring Boot的启动过程,帮助读者深入理解其工作机制。
41 3
|
1月前
|
Java 开发者 微服务
手写模拟Spring Boot自动配置功能
【11月更文挑战第19天】随着微服务架构的兴起,Spring Boot作为一种快速开发框架,因其简化了Spring应用的初始搭建和开发过程,受到了广大开发者的青睐。自动配置作为Spring Boot的核心特性之一,大大减少了手动配置的工作量,提高了开发效率。
48 0
|
1月前
|
JavaScript 安全 Java
如何使用 Spring Boot 和 Ant Design Pro Vue 构建一个具有动态路由和菜单功能的前后端分离应用。
本文介绍了如何使用 Spring Boot 和 Ant Design Pro Vue 构建一个具有动态路由和菜单功能的前后端分离应用。首先,创建并配置 Spring Boot 项目,实现后端 API;然后,使用 Ant Design Pro Vue 创建前端项目,配置动态路由和菜单。通过具体案例,展示了如何快速搭建高效、易维护的项目框架。
111 62
|
17天前
|
监控 Java 数据安全/隐私保护
如何用Spring Boot实现拦截器:从入门到实践
如何用Spring Boot实现拦截器:从入门到实践
37 5
|
18天前
|
开发框架 Java UED
如何使用 Spring Boot 实现异常处理
如何使用 Spring Boot 实现异常处理
26 2
|
1月前
|
SQL 前端开发 关系型数据库
SpringBoot使用mysql查询昨天、今天、过去一周、过去半年、过去一年数据
SpringBoot使用mysql查询昨天、今天、过去一周、过去半年、过去一年数据
58 9
|
1月前
|
前端开发 Java easyexcel
SpringBoot操作Excel实现单文件上传、多文件上传、下载、读取内容等功能
SpringBoot操作Excel实现单文件上传、多文件上传、下载、读取内容等功能
91 8
|
1月前
|
JSON Java 数据格式
springboot中表字段映射中设置JSON格式字段映射
springboot中表字段映射中设置JSON格式字段映射
111 1
|
1月前
|
JavaScript 安全 Java
如何使用 Spring Boot 和 Ant Design Pro Vue 构建一个前后端分离的应用框架,实现动态路由和菜单功能
本文介绍了如何使用 Spring Boot 和 Ant Design Pro Vue 构建一个前后端分离的应用框架,实现动态路由和菜单功能。首先,确保开发环境已安装必要的工具,然后创建并配置 Spring Boot 项目,包括添加依赖和配置 Spring Security。接着,创建后端 API 和前端项目,配置动态路由和菜单。最后,运行项目并分享实践心得,帮助开发者提高开发效率和应用的可维护性。
70 2
|
1月前
|
存储 easyexcel Java
SpringBoot+EasyExcel轻松实现300万数据快速导出!
本文介绍了在项目开发中使用Apache POI进行数据导入导出的常见问题及解决方案。首先比较了HSSFWorkbook、XSSFWorkbook和SXSSFWorkbook三种传统POI版本的优缺点,然后根据数据量大小推荐了合适的使用场景。接着重点介绍了如何使用EasyExcel处理超百万数据的导入导出,包括分批查询、分批写入Excel、分批插入数据库等技术细节。通过测试,300万数据的导出用时约2分15秒,导入用时约91秒,展示了高效的数据处理能力。最后总结了公司现有做法的不足,并提出了改进方向。