Spring ResponseEntityExceptionHandler中获取HttpServletRequest的实现
在Spring Boot自定义异常处理器中获取HttpServletRequest的方法
嘿,我来帮你搞定这个问题!在你继承ResponseEntityExceptionHandler的自定义异常处理器里,获取HttpServletRequest有两种实用方式,对应不同的场景:
1. 重写父类方法时,从WebRequest转换获取
像你代码里的handleHttpMessageNotReadable、handleMethodArgumentNotValid这类重写的方法,参数里只有WebRequest,这时候可以通过RequestContextHolder来拿到HttpServletRequest:
@Override protected ResponseEntity<Object> handleHttpMessageNotReadable(HttpMessageNotReadableException ex, HttpHeaders headers, HttpStatus status, WebRequest request) { // 从请求上下文获取HttpServletRequest ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); HttpServletRequest httpServletRequest = attributes.getRequest(); // 现在就能用它做你需要的操作了,比如获取请求IP、URI String remoteIp = httpServletRequest.getRemoteAddr(); String requestUri = httpServletRequest.getRequestURI(); // 你的原有业务逻辑... if (ExceptionUtils.getRootCauseMessage(ex).contains("Duplicate entry")) { // 这里可以把httpServletRequest传给你的buildIntegrityError方法 return response(HttpStatus.CONFLICT, new HttpHeaders(), buildIntegrityError(ex, httpServletRequest, HttpStatus.CONFLICT, LocaleContextHolder.getLocale())); } else { return response(HttpStatus.BAD_REQUEST, new HttpHeaders(), buildGenericError(ex, request, HttpStatus.BAD_REQUEST, LocaleContextHolder.getLocale())); } }
注:在Spring MVC的请求上下文里,RequestContextHolder一定会持有ServletRequestAttributes,不用担心空指针问题。
2. 自定义@ExceptionHandler方法时,直接注入参数
就像你代码里的handleConflictException和handleFileUpload方法那样,直接把HttpServletRequest作为方法参数,Spring会自动帮你注入进来,用起来超方便:
@ExceptionHandler(MaxUploadSizeExceededException.class) public ResponseEntity<?> handleFileUpload(MaxUploadSizeExceededException ex, HttpServletRequest request, Locale locale) throws Exception { // 直接使用request,比如你已经在日志里用到的获取远程IP log.error(String.format("从%s收到过大文件。错误信息:%s", AppUtils.getRemoteIp(request), ExceptionUtils.getRootCauseMessage(ex))); // 你的原有业务逻辑... return response(HttpStatus.BAD_REQUEST, new HttpHeaders(), buildIntegrityError(ex, request, HttpStatus.BAD_REQUEST, LocaleContextHolder.getLocale())); }
额外小技巧:工具类中全局获取
如果你的工具方法(比如buildIntegrityError)也需要用到HttpServletRequest,可以写个静态工具方法:
private HttpServletRequest getCurrentRequest() { ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); return attributes != null ? attributes.getRequest() : null; }
这样在任何需要的地方调用这个方法就能拿到当前请求对象了。
内容的提问来源于stack exchange,提问作者drenda
相关产品推荐
相关产品推荐

