我一直在使用 Spring Boot 开发 REST API 服务。 这是我的休息 Controller
@RequestMapping(value = "owner/login", method = RequestMethod.POST, produces = "application/json;charset=UTF-8")
@ResponseBody
public ResponseEntity<String> login(@RequestBody Owner owner) throws TimeoutException, SocketTimeoutException, SocketException {
controller.login(owner);
return ResponseEntity.ok("\"error\": 0");
}
这是 Controller
public JsonObject login(Owner loginOwner){
Map<String,String> params = new HashMap<String,String>();
params.put("email", loginOwner.getEmail());
params.put("password", loginOwner.getPassword());
if(GMoikaStringUtils.isEmpty(loginOwner.getEmail()) || !GMoikaStringUtils.isValidEmail(loginOwner.getEmail())){
throw new InvalidUserInputException("Wrong email format", CLASS_NAME, "login", params, "owners/owner/login POST");
}
else{
someLogic...
}
}
问题是,使用这个结构我应该在每个方法内创建带有参数的映射。如何避免在每个方法内创建映射并将所有参数放入该映射中?我需要“MAP”在日志中显示参数,以防发生异常。 也许 spring boot 可以做到这一点,但我在官方文档中找不到我的案例。提前致谢
最佳答案
如果您只想在抛出 InvalidUserInputException
后执行此操作,则可以编写一个异常处理程序:
@ExceptionHandler(InvalidUserInputException.class)
@ResponseBody
public ValidationError getError(InvalidUserInputException ex) {
// ...
}
由于 InvalidUserInputException
是自定义异常,因此您可以添加一个 Object
类型的字段,您可以在其中传递请求正文,例如:
throw new InvalidUserInputException("Wrong email format", loginOwner);
现在您可以使用 Owner
对象的 toString()
方法来记录它。如果你想以JSON方式获取,可以使用 Apache commons和他们的ToStringBuilder
:
@Override
public String toString() {
return new ToStringBuilder(this, ToStringStyle.JSON_STYLE)
.append("email", email)
.append("password", password)
.toString();
}
<小时/>
或者,如果您不想依赖使用 toString()
方法而只想返回纯请求正文,您也可以将 HttpServletRequest
添加为异常处理程序的参数。
在执行此操作之前,您必须将其包装起来,因为请求正文只能读取一次,为了克服该问题,您应该在读取请求正文后“缓存”请求正文。为此,您可以使用 Spring 的 ContentCachingRequestWrapper
.
要包装它,您应该编写自己的Filter
。您可以通过从 Spring 扩展它们的 OncePerRequestFilter
来做到这一点像这样:
ContentCachingRequestWrapper wrapper = (ContentCachingRequestWrapper) request;
wrapper.getContentAsByteArray();
@Component
public class RequestWrapperFilter extends OncePerRequestFilter {
@Override
protected void doFilterInternal(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, FilterChain filterChain) throws ServletException, IOException {
filterChain.doFilter(new ContentCachingRequestWrapper(httpServletRequest), httpServletResponse);
}
}
现在,您可以通过调用 getContentAsByteArray()
方法在异常处理程序中获取请求正文。要获取字符串形式的请求正文,您可以使用 Apache Commons 中的 IOUtils
:
ContentCachingRequestWrapper wrapper = (ContentCachingRequestWrapper) request;
logger.warn("Input validation failed, request body: {}", IOUtils.toString(wrapper.getContentAsByteArray(), wrapper.getCharacterEncoding()));
这会将整个请求正文记录为字符串。不过,记录敏感信息时要小心。
关于java - 如果发生异常,则记录http请求正文,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45633154/