下面列出了怎么用org.springframework.http.converter.HttpMessageNotReadableException的API类实例代码及写法,或者点击链接到github查看源代码。
@Override
@SuppressWarnings("unchecked")
protected T readInternal(Class<? extends T> clazz, HttpInputMessage inputMessage)
throws IOException, HttpMessageNotReadableException {
WireFeedInput feedInput = new WireFeedInput();
MediaType contentType = inputMessage.getHeaders().getContentType();
Charset charset = (contentType != null && contentType.getCharset() != null ?
contentType.getCharset() : DEFAULT_CHARSET);
try {
Reader reader = new InputStreamReader(inputMessage.getBody(), charset);
return (T) feedInput.build(reader);
}
catch (FeedException ex) {
throw new HttpMessageNotReadableException("Could not read WireFeed: " + ex.getMessage(), ex);
}
}
@Override
protected Object readInternal(Class<? extends Object> clazz, HttpInputMessage inputMessage) throws IOException, HttpMessageNotReadableException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
InputStream in = inputMessage.getBody();
byte[] buf = new byte[1024];
for (;;) {
int len = in.read(buf);
if (len == -1) {
break;
}
if (len > 0) {
baos.write(buf, 0, len);
}
}
byte[] bytes = baos.toByteArray();
return JSON.parseObject(bytes, 0, bytes.length, charset.newDecoder(), clazz);
}
@Test
public void testXmlBomb() throws Exception {
// https://en.wikipedia.org/wiki/Billion_laughs
// https://msdn.microsoft.com/en-us/magazine/ee335713.aspx
String content = "<?xml version=\"1.0\"?>\n" +
"<!DOCTYPE lolz [\n" +
" <!ENTITY lol \"lol\">\n" +
" <!ELEMENT lolz (#PCDATA)>\n" +
" <!ENTITY lol1 \"&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;\">\n" +
" <!ENTITY lol2 \"&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;\">\n" +
" <!ENTITY lol3 \"&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;\">\n" +
" <!ENTITY lol4 \"&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;\">\n" +
" <!ENTITY lol5 \"&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;\">\n" +
" <!ENTITY lol6 \"&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;\">\n" +
" <!ENTITY lol7 \"&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;\">\n" +
" <!ENTITY lol8 \"&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;\">\n" +
" <!ENTITY lol9 \"&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;\">\n" +
"]>\n" +
"<rootElement><external>&lol9;</external></rootElement>";
MockHttpInputMessage inputMessage = new MockHttpInputMessage(content.getBytes("UTF-8"));
assertThatExceptionOfType(HttpMessageNotReadableException.class).isThrownBy(() ->
this.converter.read(RootElement.class, inputMessage))
.withMessageContaining("DOCTYPE");
}
@Test
public void readDomSourceWithXmlBomb() throws Exception {
// https://en.wikipedia.org/wiki/Billion_laughs
// https://msdn.microsoft.com/en-us/magazine/ee335713.aspx
String content = "<?xml version=\"1.0\"?>\n" +
"<!DOCTYPE lolz [\n" +
" <!ENTITY lol \"lol\">\n" +
" <!ELEMENT lolz (#PCDATA)>\n" +
" <!ENTITY lol1 \"&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;\">\n" +
" <!ENTITY lol2 \"&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;\">\n" +
" <!ENTITY lol3 \"&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;\">\n" +
" <!ENTITY lol4 \"&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;\">\n" +
" <!ENTITY lol5 \"&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;\">\n" +
" <!ENTITY lol6 \"&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;\">\n" +
" <!ENTITY lol7 \"&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;\">\n" +
" <!ENTITY lol8 \"&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;\">\n" +
" <!ENTITY lol9 \"&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;\">\n" +
"]>\n" +
"<root>&lol9;</root>";
MockHttpInputMessage inputMessage = new MockHttpInputMessage(content.getBytes("UTF-8"));
this.thrown.expect(HttpMessageNotReadableException.class);
this.thrown.expectMessage("DOCTYPE");
this.converter.read(DOMSource.class, inputMessage);
}
@Test
public void readDomSourceWithXmlBomb() throws Exception {
// https://en.wikipedia.org/wiki/Billion_laughs
// https://msdn.microsoft.com/en-us/magazine/ee335713.aspx
String content = "<?xml version=\"1.0\"?>\n" +
"<!DOCTYPE lolz [\n" +
" <!ENTITY lol \"lol\">\n" +
" <!ELEMENT lolz (#PCDATA)>\n" +
" <!ENTITY lol1 \"&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;\">\n" +
" <!ENTITY lol2 \"&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;\">\n" +
" <!ENTITY lol3 \"&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;\">\n" +
" <!ENTITY lol4 \"&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;\">\n" +
" <!ENTITY lol5 \"&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;\">\n" +
" <!ENTITY lol6 \"&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;\">\n" +
" <!ENTITY lol7 \"&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;\">\n" +
" <!ENTITY lol8 \"&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;\">\n" +
" <!ENTITY lol9 \"&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;\">\n" +
"]>\n" +
"<root>&lol9;</root>";
MockHttpInputMessage inputMessage = new MockHttpInputMessage(content.getBytes("UTF-8"));
assertThatExceptionOfType(HttpMessageNotReadableException.class).isThrownBy(() ->
this.converter.read(DOMSource.class, inputMessage))
.withMessageContaining("DOCTYPE");
}
@Test
public void readWithXmlBomb() throws IOException {
// https://en.wikipedia.org/wiki/Billion_laughs
// https://msdn.microsoft.com/en-us/magazine/ee335713.aspx
String body = "<?xml version=\"1.0\"?>\n" +
"<!DOCTYPE lolz [\n" +
" <!ENTITY lol \"lol\">\n" +
" <!ELEMENT lolz (#PCDATA)>\n" +
" <!ENTITY lol1 \"&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;\">\n" +
" <!ENTITY lol2 \"&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;\">\n" +
" <!ENTITY lol3 \"&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;\">\n" +
" <!ENTITY lol4 \"&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;\">\n" +
" <!ENTITY lol5 \"&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;\">\n" +
" <!ENTITY lol6 \"&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;\">\n" +
" <!ENTITY lol7 \"&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;\">\n" +
" <!ENTITY lol8 \"&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;\">\n" +
" <!ENTITY lol9 \"&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;\">\n" +
"]>\n" +
"<MyBean>&lol9;</MyBean>";
MockHttpInputMessage inputMessage = new MockHttpInputMessage(body.getBytes("UTF-8"));
inputMessage.getHeaders().setContentType(new MediaType("application", "xml"));
assertThatExceptionOfType(HttpMessageNotReadableException.class).isThrownBy(() ->
this.converter.read(MyBean.class, inputMessage));
}
@Test
public void readDomSourceWithXmlBomb() throws Exception {
// https://en.wikipedia.org/wiki/Billion_laughs
// https://msdn.microsoft.com/en-us/magazine/ee335713.aspx
String content = "<?xml version=\"1.0\"?>\n" +
"<!DOCTYPE lolz [\n" +
" <!ENTITY lol \"lol\">\n" +
" <!ELEMENT lolz (#PCDATA)>\n" +
" <!ENTITY lol1 \"&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;\">\n" +
" <!ENTITY lol2 \"&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;\">\n" +
" <!ENTITY lol3 \"&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;\">\n" +
" <!ENTITY lol4 \"&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;\">\n" +
" <!ENTITY lol5 \"&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;\">\n" +
" <!ENTITY lol6 \"&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;\">\n" +
" <!ENTITY lol7 \"&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;\">\n" +
" <!ENTITY lol8 \"&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;\">\n" +
" <!ENTITY lol9 \"&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;\">\n" +
"]>\n" +
"<root>&lol9;</root>";
MockHttpInputMessage inputMessage = new MockHttpInputMessage(content.getBytes("UTF-8"));
this.thrown.expect(HttpMessageNotReadableException.class);
this.thrown.expectMessage("DOCTYPE");
this.converter.read(DOMSource.class, inputMessage);
}
@Override
@SuppressWarnings("unchecked")
protected T readInternal(Class<? extends T> clazz, HttpInputMessage inputMessage)
throws IOException, HttpMessageNotReadableException {
InputStream body = inputMessage.getBody();
if (DOMSource.class == clazz) {
return (T) readDOMSource(body, inputMessage);
}
else if (SAXSource.class == clazz) {
return (T) readSAXSource(body, inputMessage);
}
else if (StAXSource.class == clazz) {
return (T) readStAXSource(body, inputMessage);
}
else if (StreamSource.class == clazz || Source.class == clazz) {
return (T) readStreamSource(body);
}
else {
throw new HttpMessageNotReadableException("Could not read class [" + clazz +
"]. Only DOMSource, SAXSource, StAXSource, and StreamSource are supported.", inputMessage);
}
}
@Override
public JSONAPIDocument read(Type type, Class<?> contextClass, HttpInputMessage inputMessage) throws IOException, HttpMessageNotReadableException {
if (!isAcceptable(type)) {
throw new IllegalArgumentException("Type not supported");
}
ParameterizedType rootType = getSubType(type);
if (rootType != null && Collection.class.isAssignableFrom((Class) rootType.getRawType())) {
Class<?> collectionType = getSubClass(rootType);
if (collectionType != null) {
return converter.readDocumentCollection(inputMessage.getBody(), collectionType);
}
}
Class<?> rootClass = getSubClass(type);
if (rootClass != null) {
return converter.readDocument(inputMessage.getBody(), rootClass);
}
throw new IllegalArgumentException("No collection subtype found");
}
@Test
public void readWithMarshallingFailureException() throws Exception {
MockHttpInputMessage inputMessage = new MockHttpInputMessage(new byte[0]);
UnmarshallingFailureException ex = new UnmarshallingFailureException("forced");
Unmarshaller unmarshaller = mock(Unmarshaller.class);
given(unmarshaller.unmarshal(isA(StreamSource.class))).willThrow(ex);
MarshallingHttpMessageConverter converter = new MarshallingHttpMessageConverter();
converter.setUnmarshaller(unmarshaller);
try {
converter.read(Object.class, inputMessage);
fail("HttpMessageNotReadableException should be thrown");
}
catch (HttpMessageNotReadableException e) {
assertTrue("Invalid exception hierarchy", e.getCause() == ex);
}
}
@SuppressWarnings("deprecation")
private Object readJavaType(JavaType javaType, HttpInputMessage inputMessage) {
try {
if (inputMessage instanceof MappingJacksonInputMessage) {
Class<?> deserializationView = ((MappingJacksonInputMessage) inputMessage).getDeserializationView();
if (deserializationView != null) {
return this.objectMapper.readerWithView(deserializationView).withType(javaType).
readValue(inputMessage.getBody());
}
}
return this.objectMapper.readValue(inputMessage.getBody(), javaType);
}
catch (IOException ex) {
throw new HttpMessageNotReadableException("Could not read document: " + ex.getMessage(), ex);
}
}
@Override
protected Resource readInternal(Class<? extends Resource> clazz, HttpInputMessage inputMessage)
throws IOException, HttpMessageNotReadableException {
WxMediaResource wxMediaResource = new WxMediaResource(inputMessage);
if (wxMediaResource.isUrlMedia() && !clazz.isAssignableFrom(WxMediaResource.class)) {
throw new WxApiException("不支持的返回类型,接口返回了url");
}
if (InputStreamResource.class == clazz) {
return new InputStreamResource(wxMediaResource.getInputStream());
} else if (clazz.isAssignableFrom(WxMediaResource.class)) {
return wxMediaResource;
} else if (clazz.isAssignableFrom(ByteArrayResource.class)) {
return new ByteArrayResource(wxMediaResource.getBody());
} else if (clazz.isAssignableFrom(FileSystemResource.class)) {
return new FileSystemResource(wxMediaResource.getFile());
}
// else if (clazz.isAssignableFrom(File.class)) {
// return wxMediaResource.getFile();
// }
throw new WxApiException("不支持的返回类型");
}
@Override
protected <T> Object readWithMessageConverters(NativeWebRequest webRequest, MethodParameter methodParam,
Type paramType) throws IOException, HttpMediaTypeNotSupportedException, HttpMessageNotReadableException {
HttpServletRequest servletRequest = webRequest.getNativeRequest(HttpServletRequest.class);
ServletServerHttpRequest inputMessage = new ServletServerHttpRequest(servletRequest);
Object arg = readWithMessageConverters(inputMessage, methodParam, paramType);
if (arg == null) {
if (methodParam.getParameterAnnotation(RequestBody.class).required()) {
throw new HttpMessageNotReadableException("Required request body is missing: " +
methodParam.getMethod().toGenericString());
}
}
return arg;
}
@Override
@SuppressWarnings("unchecked")
protected T readInternal(Class<? extends T> clazz, HttpInputMessage inputMessage)
throws IOException, HttpMessageNotReadableException {
InputStream body = inputMessage.getBody();
if (DOMSource.class == clazz) {
return (T) readDOMSource(body);
}
else if (SAXSource.class == clazz) {
return (T) readSAXSource(body);
}
else if (StAXSource.class == clazz) {
return (T) readStAXSource(body);
}
else if (StreamSource.class == clazz || Source.class == clazz) {
return (T) readStreamSource(body);
}
else {
throw new HttpMessageConversionException("Could not read class [" + clazz +
"]. Only DOMSource, SAXSource, StAXSource, and StreamSource are supported.");
}
}
@Override
protected Message readInternal(Class<? extends Message> clazz, HttpInputMessage inputMessage)
throws IOException, HttpMessageNotReadableException {
MediaType contentType = inputMessage.getHeaders().getContentType();
if (contentType == null) {
contentType = PROTOBUF;
}
Charset charset = contentType.getCharset();
if (charset == null) {
charset = DEFAULT_CHARSET;
}
Message.Builder builder = getMessageBuilder(clazz);
if (PROTOBUF.isCompatibleWith(contentType)) {
builder.mergeFrom(inputMessage.getBody(), this.extensionRegistry);
}
else if (TEXT_PLAIN.isCompatibleWith(contentType)) {
InputStreamReader reader = new InputStreamReader(inputMessage.getBody(), charset);
TextFormat.merge(reader, this.extensionRegistry, builder);
}
else if (this.protobufFormatSupport != null) {
this.protobufFormatSupport.merge(
inputMessage.getBody(), charset, contentType, this.extensionRegistry, builder);
}
return builder.build();
}
/**
* 400 - Bad Request
*/
@ResponseStatus(HttpStatus.BAD_REQUEST)
@ExceptionHandler(HttpMessageNotReadableException.class)
public String handleHttpMessageNotReadableException(HttpMessageNotReadableException e, Model model) {
logger.error("参数解析失败", e);
String message = "【参数解析失败】" + e.getMessage();
model.addAttribute("message", message);
model.addAttribute("code", 400);
return viewName;
}
@Override
public Object read(Type type, Class<?> contextClass, HttpInputMessage inputMessage)
throws IOException, HttpMessageNotReadableException {
JavaType javaType = getJavaType(type, contextClass);
return readJavaType(javaType, inputMessage);
}
@Override
protected Serializable readInternal(final Class<? extends Serializable> type, final HttpInputMessage inputMessage)
throws IOException, HttpMessageNotReadableException
{
try {
return type.cast(IOUtils.deserializeObject(IOUtils.toByteArray(inputMessage.getBody()),
ObjectUtils.defaultIfNull(type.getClassLoader(), getClass().getClassLoader())));
}
catch (ClassNotFoundException e) {
throw new HttpMessageNotReadableException(String.format(
"Unable to convert the HTTP message body into an Object of type (%1$s)", type.getName()), e);
}
}
@ExceptionHandler(HttpMessageNotReadableException.class)
public BaseResponse handleError(HttpMessageNotReadableException e) {
logger.error("Message Not Readable", e);
return BaseResponse
.builder()
.code(ResultCode.MSG_NOT_READABLE)
.message(e.getMessage())
.build();
}
/**
* 400 - Bad Request
*/
@ResponseStatus(HttpStatus.BAD_REQUEST)
@ExceptionHandler(HttpMessageNotReadableException.class)
public String handleHttpMessageNotReadableException(HttpMessageNotReadableException e, Model model) {
log.error("参数解析失败", e);
String message = "【参数解析失败】" + e.getMessage();
model.addAttribute("message", message);
model.addAttribute("code", 400);
return viewName;
}
@Override
public Object resolve(RestMethodMetadata restMethodMetadata,
MethodParameterMetadata methodParameterMetadata, HttpServerRequest request) {
if (!supportParameter(restMethodMetadata, methodParameterMetadata)) {
return null;
}
Object result = null;
Class<?> parameterType = resolveClass(methodParameterMetadata.getType());
HttpMessageConverterHolder holder = httpMessageConverterResolver.resolve(request,
parameterType);
if (holder != null) {
HttpMessageConverter converter = holder.getConverter();
try {
result = converter.read(parameterType, request);
}
catch (IOException e) {
throw new HttpMessageNotReadableException(
"I/O error while reading input message", e);
}
}
return result;
}
@Override
protected <T> Object readWithMessageConverters(NativeWebRequest webRequest, MethodParameter parameter,
Type paramType) throws IOException, HttpMediaTypeNotSupportedException, HttpMessageNotReadableException {
HttpServletRequest servletRequest = webRequest.getNativeRequest(HttpServletRequest.class);
Assert.state(servletRequest != null, "No HttpServletRequest");
ServletServerHttpRequest inputMessage = new ServletServerHttpRequest(servletRequest);
Object arg = readWithMessageConverters(inputMessage, parameter, paramType);
if (arg == null && checkRequired(parameter)) {
throw new HttpMessageNotReadableException("Required request body is missing: " +
parameter.getExecutable().toGenericString(), inputMessage);
}
return arg;
}
@Override
@SuppressWarnings({ "unchecked", "rawtypes" })
protected Object doResolveArgumentFromNotificationMessage(JsonNode content,
HttpInputMessage request, Class<?> parameterType) {
if (!"Notification".equals(content.get("Type").asText())) {
throw new IllegalArgumentException(
"@NotificationMessage annotated parameters are only allowed for method that receive a notification message.");
}
MediaType mediaType = getMediaType(content);
String messageContent = content.findPath("Message").asText();
for (HttpMessageConverter<?> converter : this.messageConverter) {
if (converter.canRead(parameterType, mediaType)) {
try {
return converter.read((Class) parameterType,
new ByteArrayHttpInputMessage(messageContent, mediaType,
request));
}
catch (Exception e) {
throw new HttpMessageNotReadableException(
"Error converting notification message with payload:"
+ messageContent,
e);
}
}
}
throw new HttpMessageNotReadableException(
"Error converting notification message with payload:" + messageContent);
}
@Test(expected = HttpMessageNotReadableException.class) // SPR-9942
public void resolveArgumentRequiredNoContent() throws Exception {
this.servletRequest.setContent(new byte[0]);
this.servletRequest.setContentType("text/plain");
List<HttpMessageConverter<?>> converters = new ArrayList<HttpMessageConverter<?>>();
converters.add(new StringHttpMessageConverter());
RequestResponseBodyMethodProcessor processor = new RequestResponseBodyMethodProcessor(converters);
processor.resolveArgument(paramString, mavContainer, webRequest, binderFactory);
}
@ExceptionHandler({
MissingServletRequestParameterException.class,
ServletRequestBindingException.class,
TypeMismatchException.class,
HttpMessageNotReadableException.class,
MethodArgumentNotValidException.class,
MissingServletRequestPartException.class,
BindException.class,
ConstraintViolationException.class
})
public final Object handleSpringBadRequestException(Exception e, HandlerMethod handlerMethod) {
return logAndHandleException(e, BAD_REQUEST, handlerMethod);
}
/**
* {@inheritDoc}
*/
public Object read(Type type, Class<?> contextClass,
HttpInputMessage inputMessage) throws IOException,
HttpMessageNotReadableException {
JavaType javaType = getJavaType(type, contextClass);
return readJavaType(javaType, inputMessage);
}
@Override
protected Message readInternal(Class<? extends Message> clazz, HttpInputMessage inputMessage)
throws IOException, HttpMessageNotReadableException {
MediaType contentType = inputMessage.getHeaders().getContentType();
contentType = (contentType != null ? contentType : PROTOBUF);
Charset charset = getCharset(inputMessage.getHeaders());
InputStreamReader reader = new InputStreamReader(inputMessage.getBody(), charset);
try {
Message.Builder builder = getMessageBuilder(clazz);
if (MediaType.APPLICATION_JSON.isCompatibleWith(contentType)) {
JsonFormat.merge(reader, this.extensionRegistry, builder);
}
else if (MediaType.TEXT_PLAIN.isCompatibleWith(contentType)) {
TextFormat.merge(reader, this.extensionRegistry, builder);
}
else if (MediaType.APPLICATION_XML.isCompatibleWith(contentType)) {
XmlFormat.merge(reader, this.extensionRegistry, builder);
}
else {
builder.mergeFrom(inputMessage.getBody(), this.extensionRegistry);
}
return builder.build();
}
catch (Exception e) {
throw new HttpMessageNotReadableException("Could not read Protobuf message: " + e.getMessage(), e);
}
}
@Test
public void shouldConvertHttpMessageConversionExceptionToMALFORMED_REQUEST() throws Exception {
MvcResult result = this.mockMvc.perform(post("/clientFacingErrorTestDummy/validateDummyRequestObject")
.content("{broken json")
.contentType(MediaType.APPLICATION_JSON)
).andReturn();
// The handler does a instanceof HttpMessageConversionException, but this particular JSON error is a HttpMessageNotReadableException
// (a subclass of HttpMessageConversionException), so that's what we need to expect. It should still get converted to MALFORMED_REQUEST.
verifyErrorResponse(result, projectApiErrors, projectApiErrors.getMalformedRequestApiError(), HttpMessageNotReadableException.class);
}
@ExceptionHandler({HttpMessageNotReadableException.class})
public ResponseEntity<Object> messageNotReadableExceptionHandler(HttpServletRequest req, HttpMessageNotReadableException exception) {
logger.error("Request not readable: {}", exception.toString());
StatusCode statusCode = new StatusCode();
statusCode.setCode("400");
statusCode.setReasonPhrase(exception.getMessage());
if (exception.getCause() != null) {
statusCode.setDetail(exception.getCause().getMessage());
}
return new ResponseEntity<>(statusCode, HttpStatus.BAD_REQUEST);
}
/**
* 400错误拦截
* @param ex 异常信息
* @return 返回前端异常信息
*/
@ExceptionHandler(HttpMessageNotReadableException.class)
@ResponseStatus(HttpStatus.BAD_REQUEST)
public Result request400(HttpMessageNotReadableException ex){
log.error("错误详情:" + ex.getMessage(),ex);
return Result.errorJson(BaseEnum.BAD_REQUEST.getMsg() + " 可能缺少参数",BaseEnum.BAD_REQUEST.getIndex());
}