快速入门 Spring Boot 拦截器、统一响应格式和全局异常处理

一、拦截器

1.1、什么是拦截器?

拦截器是 Spring 框架的核心功能之一,主要用于拦截用户请求,在目标方法执行前后根据业务需求执行预设的代码逻辑。如下图所示,在用户请求到达服务器之前,拦截器会对发起请求的客户端进行身份认证和权限验证,从而有效防止未登录用户向无权限的界面发送请求。

1.2、拦截器的使用

1.2.1、自定义拦截器
java 复制代码
@Configuration
public class LoginInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("方法调用的路径是:"+request.getRequestURI());
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("方法已完成");
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("视图渲染也完成!");
    }
}

• preHandle()方法:在目标方法执行前运行。返回 true 时继续执行后续流程,返回false则终止后续操作

• postHandle()方法:在目标方法执行后立即运行

• afterCompletion()方法:在视图渲染完成后执行

1.2.2、配置拦截器

我们需要先实现 WebMvcConfigurer 接口,并重写其中的 addInterceptors 方法。

java 复制代码
@Component
public class WebConfig implements WebMvcConfigurer{
    @Autowired
    LoginInterceptor loginInterceptor;

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(loginInterceptor)
                .addPathPatterns("/**")
                .excludePathPatterns("/login");
    }
}

上述这段代码中:

其他拦截路径配置

1.2.3、测试

让我们先分析自定义拦截器中三个重写方法的执行时序及其作用效果

对于一个正常的请求,如果不拦截的情况下:会依次输入上述三个方法

java 复制代码
@RestController
public class Test {
    @RequestMapping("/login")
    public String login(){
        return "login"+"路径登录成功";
    }
    @RequestMapping("/getUser")
    public String getUser(){
        return "getUser";
    }
}

指定两个路径,并添加拦截路径后(见目录 1.2.2):

访问未放行的路径: 127.0.0.1:8080/getUser 可看到无任何返回

访问已放行的路径: 127.0.0.1:8080/login 可以看到代码中写好的结果

二、统一响应格式

2.1、为什么要统一响应格式?

当请求通过拦截器发送至服务器后,服务器会对请求报文进行处理并返回响应报文。这个交互过程涉及前端向后端发送参数,以及后端向前端返回处理结果。当前的主要问题在于后端返回的参数类型不固定,导致前端难以处理。因此,我们需要通过统一响应机制来规范前后端之间的数据格式。

对于统一响应格式的标准设计,一个包含:

状态码:告诉前端请求处理结果

消息:可读的描述消息(包括出现什么异常、响应成功等等)

数据:真正的业务数据

时间戳:方便调试和排除问题

2.2、实现统一响应

采用 @ControllerAdvice 和 ResponseBodyAdvice实现统一数据返回格式

@ControllerAdvice 注解用于定义控制器通知类

java 复制代码
@Data
@AllArgsConstructor
@NoArgsConstructor
@ControllerAdvice
public class Result<T> {
    private Integer code;
    private String message;
    private T data;

    public static <T> Result<T> success(T data) {
        return new Result<>(200, "success", data);
    }

    public static <T> Result<T> error(String message) {
        return new Result<>(500, message, null);
    }
}
java 复制代码
@ControllerAdvice
//统一返回响应
public class ResponseAdvice implements ResponseBodyAdvice<Object> {
    private static ObjectMapper mapper = new 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){
            return mapper.writeValueAsString(Result.success(body));
        }
        return Result.success(body);
    }
}

上述代码中,使用 ObjectMapper 主要是用来对 String 类型进行 JSON 格式化,如果传递的是String类型,那么会出现类型转换错误的情况,详情见下方优秀博主的链接解释:Spring统一数据返回格式处理String类型出错解析_beforebodywrite中类型是string报错-CSDN博客

另外对于本就是Result类型的数据,就无需二次统一响应格式了,故加入两个判断条件

三、全局异常处理

3.1、快速上手

统一异常处理通过 @ControllerAdvice 和@ExceptionHandler组合实现。 @ControllerAdvice 标记控制器通知类,@ExceptionHandler用于定义异常处理方法。两者配合使用可在异常发生时触发指定的处理逻辑。

java 复制代码
@RestControllerAdvice
public class ErrorAdvice {
    @ExceptionHandler(Exception.class)
    public Result<?> handler(Exception e){
        return Result.fail(e.getMessage());
    }

    @ExceptionHandler(NullPointerException.class)  // 明确指定异常类型
    public Result<?> handler(NullPointerException e){
        return Result.fail("发生空指针异常:" + e.getMessage());
    }

    @ExceptionHandler(ArithmeticException.class)  // 明确指定异常类型
    public Result<?> handler(ArithmeticException e){
        return Result.fail("发生算数异常:" + e.getMessage());
    }
}

在下方做三个接口的示例,第一个是无错版本,第二个对于不同的报错类型

java 复制代码
@RestController
public class UserController {
    @RequestMapping(value = "aa",produces = "application/json")
    public String aa() {
        return "aa";
    }
    @RequestMapping(value = "bb",produces = "application/json")
    public String bb() {
        int a=10/0;
        return "bb";
    }
    @RequestMapping(value = "cc",produces = "application/json")
    public String cc() {
        String s=null;
        System.out.println(s.length());
        return "cc";
    }
}

3.2、测试

下面我们将依次访三个URL:

相关推荐
m0_5873830038 分钟前
广州 24 小时自助健身房解决方案技术实现与实战指南
java·spring·小程序·架构·需求分析
·云扬·1 小时前
Prompt 工程与安全:从 System 设计到注入防御
java·人工智能·安全·ai·prompt
专注仿真1 小时前
引擎扩展性与集成设计深度剖析:从 14 个扩展点到 DIS→HLA 演进之路
开发语言·算法·仿真引擎·推演引擎
Best-Wishes1 小时前
科来网络分析系统(技术交流版)使用说明书
开发语言·junit·php
代码不停2 小时前
自动化测试(java)
java·开发语言·selenium·自动化
鬼手点金4 小时前
opencode-rules 插件
java·开发语言·前端·人工智能·chrome·git·github
爱上网的小舟4 小时前
星际战士2启动错误怎么办?5种游戏报错解决方法
开发语言·php
paopaokaka_luck5 小时前
滑雪场管理系统(AI智能助手流式对话,ECharts 运营数据分析、教练、雪具与场地一体化预约,钱包支付退款、订单核销与服务评价)
java·人工智能·spring boot·网络协议·数据分析·echarts
阿里嘎多学长5 小时前
2026-10-12 GitHub 热点项目精选
开发语言·程序员·github·代码托管
Wang's Blog5 小时前
Java 项目实战: 交友项目 - Dubbo 的内部结构与一次调用的完整链路
java·dubbo