2016-11-15 87 views
2

我正在使用Spring 4 MVC創建REST API。 我希望我可以在請求無效端點時提供默認的JSON錯誤對象。 我讀過有關@ControllerAdvice和@ExceptionHandler,我想正確使用:@ControllerAdvice無法返回ResponseEntity <T>(T是POJO)

package com.yopyop.wackend.controller; 

import org.slf4j.Logger; 
import org.slf4j.LoggerFactory; 

import org.springframework.http.HttpHeaders; 
import org.springframework.http.HttpStatus; 
import org.springframework.http.MediaType; 
import org.springframework.http.ResponseEntity; 
import org.springframework.web.bind.annotation.ControllerAdvice; 
import org.springframework.web.bind.annotation.ExceptionHandler; 

import org.springframework.web.context.request.WebRequest; 
import org.springframework.web.servlet.NoHandlerFoundException; 

import com.yopyop.wackend.controller.ErrorResponse; 
import com.yopyop.wackend.service.NotFoundException; 


@ControllerAdvice 
public class ExceptionControllerAdvice { 

    @ExceptionHandler(Exception.class) 
    public ResponseEntity<ErrorResponse> exceptionHandler(Exception ex) { 

     ErrorResponse error = new ErrorResponse(); 
     error.setErrorCode(HttpStatus.INTERNAL_SERVER_ERROR.value()); 

     if (ex.getClass()==NotFoundException.class) { 
      error.setMessage("ExceptionControllerAdvice() Not found"); 
      error.setErrorCode(HttpStatus.NOT_FOUND.value()); 
      return new ResponseEntity<ErrorResponse>(error, HttpStatus.NOT_FOUND); 
     } 
     else { 
      error.setMessage("ExceptionControllerAdvice() " + ex.getClass() + "(" + ex.getMessage() + ")"); 
      error.setErrorCode(HttpStatus.INTERNAL_SERVER_ERROR.value()); 
     } 

     return new ResponseEntity<ErrorResponse>(error, HttpStatus.INTERNAL_SERVER_ERROR); 
    } 

    @ExceptionHandler({NoHandlerFoundException.class}) 
    ResponseEntity<ErrorResponse> handleNoHandlerFoundException(NoHandlerFoundException ex, 
      WebRequest request) { 

     HttpHeaders headers = new HttpHeaders(); 
     headers.setContentType(MediaType.APPLICATION_JSON); 

     ErrorResponse error = new ErrorResponse(); 
     error.setErrorCode(HttpStatus.INTERNAL_SERVER_ERROR.value()); 
     error.setMessage("ExceptionControllerAdvice() " + ex.getClass() + "(" + ex.getMessage() + ")"); 

     return new ResponseEntity<ErrorResponse>(error, HttpStatus.INTERNAL_SERVER_ERROR); 
    } 
} 

我的錯誤響應類是如下:

package com.yopyop.wackend.controller; 

public class ErrorResponse { 
    private int errorCode; 
    private String message; 

    public int getErrorCode() { 
     return errorCode; 
    } 
    public void setErrorCode(int errorCode) { 
     this.errorCode = errorCode; 
    } 
    public String getMessage() { 
     return message; 
    } 
    public void setMessage(String message) { 
     this.message = message; 
    } 
} 

我修改web.xml文件,以使NoHandlerFound拋出異常:

<!DOCTYPE web-app PUBLIC 
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" 
"http://java.sun.com/dtd/web-app_2_3.dtd" > 

<web-app> 
    <display-name>Wackend WebApp</display-name> 
    <servlet> 
<servlet-name>wackend</servlet-name> 
<servlet-class> 
    org.springframework.web.servlet.DispatcherServlet 
</servlet-class> 
<init-param> 
    <param-name>throwExceptionIfNoHandlerFound</param-name> 
    <param-value>true</param-value> 
</init-param> 

<load-on-startup>1</load-on-startup> 
</servlet> 

<servlet-mapping> 
<servlet-name>wackend</servlet-name> 
<url-pattern>/</url-pattern> 
</servlet-mapping> 
</web-app> 

Nevetheless,當接收到未映射端點的請求時,我得到:

