Spring自定义错误控制器:@Controller与@RequestMapping注解写法差异解析
哈哈,这个问题我之前踩过一模一样的坑!核心是你误解了@Controller注解的value属性的作用,咱们一步步拆解清楚:
第一种写法@Controller("/error")的问题根源
很多人会误以为@Controller括号里的字符串是请求路径,其实完全不是!它的真实作用是给这个控制器的Spring Bean设置名称,等价于@Controller(value = "error"),根本没有把控制器映射到/error路径上。
那为什么一开始常规REST接口的错误能被处理?因为你实现了ErrorController接口,这个接口的getErrorPath()方法默认返回"/error",Spring的错误处理机制会自动把错误请求转发到这个路径。但你的控制器里的@GetMapping没有指定路径,相当于映射到控制器的“根路径”——可这个控制器本身没有@RequestMapping前缀,所以这个@GetMapping其实是映射到空路径""。
这种模糊的映射逻辑在遇到Swagger、WebSocket这类特殊端点时就会乱套:
- Swagger的
/api/swagger-ui.html是静态资源请求,错误转发时Spring找不到明确的处理规则,触发重定向; - WebSocket用的是ws/wss协议,和HTTP请求的处理逻辑不同,错误转发时匹配不到正确的错误控制器,也会出现异常。
第二种写法@Controller @RequestMapping("/error")的正确性
这里的@RequestMapping("/error")才是真正给整个控制器设置了请求路径前缀,控制器里的所有请求映射(比如@GetMapping)都会基于/error来匹配。
当Spring把错误请求转发到/error时,这个控制器的@GetMapping能精准匹配到GET类型的错误请求,处理逻辑清晰明确,不会和Swagger、WebSocket的端点逻辑产生冲突,所以一切就恢复正常了。
额外小提示
其实在Spring Boot 2.3+版本之后,官方已经不推荐实现ErrorController了,更推荐用@ControllerAdvice配合@ExceptionHandler做全局异常处理,或者自定义ErrorAttributes来定制错误响应信息,你之后可以试试这种更优雅的方式~
内容的提问来源于stack exchange,提问作者lapots

