使用 Spring MVC 从 ExceptionHandler 获取请求值

sma*_*h87 6 java exception spring-mvc httprequest

我有一个 Spring MVC 控制器和一个异常处理程序。发生异常时,我希望异常处理程序记录请求中发送的所有 GET/POST 数据。如何做到这一点?

控制器:

@Controller
@RequestMapping("/foo")
public class FooController {
    private final FooService fooService;

    @PostMapping("/bar")
    @ResponseBody
    public BarObject doSomething(@RequestBody final FooContext context) 
    {
        return fooService.doSomething(context);
    }
}
Run Code Online (Sandbox Code Playgroud)

异常处理程序:

@ControllerAdvice
public class ExceptionController {

    private final Logger log = LoggerFactory.getLogger(ExceptionController.class);

    @ResponseStatus(HttpStatus.BAD_REQUEST)
    @ExceptionHandler(Exception.class)
    @ResponseBody
    public ErrorMessage handleException(final HttpServletRequest request, final Exception exception) {
        //Retrieve request data 
        //request.getQueryString() 
        // How to get POST data if we cannot access @RequestBody?)
        log.error(request.getRequestURI(), exception);
        return new ErrorMessage(request.getRequestURI(), exception.getLocalizedMessage());
}
Run Code Online (Sandbox Code Playgroud)

Mar*_*oza 8

请求正文位于 HttpServletRequest 中。

您可以通过执行以下操作来访问 RAW 请求正文:

String body = request.getReader().lines().collect(Collectors.joining(System.lineSeparator()));
Run Code Online (Sandbox Code Playgroud)

来自异常处理程序方法。(使用java 8)。

然后您可以将正文字符串解析为 POJO。

编辑

值得注意的是 avobe 答案不起作用。发生这种情况是因为当解析主体(使用 @RequestBody)时,http 连接流被关闭,因此无法再次访问请求主体。但是,您可以从控制器方法直接将属性注入到 httpRequest,然后访问异常处理程序中的值:

@RestController
@RequestMapping(ApiVersion.V1.prefix)
public class BatchController {
    @PostMapping("/batch")
    public @ResponseBody BatchResponse runBatch(@RequestBody BatchRequest batchRequest, HttpServletRequest request) throws IOException {
        System.out.println(batchRequest.getName());
        request.setAttribute("batchRequest" , batchRequest);
        throw new IllegalArgumentException("Some error");
    }

    @ExceptionHandler(IllegalArgumentException.class)
    public @ResponseBody BatchResponse handle(HttpServletRequest request) {
        BatchRequest batchRequest = (BatchRequest) request.getAttribute("batchRequest");
        System.out.println("handling exception");
        return new BatchResponse(batchRequest.getName());
    }
}
Run Code Online (Sandbox Code Playgroud)

希望这可以帮助

  • 当我在“handleException”方法中调用“request.getReader()”时,出现“IllegalStateException”异常:Controller$ErrorMessage com.foo.core.ExceptionController.handleException(javax.servlet.http.HttpServletRequest,java.lang.Exception ) java.lang.IllegalStateException:在 org.eclipse.jetty.server.Request.getReader(Request.java:1158) 处流式传输 (4认同)