> 22:47:28.545 [http-nio-8080-exec-15] DEBUG 
> o.s.web.servlet.DispatcherServlet - DispatcherServlet with name 
> 'wackend' processing GET request for [/wackend/swagger-ui.html] 
> 22:47:28.548 [http-nio-8080-exec-15] DEBUG 
> o.s.w.s.m.m.a.RequestMappingHandlerMapping - Looking up handler method 
> for path /swagger-ui.html 22:47:28.552 [http-nio-8080-exec-15] DEBUG 
> o.s.w.s.m.m.a.RequestMappingHandlerMapping - Returning handler method 
> [public void 
> com.yopyop.wackend.controller.DefaultController.unmappedRequest(javax.servlet.http.HttpServletRequest) 
> throws org.springframework.web.servlet.NoHandlerFoundException] 
> 22:47:28.552 [http-nio-8080-exec-15] DEBUG 
> o.s.b.f.s.DefaultListableBeanFactory - Returning cached instance of 
> singleton bean 'defaultController' 22:47:28.553 
> [http-nio-8080-exec-15] DEBUG o.s.web.servlet.DispatcherServlet - 
> Last-Modified value for [/wackend/swagger-ui.html] is: -1 22:47:28.566 
> [http-nio-8080-exec-15] DEBUG 
> o.s.w.s.m.m.a.ExceptionHandlerExceptionResolver - Resolving exception 
> from handler [public void 
> com.yopyop.wackend.controller.DefaultController.unmappedRequest(javax.servlet.http.HttpServletRequest) 
> throws org.springframework.web.servlet.NoHandlerFoundException]: 
> org.springframework.web.servlet.NoHandlerFoundException: No handler 
> found for GET /wackend/swagger-ui.html, headers={} 22:47:28.567 
> [http-nio-8080-exec-15] DEBUG o.s.b.f.s.DefaultListableBeanFactory - 
> Returning cached instance of singleton bean 
> 'exceptionControllerAdvice' 22:47:28.567 [http-nio-8080-exec-15] DEBUG 
> o.s.w.s.m.m.a.ExceptionHandlerExceptionResolver - Invoking 
> @ExceptionHandler method: 
> org.springframework.http.ResponseEntity<com.yopyop.wackend.controller.ErrorResponse> 
> com.yopyop.wackend.controller.ExceptionControllerAdvice.handleNoHandlerFoundException(org.springframework.web.servlet.NoHandlerFoundException,org.springframework.web.context.request.WebRequest) 
> 22:47:28.603 [http-nio-8080-exec-15] ERROR 
> o.s.w.s.m.m.a.ExceptionHandlerExceptionResolver - Failed to invoke 
> @ExceptionHandler method: 
> org.springframework.http.ResponseEntity<com.yopyop.wackend.controller.ErrorResponse> 
> com.yopyop.wackend.controller.ExceptionControllerAdvice.handleNoHandlerFoundException(org.springframework.web.servlet.NoHandlerFoundException,org.springframework.web.context.request.WebRequest) 
> org.springframework.web.HttpMediaTypeNotAcceptableException: Could not 
> find acceptable representation at 
> org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodProcessor.writeWithMessageConverters(AbstractMessageConverterMethodProcessor.java:134) 
> ~[spring-webmvc-4.1.6.RELEASE.jar:4.1.6.RELEASE] at 
> org.springframework.web.servlet.mvc.method.annotation.HttpEntityMethodProcessor.handleReturnValue(HttpEntityMethodProcessor.java:146) 
> ~[spring-webmvc-4.1.6.RELEASE.jar:4.1.6.RELEASE] at 
> org.springframework.web.method.support.HandlerMethodReturnValueHandlerComposite.handleReturnValue(HandlerMethodReturnValueHandlerComposite.java:71) 
> ~[spring-web-4.1.6.RELEASE.jar:4.1.6.RELEASE] [...] at 
> java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) 
> [na:1.8.0_101] at 
> java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) 
> [na:1.8.0_101] at 
> org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) 
> [tomcat-util.jar:8.0.36] at java.lang.Thread.run(Thread.java:745) 
> [na:1.8.0_101] 22:47:28.603 [http-nio-8080-exec-15] DEBUG 
> o.s.w.s.m.m.a.ExceptionHandlerExceptionResolver - Resolving exception 
> from handler [public void 
> com.yopyop.wackend.controller.DefaultController.unmappedRequest(javax.servlet.http.HttpServletRequest) 
> throws org.springframework.web.servlet.NoHandlerFoundException]: 
> org.springframework.web.servlet.NoHandlerFoundException: No handler 
> found for GET /wackend/swagger-ui.html, headers={} 22:47:28.603 
> [http-nio-8080-exec-15] DEBUG o.s.b.f.s.DefaultListableBeanFactory - 
> Returning cached instance of singleton bean 
> 'exceptionControllerAdvice' 22:47:28.603 [http-nio-8080-exec-15] DEBUG 
> o.s.w.s.m.m.a.ExceptionHandlerExceptionResolver - Invoking 
> @ExceptionHandler method: 
> org.springframework.http.ResponseEntity<com.yopyop.wackend.controller.ErrorResponse> 
> com.yopyop.wackend.controller.ExceptionControllerAdvice.handleNoHandlerFoundException(org.springframework.web.servlet.NoHandlerFoundException,org.springframework.web.context.request.WebRequest) 
> 22:47:28.604 [http-nio-8080-exec-15] ERROR 
> o.s.w.s.m.m.a.ExceptionHandlerExceptionResolver - Failed to invoke 
> @ExceptionHandler method: 
> org.springframework.http.ResponseEntity<com.yopyop.wackend.controller.ErrorResponse> 
> com.yopyop.wackend.controller.ExceptionControllerAdvice.handleNoHandlerFoundException(org.springframework.web.servlet.NoHandlerFoundException,org.springframework.web.context.request.WebRequest) 
> org.springframework.web.HttpMediaTypeNotAcceptableException: Could not 
> find acceptable representation at 
> org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodProcessor.writeWithMessageConverters(AbstractMessageConverterMethodProcessor.java:134) 
> ~[spring-webmvc-4.1.6.RELEASE.jar:4.1.6.RELEASE] at 
> org.springframework.web.servlet.mvc.method.annotation.HttpEntityMethodProcessor.handleReturnValue(HttpEntityMethodProcessor.java:146) 
> ~[spring-webmvc-4.1.6.RELEASE.jar:4.1.6.RELEASE] at 
> org.springframework.web.method.support.HandlerMethodReturnValueHandlerComposite.handleReturnValue(HandlerMethodReturnValueHandlerComposite.java:71) 
> ~[spring-web-4.1.6.RELEASE.jar:4.1.6.RELEASE]  at 
> org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:126) 
> ~[spring-webmvc-4.1.6.RELEASE.jar:4.1.6.RELEASE] [...] at 
> java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) 
> [na:1.8.0_101] at 
> org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) 
> [tomcat-util.jar:8.0.36] at java.lang.Thread.run(Thread.java:745) 
> [na:1.8.0_101] 22:47:28.604 [http-nio-8080-exec-15] DEBUG 
> o.s.w.s.m.a.ResponseStatusExceptionResolver - Resolving exception from 
> handler [public void 
> com.yopyop.wackend.controller.DefaultController.unmappedRequest(javax.servlet.http.HttpServletRequest) 
> throws org.springframework.web.servlet.NoHandlerFoundException]: 
> org.springframework.web.servlet.NoHandlerFoundException: No handler 
> found for GET /wackend/swagger-ui.html, headers={} 22:47:28.604 
> [http-nio-8080-exec-15] DEBUG 
> o.s.w.s.m.s.DefaultHandlerExceptionResolver - Resolving exception from 
> handler [public void 
> com.yopyop.wackend.controller.DefaultController.unmappedRequest(javax.servlet.http.HttpServletRequest) 
> throws org.springframework.web.servlet.NoHandlerFoundException]: 
> org.springframework.web.servlet.NoHandlerFoundException: No handler 
> found for GET /wackend/swagger-ui.html, headers={} 22:47:28.604 
> [http-nio-8080-exec-15] DEBUG o.s.web.servlet.DispatcherServlet - Null 
> ModelAndView returned to DispatcherServlet with name 'wackend': 
> assuming HandlerAdapter completed request handling 22:47:28.604 
> [http-nio-8080-exec-15] DEBUG o.s.web.servlet.DispatcherServlet - 
> Successfully completed request 

