Spring Boot错误处理场景下如何获取浏览器原始请求URL
如何在自定义ErrorController中获取原始请求URL?
我之前刚好遇到过一模一样的问题!Spring Boot在把请求转发到自定义的/error处理器时,确实会把当前请求的路径改成/error,但其实容器和Spring已经帮我们把原始请求的信息存起来了,有两种简单的方法可以拿到:
方法一:直接从HttpServletRequest获取Servlet规范属性
Servlet容器会把原始请求的URI存储在javax.servlet.error.request_uri这个请求属性里,我们可以直接从HttpServletRequest中获取:
@RestController public class IndexController implements ErrorController { @RequestMapping("/error") public String handleError(HttpServletRequest request) { // 从请求属性中拿到原始请求URI String originalRequestUri = (String) request.getAttribute("javax.servlet.error.request_uri"); if (originalRequestUri != null) { return "触发错误的原始请求URL:" + originalRequestUri; } return "无法获取原始请求URL"; } @Override public String getErrorPath() { return "/error"; } @RequestMapping("/") public String index() { return "Hello World!"; } }
这个方法是基于Servlet规范的,不管是Spring Boot还是普通的Servlet项目都适用,非常直接。
方法二:使用Spring Boot的ErrorAttributes(推荐)
如果是Spring Boot 2.3及以上版本,更推荐用ErrorAttributes来获取错误信息,它是Spring提供的统一处理错误上下文的组件,能拿到包括原始请求路径、状态码、异常信息在内的所有错误相关数据:
@RestController public class IndexController implements ErrorController { private final ErrorAttributes errorAttributes; // 通过构造器注入ErrorAttributes public IndexController(ErrorAttributes errorAttributes) { this.errorAttributes = errorAttributes; } @RequestMapping("/error") public String handleError(HttpServletRequest request) { WebRequest webRequest = new ServletWebRequest(request); // 获取错误信息Map,其中"path"字段就是原始请求路径 Map<String, Object> errorDetails = errorAttributes.getErrorAttributes(webRequest, ErrorAttributeOptions.defaults()); String originalRequestUri = (String) errorDetails.get("path"); return "触发错误的原始请求URL:" + originalRequestUri; } @Override public String getErrorPath() { return "/error"; } @RequestMapping("/") public String index() { return "Hello World!"; } }
这种方式更符合Spring Boot的设计理念,而且扩展性更强,如果之后需要获取其他错误信息,直接从errorDetails里拿对应的key就行。
注意事项
如果是Spring Boot 3.x版本,ErrorController接口已经被标记为Deprecated了,官方更推荐使用@ControllerAdvice配合@ExceptionHandler来处理全局异常,或者使用ErrorWebExceptionHandler(针对WebFlux场景)。不过如果坚持使用ErrorController,上面的两种方法依然可以正常工作。
内容的提问来源于stack exchange,提问作者user2914191
相关产品推荐
相关产品推荐

