restTemplate如何获取Exception中的body信息
问题描述:Rest 接口中的异常,如何能在RestTemplate 中显示出来.RestTemplate 中try catch 的 e.getMessage()只能是请求本身代码异常.(400 null 或者 500 null),但是 用postman 调用的时候是可以显示错误信息的.这是怎么回事?
具体图片情况如下:
但是当我们通过test请求时只能获取到如下信息:
com.disney.wdpro.service.shdr.order.adaptor.ticketing.exception.RestException: 400 at com.disney.wdpro.service.shdr.order.adaptor.ticketing.handler.HttpClientResponseErrorHandler.handleError(HttpClientResponseErrorHandler.java:45) at org.springframework.web.client.ResponseErrorHandler.handleError(ResponseErrorHandler.java:63) at org.springframework.web.client.RestTemplate.handleResponse(RestTemplate.java:778) at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:736) at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:670) at org.springframework.web.client.RestTemplate.postForEntity(RestTemplate.java:445) at com.disney.wdpro.service.shdr.order.adaptor.ticketing.ShdrOrderAdaptorTicketingApplicationTests.testErrors(ShdrOrderAdaptorTicketingApplicationTests.java:200) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50) at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47) at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17) at org.springframework.test.context.junit4.statements.RunBeforeTestExecutionCallbacks.evaluate(RunBeforeTestExecutionCallbacks.java:74) at org.springframework.test.context.junit4.statements.RunAfterTestExecutionCallbacks.evaluate(RunAfterTestExecutionCallbacks.java:84) at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:75) at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:86) at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:84) at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325) at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:251) at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:97) at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61) at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70) at org.junit.runners.ParentRunner.run(ParentRunner.java:363) at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:190) at org.junit.runner.JUnitCore.run(JUnitCore.java:137) at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68) at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47) at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242) at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
查询了很多资料,发现是因为restTemplate源代码中进行了异常捕获并重新进行了抛出,所以我们要获取其中body只能通过重写它的方法handleError来进行异常的获取,具体代码如下:
public class RestException extends RestClientException implements Serializable { private static final long serialVersionUID = 9166280219178545623L; private RestClientException restClientException; private String body; public RestClientException getRestClientException() { return restClientException; } public void setRestClientException(RestClientException restClientException) { this.restClientException = restClientException; } public String getBody() { return body; } public void setBody(String body) { this.body = body; } public RestException(String msg, RestClientException restClientException, String body) { super(msg); this.restClientException = restClientException; this.body = body; } }
public class HttpClientResponseErrorHandler implements ResponseErrorHandler { private ResponseErrorHandler errorHandler = new DefaultResponseErrorHandler(); @Override public boolean hasError(ClientHttpResponse response) throws IOException { return errorHandler.hasError(response); } @Override public void handleError(ClientHttpResponse response) throws IOException { String body = StringUtil.convertStreamToString(response.getBody()); try { errorHandler.handleError(response); }catch (RestClientException re) { throw new RestException(re.getMessage(), re, body); } } }
进行测试的代码修改成捕获我们自己的异常,就可以获取到body中的信息了。
try{ ResponseEntity<TicketCreateOrderResponse> response = restTemplate.postForEntity("https://pep-service-internal.latest.shdrapps.disney.com/ticket-order-service/v2/orders/", httpEntity, TicketCreateOrderResponse.class); System.out.println("**************" + response.getBody()); TicketCreateOrderResponse ticketCreateOrderResponse = response.getBody(); if (Objects.nonNull(ticketCreateOrderResponse) && StringUtils.isNotBlank(ticketCreateOrderResponse.getOrderId())) { ticketCreateOrderResponse.setOrderNumber(ticketCreateOrderResponse.getOrderId()); // System.out.println(ticketCreateOrderResponse.getErrors().getErrorCode()); // System.out.println(ticketCreateOrderResponse.getErrors().getErrorMessage()); // System.out.println(ticketCreateOrderResponse.getErrors().getErrorType()); } }catch (RestException e) { e.printStackTrace(); System.out.println(e.getBody()); TicketCreateOrderResponse errorResponse = GsonUtil.convertJsonToBean(e.getBody(), TicketCreateOrderResponse.class); errorResponse.getErrors().stream().forEach(response -> { errorResponse.setOrderNumber(response.getOrderId()); errorResponse.setCode(Integer.valueOf(response.getErrorCode())); errorResponse.setStatus(response.getErrorType()); }); System.out.println(GsonUtil.getString(errorResponse)); System.out.println(e.getRestClientException()); }
com.disney.wdpro.service.shdr.order.adaptor.ticketing.exception.RestException: 400 at com.disney.wdpro.service.shdr.order.adaptor.ticketing.handler.HttpClientResponseErrorHandler.handleError(HttpClientResponseErrorHandler.java:45) at org.springframework.web.client.ResponseErrorHandler.handleError(ResponseErrorHandler.java:63) at org.springframework.web.client.RestTemplate.handleResponse(RestTemplate.java:778) at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:736) at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:670) at org.springframework.web.client.RestTemplate.postForEntity(RestTemplate.java:445) at com.disney.wdpro.service.shdr.order.adaptor.ticketing.ShdrOrderAdaptorTicketingApplicationTests.testErrors(ShdrOrderAdaptorTicketingApplicationTests.java:200) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50) at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47) at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17) at org.springframework.test.context.junit4.statements.RunBeforeTestExecutionCallbacks.evaluate(RunBeforeTestExecutionCallbacks.java:74) at org.springframework.test.context.junit4.statements.RunAfterTestExecutionCallbacks.evaluate(RunAfterTestExecutionCallbacks.java:84) at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:75) at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:86) at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:84) at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325) at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:251) at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:97) at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61) at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70) at org.junit.runners.ParentRunner.run(ParentRunner.java:363) at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:190) at org.junit.runner.JUnitCore.run(JUnitCore.java:137) at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68) at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47) at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242) at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70) {"errors":[{"errorCode":"1009","errorType":"ORDER_ID_DUPLICATE","errorMessage":"org.jooq.exception.DataAccessException: SQL [insert into `ORDERS` (`ORDER_ID`, `CLIENT_NAME`, `CLIENT_ID`, `SESSION_ID`, `ORDER_TYPE`, `PRODUCT_TYPE`, `ORDER_STATUS`, `STORE_ID`, `CUSTOMER_ID`, `BOOKING_INTERFACE`, `USER_LANGUAGE`, `CONTACT_GUEST_ID`, `CONTACT_FIRST_NAME`, `CONTACT_LAST_NAME`, `CONTACT_PHONE`, `CONTACT_EMAIL`, `CONTACT_GOVERNMENT_ID`, `AGENCY_IATA_NUMBER`, `PAYMENT_SESSION_ID`, `CASL`, `CREATE_DATE_TIME`, `LAST_MODIFIED_DATE_TIME`, `VERSION`, `INSTALLMENT_PERIOD`, `FROM_CART`, `REG_SUPPORTED`) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)]; Duplicate entry '123456789' for key 'UQ_BOOKING_ORDER_ID'","orderId":"123456789"}]} {"orderNumber":"123456789","status":"ORDER_ID_DUPLICATE","code":1009,"errors":[{"errorCode":"1009","errorType":"ORDER_ID_DUPLICATE","errorMessage":"org.jooq.exception.DataAccessException: SQL [insert into `ORDERS` (`ORDER_ID`, `CLIENT_NAME`, `CLIENT_ID`, `SESSION_ID`, `ORDER_TYPE`, `PRODUCT_TYPE`, `ORDER_STATUS`, `STORE_ID`, `CUSTOMER_ID`, `BOOKING_INTERFACE`, `USER_LANGUAGE`, `CONTACT_GUEST_ID`, `CONTACT_FIRST_NAME`, `CONTACT_LAST_NAME`, `CONTACT_PHONE`, `CONTACT_EMAIL`, `CONTACT_GOVERNMENT_ID`, `AGENCY_IATA_NUMBER`, `PAYMENT_SESSION_ID`, `CASL`, `CREATE_DATE_TIME`, `LAST_MODIFIED_DATE_TIME`, `VERSION`, `INSTALLMENT_PERIOD`, `FROM_CART`, `REG_SUPPORTED`) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)]; Duplicate entry \u0027123456789\u0027 for key \u0027UQ_BOOKING_ORDER_ID\u0027","orderId":"123456789"}]} org.springframework.web.client.HttpClientErrorException$BadRequest: 400