然後返回一個標準的Tomcat 404頁面。 請不就是:

  1. 回報新ResponseEntity(錯誤, HttpStatus.INTERNAL_SERVER_ERROR);

    會返回一個HTTP 500與空體(比Tomcat 默認頁面更好)

  2. 回報新ResponseEntity( 「活泉」, HttpStatus.INTERNAL_SERVER_ERROR);將作爲一個正文返回一個帶有woot的HTTP 500。

看起來像我的ErrorResponse類無法完成JSON映射。

除此之外,我使用了一個默認的控制器,但我想這是沒用的,因爲我使用@ControllerAdvice。我在這裏貼吧信息:

package com.yopyop.wackend.controller; 

import javax.servlet.http.HttpServletRequest; 

import org.springframework.http.HttpHeaders; 
import org.springframework.stereotype.Controller; 
import org.springframework.web.bind.annotation.RequestMapping; 
import org.springframework.web.servlet.NoHandlerFoundException; 

/** 
* Default controller that exists to return a proper REST response for unmapped requests. 
*/ 
@Controller 
public class DefaultController { 

    @RequestMapping("/**") 
    public void unmappedRequest(HttpServletRequest request) throws NoHandlerFoundException { 
     String uri = request.getRequestURI(); 
     String method = request.getMethod(); 
     HttpHeaders h = new HttpHeaders(); 

     throw new NoHandlerFoundException(method, uri, h); 
    } 
} 

我的REST API也利用ResponseEntity <>收益並返還適當的JSON有效載荷成功。

回答

0

我不知道答案是什麼,但也許問題是與JSON配置。起初你的@Controller不是@RestController,你沒有明確指定產生的東西。我希望你在你的要求中這樣做,所以春天知道該怎麼做。我認爲@Controller的mime類型是繼承並用於轉換的。

您可能嘗試在您的http消息轉換器中添加斷點。在每個轉換器中都有一個方法supports嘗試在此處捕獲您的代碼。檢查哪個轉換器返回true。如果超過一個條件,Spring會使用第一個。通過堆棧跟蹤,您可能會發現哪些轉換器可用於您的請求以及需要哪種轉換器。

http://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/http/converter/AbstractHttpMessageConverter.html#supports-java.lang.Class-

相關問題