spring boot 全局异常处理捕获 header 解析异常,核心在于将 @exceptionhandler 与 @controlleradvice 结合使用。当请求头格式错误导致框架抛出 httpmessagenotreadableexception 或 methodargumenttypemismatchexception 时,拦截器会将其转发至全局处理器。通过定义针对这些异常类的处理方法,可以统一返回 json 格式的友好提示,避免暴露堆栈信息。

@ExceptionHandler 如何匹配 Header 解析失败
在 Spring MVC 中,Header 的解析通常发生在参数绑定阶段。如果自定义注解或方法参数要求特定的 Header 值(如日期格式、枚举值),而实际传入的值不符合预期,Spring 会抛出 MethodArgumentTypeMismatchException。此外,如果请求体或某些序列化相关的 Header 导致消息转换器失败,则会抛出 HttpMessageNotReadableException。全局异常处理器通过指定 value 属性为这些异常类,即可精准捕获并处理。

import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException;
import org.springframework.http.converter.HttpMessageNotReadableException;
import java.util.HashMap;
import java.util.Map;
@ControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(MethodArgumentTypeMismatchException.class)
public ResponseEntity<Map<String, Object>> handleTypeMismatch(MethodArgumentTypeMismatchException ex) {
Map<String, Object> body = new HashMap<>();
body.put("error", "Parameter mismatch");
body.put("message", "Invalid header value for: " + ex.getName());
return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(body);
}
@ExceptionHandler(HttpMessageNotReadableException.class)
public ResponseEntity<Map<String, Object>> handleMessageNotReadable(HttpMessageNotReadableException ex) {
Map<String, Object> body = new HashMap<>();
body.put("error", "Message not readable");
body.put("message", "Failed to parse request or headers");
return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(body);
}
}上述代码展示了两个关键的异常处理方法。第一个方法处理类型不匹配,通常对应 Header 值无法转换为预期类型(如期望整数却收到字符串)。第二个方法处理消息不可读,常用于更广泛的解析失败场景。这两个方法都返回 ResponseEntity,确保状态码和响应体符合 RESTful 规范。
自定义 Header 校验器如何触发全局异常
除了依赖 Spring 内置的类型转换,开发者常通过自定义 HandlerMethodArgumentResolver 来解析复杂的 Header。如果在解析过程中发现数据非法,直接抛出运行时异常会导致 500 错误。正确的做法是抛出 IllegalArgumentException 或自定义的业务异常,并在 @ControllerAdvice 中捕获它们。这样可以将 Header 校验逻辑与异常处理解耦,保持控制器方法的简洁。

import org.springframework.core.MethodParameter;
import org.springframework.web.bind.support.WebDataBinderFactory;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.ModelAndViewContainer;
public class CustomHeaderResolver implements HandlerMethodArgumentResolver {
@Override
public boolean supportsParameter(MethodParameter parameter) {
return parameter.hasParameterAnnotation(CustomHeader.class);
}
@Override
public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer,
NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
String headerValue = webRequest.getHeader("X-Custom-Id");
if (headerValue == null || !headerValue.matches("^[A-Z0-9]{5}$")) {
throw new IllegalArgumentException("Invalid custom header format");
}
return headerValue;
}
}这段代码实现了一个简单的自定义参数解析器。它检查名为 X-Custom-Id 的 Header 是否符合正则表达式。如果不符合,抛出 IllegalArgumentException。为了捕获这个异常,需要在 GlobalExceptionHandler 中添加对应的 @ExceptionHandler(IllegalArgumentException.class) 方法。这种模式允许开发者对 Header 内容进行细粒度的控制,同时利用全局异常处理机制保证错误响应的一致性。
当 Header 值为空时全局异常处理器的行为是什么
当 Header 值为空或缺失时,Spring 的行为取决于具体的解析方式。对于标准的 @RequestHeader 注解,如果未设置 required=true,默认值为 null 或空字符串,不会触发异常。但如果使用了自定义解析器或在类型转换阶段,空值可能导致 NullPointerException 或类型转换失败。在全局异常处理器中,需要特别注意区分“缺失”和“无效”。例如,在 MethodArgumentTypeMismatchException 的处理中,可以通过 ex.getRequiredType() 判断是否期望非空值,从而提供更精确的错误信息,而不是笼统地返回 400 错误。


















