🌟1、简述
在 Spring Boot Web 开发中,Handler 是处理 HTTP 请求的核心组件,常见的 Handler 类型有以下四种:
🔹 Controller
(注解控制器)
🔹 HandlerInterceptor
(请求拦截器)
🔹 HandlerExceptionResolver
(异常处理器)
🔹 HandlerMethodArgumentResolver
(自定义参数解析器)
掌握这些 Handler 类型可以帮助我们灵活应对请求路由、权限控制、参数解析和全局异常处理等场景。
📦2、项目结构
✅ 实战项目中建议组合使用
🔹 登录校验 → HandlerInterceptor
🔹 获取登录用户信息 → HandlerMethodArgumentResolver
🔹 接口处理逻辑 → @RestController
🔹 统一返回异常信息 → HandlerExceptionResolver
✅ 示例项目推荐结构
├── controller
│ └── UserController.java
├── config
│ └── WebMvcConfig.java
├── handler
│ ├── GlobalExceptionHandler.java
│ └── AuthInterceptor.java
├── resolver
│ └── LoginUserResolver.java
└── model
└── User.java
✍️ 3、 @Controller
/ @RestController
—— 请求分发核心
这是最常见的处理器,接收和响应 HTTP 请求。
✅ 使用方式
@RestController
@RequestMapping("/api")
public class UserController {
@GetMapping("/user/{id}")
public String getUser(@PathVariable Long id) {
return "User ID: " + id;
}
}
📌 实战场景
🔹 控制器接收请求、返回数据
🔹 搭配 @RequestBody
、@PathVariable
解析参数
🔹 结合 Swagger 生成接口文档
✍️ 4、 HandlerInterceptor
—— 请求拦截器(前中后处理)
可以对请求进行前置(preHandle)、后置(postHandle)、完成后处理(afterCompletion)。
✅ 示例:登录鉴权拦截器
@Component
public class AuthInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request,
HttpServletResponse response,
Object handler) throws Exception {
String token = request.getHeader("Authorization");
if (StringUtils.hasText(token) && token.equals("valid-token")) {
return true;
}
response.setStatus(HttpStatus.UNAUTHORIZED.value());
return false;
}
}
✅ 配置注册
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
@Autowired
private AuthInterceptor authInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(authInterceptor)
.addPathPatterns("/api/**")
.excludePathPatterns("/api/public/**");
}
}
📌 实战场景
🔹 鉴权校验(如 JWT)
🔹 日志打印
🔹 请求统计
🔹 IP 黑名单过滤
✍️ 5、 HandlerExceptionResolver
—— 全局异常处理器
用于统一处理系统运行中的异常,避免返回堆栈信息给前端。
✅ 示例:自定义全局异常处理
@ControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(Exception.class)
@ResponseBody
public ResponseEntity<?> handleException(Exception ex) {
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
.body(Map.of("error", ex.getMessage()));
}
@ExceptionHandler(MethodArgumentNotValidException.class)
public ResponseEntity<?> handleValidation(MethodArgumentNotValidException ex) {
String msg = ex.getBindingResult().getFieldError().getDefaultMessage();
return ResponseEntity.badRequest().body(Map.of("msg", msg));
}
}
📌 实战场景
🔹 表单校验异常处理
🔹 自定义异常响应格式
🔹 分模块错误处理逻辑隔离
✍️ 6、 HandlerMethodArgumentResolver
—— 参数解析器
当请求参数比较复杂时,比如 Token、Header、RequestContext,需要通过自定义解析器提取封装为对象。
✅ 示例:自定义注解 @LoginUser
Step 1:定义注解
@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
public @interface LoginUser {}
Step 2:创建解析器
@Component
public class LoginUserResolver implements HandlerMethodArgumentResolver {
@Override
public boolean supportsParameter(MethodParameter parameter) {
return parameter.hasParameterAnnotation(LoginUser.class);
}
@Override
public Object resolveArgument(MethodParameter parameter,
ModelAndViewContainer mavContainer,
NativeWebRequest webRequest,
WebDataBinderFactory binderFactory) {
// 模拟从请求头中获取用户ID
String userId = webRequest.getHeader("X-User-Id");
return new User(Long.valueOf(userId), "mock-username");
}
}
Step 3:注册解析器
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Autowired
private LoginUserResolver loginUserResolver;
@Override
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {
resolvers.add(loginUserResolver);
}
}
Step 4:Controller 使用
@GetMapping("/profile")
public String getProfile(@LoginUser User user) {
return "Welcome " + user.getUsername();
}
📌 实战场景
🔹 自动注入登录用户信息
🔹 多租户系统注入租户上下文
🔹 提高参数封装可读性和复用性
🔚 7、总结
Handler 类型 | 作用 | 触发时机 | 适用场景 |
---|---|---|---|
@Controller / @RestController |
请求入口 | 请求执行时 | 普通业务请求处理 |
HandlerInterceptor |
请求拦截、前中后处理 | DispatcherServlet 前后 | 登录鉴权、日志、限流等 |
HandlerExceptionResolver |
异常处理 | Controller 异常后 | 全局异常处理、返回友好信息 |
HandlerMethodArgumentResolver |
自定义参数注入 | Controller 调用前 | 自动注入登录用户、Header 解析 |
如你需要我为这些内容生成一个完整可运行的 Spring Boot 项目模板,也可以告诉我,我可以直接帮你生成项目结构与代码。
是否需要我继续为你补充:
🔹 五种响应方式对比(如 ResponseEntity
, @ResponseBody
等)
🔹 自定义异常类与统一返回结构封装
🔹 和 Spring Security 结合使用的实践示例?