我有自己的Exceptionhandler,它扩展了ResponseEntityExceptionHandler
我能够捕获错误,但是在创建错误响应时请求主体为空
override fun handleHttpMessageNotReadable(e:HttpMessageNotReadableException, headers:HttpHeaders , status:HttpStatus , webRequest: WebRequest):ResponseEntity<Any>{
val rsp = ErrResponse(
Data(
HttpStatus.BAD_REQUEST.name,
e.message!!
),**REQUEST-BODY-NEEDED**[customFilter.payload])
return super.handleExceptionInternal(e, rsp,headers, HttpStatus.BAD_REQUEST, webRequest)
}
因此,我使用了customRequestfilter来获取主体并在那里捕获主体,但是customRequestFilter的顺序优先级较低,只有在请求之后才会执行。那么有什么方法可以在错误响应中捕获请求正文?
CustomRequestFilter
@Component
public class CustomRequestFilter extends OncePerRequestFilter{
public String payload;
public Map<String, Object> reqLog =null;
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
ContentCachingRequestWrapper wrappedRequest = new ContentCachingRequestWrapper(request);
int status = HttpStatus.BAD_REQUEST.value();
filterChain.doFilter(wrappedRequest, response);
if (status == response.getStatus()) {
reqLog = getTrace(wrappedRequest, status);
payload = getBody(wrappedRequest, reqLog);/** ITS CAPTURING THE BODY HERE SUCCESSFULLY**/
logTrace(wrappedRequest, reqLog);
}
}
答案 0 :(得分:1)
哇,这很棘手!反正...
创建您的自定义HttpInputMessage
,它将委托给原来的自定义广告。
class CachedHttpInputMessage implements HttpInputMessage {
private final HttpInputMessage httpInputMessage;
private ByteArrayOutputStream outputStream;
CachedHttpInputMessage(final HttpInputMessage httpInputMessage) {
this.httpInputMessage = httpInputMessage;
}
@Override
public InputStream getBody() throws IOException {
if (outputStream == null) {
outputStream = new ByteArrayOutputStream();
final InputStream body = httpInputMessage.getBody();
final byte[] buffer = new byte[1024];
while (true) {
final int length;
if (!((length = body.read(buffer)) > -1)) {
break;
}
outputStream.write(buffer, 0, length);
}
outputStream.flush();
}
return new ByteArrayInputStream(outputStream.toByteArray());
}
@Override
public HttpHeaders getHeaders() {
return httpInputMessage.getHeaders();
}
}
构建您的自定义HttpMessageConverter
,然后根据当前使用的Jackson
,Gson
等扩展正确的名称,然后将其注册为第一位。
class CustomHttpMessageConverter extends MappingJackson2HttpMessageConverter {
@Override
public Object read(
final Type type,
final Class<?> contextClass,
final HttpInputMessage inputMessage) throws IOException {
return super.read(type, contextClass, new CachedHttpInputMessage(inputMessage));
}
@Override
protected Object readInternal(
final Class<?> clazz,
final HttpInputMessage inputMessage) throws IOException {
return super.readInternal(clazz, new CachedHttpInputMessage(inputMessage));
}
}
(或者,您可以像创建CachedHttpInputMessage
一样创建通用包装器,并包装每个预先配置的HttpMessageConverter
,只需更新作为输入传递给extendMessageConverters
的列表)
@Configuration
class WebConfiguration implements WebMvcConfigurer {
@Override
public void extendMessageConverters(final List<HttpMessageConverter<?>> converters) {
converters.add(0, new CustomHttpMessageConverter());
}
...
}
扔掉自定义Filter
,然后在ExceptionHandler
内使用
final HttpInputMessage inputMessage = e.getHttpInputMessage();
final InputStream body = inputMessage.getBody();
完成!
请记住要稍微清理一下代码并处理所有可能的异常。