2017-02-26 144 views
2

在Spring MVC應用程序中,我試圖通過rest響應處理傳遞給客戶端的異常,但找不到任何工作解決方案。在客戶端處理REST異常

服務器側控制器:

@RestController 
public class MessageProducerController { 

    @Autowired 
    private MessageService service; 

    @RequestMapping(value = "/messageApp-api/getMessage/{id}", produces = "application/json") 
    public Message restGetMessage(@PathVariable long id) { 

     Message message = service.findSingleMessage(id).orElse(EMPTY_MESSAGE); 
     if (EMPTY_MESSAGE.equals(message)) { 
      throw new MessageNotFoundException(id); 
     } 

     return message; 
    } 
} 

異常類:

public class MessageNotFoundException extends RuntimeException { 
    public MessageNotFoundException(long id) { 
     super(String.format("Message id=%d not found", id)); 
    } 
} 

ApiError中類:

public class ApiError { 
    private HttpStatus status; 
    private String message; 

    public ApiError(HttpStatus status, String message) { 
     this.status = status; 
     this.message = message; 
    } 

    public HttpStatus getStatus() { 
     return status; 
    } 

    public String getMessage() { 
     return message; 
    } 
} 

RestResponseException類:

@Component 
@ControllerAdvice 
public class RestResponseException { 
    @ExceptionHandler(MessageNotFoundException.class) 
    public ResponseEntity<Object> messageNotFound(MessageNotFoundException e) { 
     ApiError apiError = new ApiError(HttpStatus.NOT_FOUND, e.getMessage()); 
     return new ResponseEntity<>(apiError, new HttpHeaders(), apiError.getStatus()); 
    } 
} 

客戶端控制器:

@Controller 
public class MessageClientController { 

    private static final String MESSAGE = "restMessage"; 
    private static final String MESSAGES = "restMessages"; 
    private static final String ERROR = "error"; 

    @RequestMapping(value = "/messageApp-api/getMessage/{id}") 
    public String restGetMessage(@PathVariable long id, Model model) { 

     String view = MESSAGE; 

     try { 
      RestTemplate rest = new RestTemplate(); 
      ResponseEntity<Message> response = 
        rest.getForEntity("http://localhost:80/messageApp-api/getMessage/{id}", Message.class, id); 

      if (HttpStatus.OK == response.getStatusCode()) { 
       model.addAttribute(MESSAGE, response.getBody()); 
      } else if (HttpStatus.NOT_FOUND == response.getStatusCode()) { 
       model.addAttribute(MESSAGE, EMPTY_MESSAGE); 
      } 
     } catch (Exception e) { 
      e.printStackTrace(); 
      view = ERROR; 
     } 

     return view; 
    } 
} 

的想法是檢查響應狀態,並根據其做出關於模型的進一步措施。但是,事實上,rest.getForEntity(「http://localhost:80/messageApp-api/getMessage/(編號)」,Message.class,ID)拋出了以下異常時,未發現有一些ID的消息:

org.springframework.web.client.HttpClientErrorException: 404 null 
    at org.springframework.web.client.DefaultResponseErrorHandler.handleError(DefaultResponseErrorHandler.java:91) 
    at org.springframework.web.client.RestTemplate.handleResponse(RestTemplate.java:667) 
    at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:620) 
    at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:580) 
    at org.springframework.web.client.RestTemplate.getForEntity(RestTemplate.java:312) 
    at messageApp.controllers.rest.MessageClientController.restGetMessage(MessageClientController.java:34) 
    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.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:220) 
    at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:134) 
    at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:116) 
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:827) 
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:738) 
    at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85) 
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:963) 
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:897) 
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970) 
    at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:861) 
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:622) 
    at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846) 
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:729) 
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:230) 
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165) 
    at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52) 
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:192) 
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165) 
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:317) 
    at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:127) 
    at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:91) 
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) 
    at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:114) 
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) 
    at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:137) 
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) 
    at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:111) 
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) 
    at org.springframework.security.web.authentication.rememberme.RememberMeAuthenticationFilter.doFilter(RememberMeAuthenticationFilter.java:150) 
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) 
    at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:170) 
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) 
    at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:63) 
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) 
    at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:200) 
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) 
    at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:116) 
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) 
    at org.springframework.security.web.csrf.CsrfFilter.doFilterInternal(CsrfFilter.java:100) 
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) 
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) 
    at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:197) 
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) 
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) 
    at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:64) 
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) 
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) 
    at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:105) 
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) 
    at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:56) 
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) 
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) 
    at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:214) 
    at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:177) 
    at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:346) 
    at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:262) 
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:192) 
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165) 
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:198) 
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:108) 
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:472) 
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:140) 
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79) 
    at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:620) 
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87) 
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:349) 
    at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:783) 
    at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66) 
    at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:789) 
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1455) 
    at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) 
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) 
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) 
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) 
    at java.lang.Thread.run(Thread.java:745) 

那麼,如何防止異常在被拋出的響應以及如何從響應中檢索httpStatus?

回答

3

這是一個我也遇到的錯誤觀念。看起來好像您只需在ResponseEntity中反思狀態代碼即可獲取錯誤。但這種情況並非如此。

您可以捕獲一個HttpStatusCodeException,只要響應狀態代碼大於等於400,就會拋出該異常。然後可以從異常中獲取狀態碼。

try { 
     RestTemplate rest = new RestTemplate(); 
     ResponseEntity<Message> response = 
       rest.getForEntity("http://localhost:80/messageApp-api/getMessage/{id}", Message.class, id); 

     model.addAttribute(MESSAGE, response.getBody()); 
    } catch (HttpStatusCodeException e) { 
     if (HttpStatus.NOT_FOUND == e.getStatusCode()) { 
      model.addAttribute(MESSAGE, EMPTY_MESSAGE); 
     } 
     //handle other errors here 
    } 

有兩個小類HttpStatusCodeException

HttpClientErrorException拋出客戶端錯誤(400 < =狀態碼< 500)

HttpServerErrorException被拋出服務器錯誤(狀態碼> = 500)