Spring rest controller @ExceptionHandler return xml 内容和json 错误
Spring rest controller @ExceptionHandler return xml content and json errors
所以我有一个 @RestController,我想 return 并基于前端应用程序的模式验证 XML 以便在编辑器中显示它们。我希望错误采用 json 格式,以便用 js 处理和显示它们。
@RestController
public class UserController {
@RequestMapping(value = "/test",
method = RequestMethod.GET,
produces = MediaType.APPLICATION_XML_VALUE)
public ResponseEntity<String> throwException(
@RequestParam(value = "flag", defaultValue = "false") Boolean flag
) throws Exception {
if (flag) {
throw new Exception();
} else {
return ResponseEntity.ok("<xml>hello</xml>");
}
}
@ResponseStatus(HttpStatus.BAD_REQUEST)
@ExceptionHandler(Exception.class)
@ResponseBody
ServerError exceptionHandler(HttpServletRequest req, Exception ex) {
return new ServerError(req.getRequestURL().toString(),ex);
}
}
我想要 return JSON 格式的 ServerError :
public class ServerError {
public final String url;
public final String error;
public ServerError(String url, Exception ex) {
this.url = url;
this.error = ex.getMessage();
}
public String getUrl() {
return url;
}
public String getError() {
return error;
}
}
所以 <xml>hello</xml>
被 return 编辑得很好但是当我将标志设置为 true
我得到
ERROR 2017-10-18 12:56:53,189 [http-nio-0.0.0.0-8080-exec-2] org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver - Failed to invoke @ExceptionHandler method: eu.openminted.registry.core.exception.ServerError eu.openminted.registry.service.UserController.malformedExeption(javax.servlet.http.HttpServletRequest,java.lang.Exception)
org.springframework.web.HttpMediaTypeNotAcceptableException: Could not find acceptable representation
此外,将 produces
设置为 XML 和 JSON 会产生相同的结果
@RequestMapping(value = "/test",
method = RequestMethod.GET,
produces = {MediaType.APPLICATION_XML_VALUE,MediaType.APPLICATION_JSON_UTF8_VALUE})
我设法通过从 @RequestMapping
中删除 produces
并使用 ResponseEntity
指定我想要 return
的类型来解决这个问题
@RequestMapping(value = "/test", method = RequestMethod.GET)
public ResponseEntity<String> throwException(
@RequestParam(value = "flag", defaultValue = "false") Boolean flag
) throws Exception {
if (flag) {
throw new Exception();
} else {
ResponseEntity response = ResponseEntity.ok().
contentType(MediaType.APPLICATION_XML).
body("<xml>hello</xml>");
return response;
}
}
该解决方案的问题是所有方法都有一个 @annotation
和它们生成的类型,而这个没有,破坏了一致性。
您需要在 pom.xml 中添加以下依赖项,它将与您的代码配合使用 produces = MediaType.APPLICATION_XML_VALUE,
<dependency>
<groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-xml</artifactId>
</dependency>
一种选择是在 ExceptionHandler 中明确地将内容类型添加到 ResponseEntity。
控制器:
@GetMapping("/path", produces = [MediaType.TEXT_XML_VALUE])
ControllerAdvice:
@ExceptionHandler(org.springframework.validation.BindException::class)
fun handleBindException(
e: org.springframework.validation.BindException
): ResponseEntity<ErrorResponse> {
return ResponseEntity
.status(HttpStatus.BAD_REQUEST)
.contentType(MediaType.APPLICATION_JSON_UTF8)
.body(ErrorResponse(e.message))
}
错误响应
data class ErrorResponse(val message: String?)
使用 Kotlin
在 Spring Boot 2.1.3.RELEASE 上测试
为了让ExceptionHandler成为returnXML格式(默认是returns JSON格式),需要做两步:
- 导入maven依赖:
<dependency>
<groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-xml</artifactId>
</dependency>
- 使用 ResposneEntity 的静态方法
internalServerError()
:
ResponseEntity.internalServerError().header("MyHeader","MyValue").contentType(MediaType.APPLICATION_XML).body(ex);
在 contentType 中,指定 MediaType.APPLICATION_XML
。
所以我有一个 @RestController,我想 return 并基于前端应用程序的模式验证 XML 以便在编辑器中显示它们。我希望错误采用 json 格式,以便用 js 处理和显示它们。
@RestController
public class UserController {
@RequestMapping(value = "/test",
method = RequestMethod.GET,
produces = MediaType.APPLICATION_XML_VALUE)
public ResponseEntity<String> throwException(
@RequestParam(value = "flag", defaultValue = "false") Boolean flag
) throws Exception {
if (flag) {
throw new Exception();
} else {
return ResponseEntity.ok("<xml>hello</xml>");
}
}
@ResponseStatus(HttpStatus.BAD_REQUEST)
@ExceptionHandler(Exception.class)
@ResponseBody
ServerError exceptionHandler(HttpServletRequest req, Exception ex) {
return new ServerError(req.getRequestURL().toString(),ex);
}
}
我想要 return JSON 格式的 ServerError :
public class ServerError {
public final String url;
public final String error;
public ServerError(String url, Exception ex) {
this.url = url;
this.error = ex.getMessage();
}
public String getUrl() {
return url;
}
public String getError() {
return error;
}
}
所以 <xml>hello</xml>
被 return 编辑得很好但是当我将标志设置为 true
我得到
ERROR 2017-10-18 12:56:53,189 [http-nio-0.0.0.0-8080-exec-2] org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver - Failed to invoke @ExceptionHandler method: eu.openminted.registry.core.exception.ServerError eu.openminted.registry.service.UserController.malformedExeption(javax.servlet.http.HttpServletRequest,java.lang.Exception)
org.springframework.web.HttpMediaTypeNotAcceptableException: Could not find acceptable representation
此外,将 produces
设置为 XML 和 JSON 会产生相同的结果
@RequestMapping(value = "/test",
method = RequestMethod.GET,
produces = {MediaType.APPLICATION_XML_VALUE,MediaType.APPLICATION_JSON_UTF8_VALUE})
我设法通过从 @RequestMapping
中删除 produces
并使用 ResponseEntity
指定我想要 return
@RequestMapping(value = "/test", method = RequestMethod.GET)
public ResponseEntity<String> throwException(
@RequestParam(value = "flag", defaultValue = "false") Boolean flag
) throws Exception {
if (flag) {
throw new Exception();
} else {
ResponseEntity response = ResponseEntity.ok().
contentType(MediaType.APPLICATION_XML).
body("<xml>hello</xml>");
return response;
}
}
该解决方案的问题是所有方法都有一个 @annotation
和它们生成的类型,而这个没有,破坏了一致性。
您需要在 pom.xml 中添加以下依赖项,它将与您的代码配合使用 produces = MediaType.APPLICATION_XML_VALUE,
<dependency>
<groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-xml</artifactId>
</dependency>
一种选择是在 ExceptionHandler 中明确地将内容类型添加到 ResponseEntity。
控制器:
@GetMapping("/path", produces = [MediaType.TEXT_XML_VALUE])
ControllerAdvice:
@ExceptionHandler(org.springframework.validation.BindException::class)
fun handleBindException(
e: org.springframework.validation.BindException
): ResponseEntity<ErrorResponse> {
return ResponseEntity
.status(HttpStatus.BAD_REQUEST)
.contentType(MediaType.APPLICATION_JSON_UTF8)
.body(ErrorResponse(e.message))
}
错误响应
data class ErrorResponse(val message: String?)
使用 Kotlin
在 Spring Boot 2.1.3.RELEASE 上测试为了让ExceptionHandler成为returnXML格式(默认是returns JSON格式),需要做两步:
- 导入maven依赖:
<dependency> <groupId>com.fasterxml.jackson.dataformat</groupId> <artifactId>jackson-dataformat-xml</artifactId> </dependency>
- 使用 ResposneEntity 的静态方法
internalServerError()
:ResponseEntity.internalServerError().header("MyHeader","MyValue").contentType(MediaType.APPLICATION_XML).body(ex);
在 contentType 中,指定 MediaType.APPLICATION_XML
。