Java 春季无法返回带有异常详细信息的ResponseEntity
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/52183546/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Not able to return ResponseEntity with Exception Details in spring
提问by Abdul
I have created a Spring Restful Service and Spring MVC application.
我创建了一个 Spring Restful Service 和 Spring MVC 应用程序。
Restful Service :: Restful service returns an entity if its existing in DB. If it doesn't exist It returns a custom Exception information in ResponseEntity object.
Restful Service :: Restful 服务返回一个实体,如果它存在于数据库中。如果不存在,则返回 ResponseEntity 对象中的自定义异常信息。
It is working as expected tested using Postman.
它使用 Postman 测试按预期工作。
@GetMapping(value = "/validate/{itemId}", produces = { MediaType.APPLICATION_JSON_VALUE, MediaType.APPLICATION_XML_VALUE })
public ResponseEntity<MyItem> validateItem(@PathVariable Long itemId, @RequestHeader HttpHeaders httpHeaders) {
MyItem myItem = myitemService.validateMyItem(itemId);
ResponseEntity<MyItem> responseEntity = null;
if (myItem == null) {
throw new ItemNotFoundException("Item Not Found!!!!");
}
responseEntity = new ResponseEntity<MyItem>(myItem, headers, HttpStatus.OK);
return responseEntity;
}
If the requested Entity does not exist Restful Service returns below.
如果请求的实体不存在 Restful Service 返回下面。
@ExceptionHandler(ItemNotFoundException.class)
public ResponseEntity<ExceptionResponse> itemNotFEx(WebRequest webRequest, Exception exception) {
System.out.println("In CREEH::ItemNFE");
ExceptionResponse exceptionResponse = new ExceptionResponse("Item Not Found Ex!!!", new Date(), webRequest.getDescription(false));
ResponseEntity<ExceptionResponse> responseEntity = new ResponseEntity<ExceptionResponse>(exceptionResponse, HttpStatus.NOT_FOUND);
return responseEntity;
}
But when I am calling the above service from a spring MVC application using RestTemplate, It is returning a valid object if it exists.
但是,当我使用 RestTemplate 从 spring MVC 应用程序调用上述服务时,它返回一个有效对象(如果存在)。
If the requested object does not exist Restful service is returning the exception information but its not reaching the calling(spring MVC) application.
如果请求的对象不存在,Restful 服务将返回异常信息,但未到达调用(spring MVC)应用程序。
Spring MVC application calls Restful Web Service using Rest template
Spring MVC 应用程序使用 Rest 模板调用 Restful Web Service
String url = "http://localhost:8080/ItemServices/items/validate/{itemId}";
ResponseEntity<Object> responseEntity = restTemplate.exchange(url, HttpMethod.GET, httpEntity, Object.class, uriParms);
int restCallStateCode = responseEntity.getStatusCodeValue();
采纳答案by Sagar Veeram
This is expected behavior. Rest template throws exception when the http status is client error or server error and returns the response when http status is not error status.
这是预期的行为。当 http 状态为客户端错误或服务器错误时,Rest 模板抛出异常,当 http 状态不是错误状态时返回响应。
You have to provide implementation to use your error handler, map the response to response entity and throw the exception.
您必须提供实现以使用您的错误处理程序,将响应映射到响应实体并抛出异常。
Create new error exception class with ResponseEntity field.
使用 ResponseEntity 字段创建新的错误异常类。
public class ResponseEntityErrorException extends RuntimeException {
private ResponseEntity<ErrorResponse> errorResponse;
public ResponseEntityErrorException(ResponseEntity<ErrorResponse> errorResponse) {
this.errorResponse = errorResponse;
}
public ResponseEntity<ErrorResponse> getErrorResponse() {
return errorResponse;
}
}
Custom error handler which maps the error response back to ResponseEntity.
将错误响应映射回 ResponseEntity 的自定义错误处理程序。
public class ResponseEntityErrorHandler implements ResponseErrorHandler {
private List<HttpMessageConverter<?>> messageConverters;
@Override
public boolean hasError(ClientHttpResponse response) throws IOException {
return hasError(response.getStatusCode());
}
protected boolean hasError(HttpStatus statusCode) {
return (statusCode.is4xxClientError() || statusCode.is5xxServerError());
}
@Override
public void handleError(ClientHttpResponse response) throws IOException {
HttpMessageConverterExtractor<ExceptionResponse> errorMessageExtractor =
new HttpMessageConverterExtractor(ExceptionResponse.class, messageConverters);
ExceptionResponse errorObject = errorMessageExtractor.extractData(response);
throw new ResponseEntityErrorException(ResponseEntity.status(response.getRawStatusCode()).headers(response.getHeaders()).body(errorObject));
}
public void setMessageConverters(List<HttpMessageConverter<?>> messageConverters) {
this.messageConverters = messageConverters;
}
}
RestTemplate Configuration - You have to set RestTemplate's errorHandler to ResponseEntityErrorHandler.
RestTemplate 配置 - 您必须将 RestTemplate 的 errorHandler 设置为 ResponseEntityErrorHandler。
@Configuration
public class RestTemplateConfiguration {
@Bean
public RestTemplate restTemplate() {
RestTemplate restTemplate = new RestTemplate();
ResponseEntityErrorHandler errorHandler = new ResponseEntityErrorHandler();
errorHandler.setMessageConverters(restTemplate.getMessageConverters());
restTemplate.setErrorHandler(errorHandler);
return restTemplate;
}
}
Calling Method
调用方式
@Autowired restTemplate
String url = "http://localhost:8080/ItemServices/items/validate/{itemId}";
try {
ResponseEntity<Object> responseEntity = restTemplate.exchange(url, HttpMethod.GET, httpEntity, Object.class, uriParms);
int restCallStateCode = responseEntity.getStatusCodeValue();
} catch (ResponseEntityErrorException re) {
ResponseEntity<ErrorResponse> errorResponse = re.getErrorResponse();
}
回答by Otto Touzil
Try using the @ResponseBody annotation on your Exceptionhandler. e.g:
尝试在您的 Exceptionhandler 上使用 @ResponseBody 注释。例如:
public @ResponseBody ResponseEntity<ExceptionResponse> itemNotFEx(WebRequest webRequest, Exception exception) {... }
回答by Adina Fometescu
I've started your application and works just fine.
我已经启动了您的应用程序并且运行良好。
Maven :
马文:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
The controller class is :
控制器类是:
@Controller
public class ValidationController {
@GetMapping(value = "/validate/{itemId}")
public @ResponseBody ResponseEntity<MyItem> validateItem(@PathVariable Long itemId) {
if (itemId.equals(Long.valueOf(1))) {
throw new ItemNotFoundException();
}
return new ResponseEntity<>(new MyItem(), HttpStatus.OK);
}
@ExceptionHandler(ItemNotFoundException.class)
public ResponseEntity<ExceptionResponse> itemNotFEx(WebRequest webRequest, Exception exception) {
System.out.println("In CREEH::ItemNFE");
ExceptionResponse exceptionResponse = new ExceptionResponse("Item Not Found Ex!!!", new Date(), webRequest.getDescription(false));
ResponseEntity<ExceptionResponse> responseEntity = new ResponseEntity<>(exceptionResponse, HttpStatus.NOT_FOUND);
return responseEntity;
}
}
and the test:
和测试:
@RunWith(SpringRunner.class)
@WebMvcTest(value = ValidationController.class, secure = false)
public class TestValidationController {
@Autowired
private MockMvc mockMvc;
@Test
public void testExpectNotFound() throws Exception {
mockMvc.perform(get("/validate/1"))
.andExpect(status().isNotFound());
}
@Test
public void testExpectFound() throws Exception {
mockMvc.perform(get("/validate/2"))
.andExpect(status().isOk());
}
}
Are you sure the url you are trying to use with RestTemplate is correct?
您确定您尝试与 RestTemplate 一起使用的网址是正确的吗?
String url = "http://localhost:8080/ItemServices/items/validate/{itemId}";
Your get method is @GetMapping(value = "/validate/{itemId}"
你的获取方法是 @GetMapping(value = "/validate/{itemId}"
If you don't have request mapping at the level of the controller the url should be:
如果您在控制器级别没有请求映射,则 url 应该是:
http://localhost:8080/validate/1
Another difference is the missing @ResponseBody on your controller method.
另一个区别是控制器方法上缺少 @ResponseBody。
回答by David Pham
You should use Custom Exception Handler to fix your case. It looks like this
您应该使用自定义异常处理程序来解决您的情况。看起来像这样
@ControllerAdvice
public class CustomResponseEntityExceptionHandler extends ResponseEntityExceptionHandler {
public CustomResponseEntityExceptionHandler() {
super();
}
// 404
@ExceptionHandler(value = { EntityNotFoundException.class, ResourceNotFoundException.class })
protected ResponseEntity<Object> handleNotFound(final RuntimeException ex, final WebRequest request) {
BaseResponse responseError = new BaseResponse(HttpStatus.NOT_FOUND.value(),HttpStatus.NOT_FOUND.name(),
Constants.HttpStatusMsg.ERROR_NOT_FOUND);
logger.error(ex.getMessage());
return handleExceptionInternal(ex, responseError, new HttpHeaders(), HttpStatus.NOT_FOUND, request);
}
}
And your code should throw some exception, eg:
并且您的代码应该抛出一些异常,例如:
if (your_entity == null) {
throw new EntityNotFoundException("said something");
}
If you get this case in somewhere else again, you just throw exception like above. Your handler will take care the rest stuffs.
如果您再次在其他地方遇到这种情况,您只需像上面一样抛出异常。您的处理程序将处理其余的东西。
Hope this help.
希望这有帮助。