如果发生异常,请记录http请求正文

时间:2017-08-11 10:37:06

标签: java spring-boot request

我一直在使用spring boot开发rest api服务。 这是我的休息控制器

@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");
    }

这是控制器

 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...
        }
    }

问题是,使用这个结构我应该在每个方法中创建带有参数的地图。如何避免在每个方法中创建地图并将所有参数放入此地图?我需要&#34; MAP&#34;如果发生异常,则显示日志中的参数。 也许春季靴子可以做到,但我无法在官方文档中找到我的案例。提前致谢

1 个答案:

答案 0 :(得分:0)

如果您只想在抛出InvalidUserInputException后执行此操作,则可以编写异常处理程序:

@ExceptionHandler(InvalidUserInputException.class)
@ResponseBody
public ValidationError getError(InvalidUserInputException ex) {
    // ...
}

由于InvalidUserInputException是自定义例外,您可以添加Object类型的字段,您可以在其中传递请求正文,例如:

throw new InvalidUserInputException("Wrong email format", loginOwner);

现在,您可以使用toString()对象的Owner方法进行记录。如果您想以JSON样式获取它,可以使用Apache commons及其ToStringBuilder

@Override
public String toString() {
    return new ToStringBuilder(this, ToStringStyle.JSON_STYLE)
        .append("email", email)
        .append("password", password)
        .toString();
}

或者,如果您不想依赖于使用toString()方法并且只想返回普通请求体,您还可以将HttpServletRequest作为参数添加到异常处理程序中。 / p>

在你这样做之前,你必须把它包起来,因为请求体只能被读取一次,为了解决这个问题,你应该在读取后“缓存”请求体。为此,您可以使用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()方法在异常处理程序中获取请求正文。要将请求体作为String,您可以使用Apache Commons中的IOUtils

ContentCachingRequestWrapper wrapper = (ContentCachingRequestWrapper) request;
logger.warn("Input validation failed, request body: {}", IOUtils.toString(wrapper.getContentAsByteArray(), wrapper.getCharacterEncoding()));

这会将整个请求正文记录为字符串。但要注意记录敏感信息。