簡體   English   中英

Spring引導不使用@ControllerAdvice覆蓋Exception

[英]Spring boot not overriding Exception using @ControllerAdvice

我希望從控制器建議方面拋出一個標准的自定義異常但由於某種原因我的自定義異常沒有被spring boot(1.3.3-RELEASE)捕獲。

這是我的代碼:

我的測試

@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(MyApplication.class)
@WebIntegrationTest("server.port:9000") 
public class ControllerTest {
    private final String URL = "http://localhost:9000";

    @Test
    public void testCustomExceptionResponse() {
        // Invoke my controller generating some exception
        Map error = restTemplate.getForObject(URL+"/exception/", Map.class);
        assertTrue(error.get("exception").contains("MyCustomException"));
    }
}

控制器

@RequestMapping(value = "/", method = RequestMethod.GET)
public List<Object> findAll() throws Exception {
    // generate whatever exception here
    if (1<2) throw new IllegalIdentifierException("test whatever exception");
    return ccRepository.findByActive(true);
}

GlobalExceptionHandler使用@ControllerAdvice注釋

@ControllerAdvice
public class GlobalExceptionHandler {
    private static final Logger logger = LoggerFactory.getLogger(GlobalExceptionHandler.class);

    // Catch whatever exception to throw my custom exception
    @ExceptionHandler(Exception.class)
    public void handleException(Exception ex) throws Exception {
        logger.error("Exception Occured: ", ex);
        throw new MyCustomException(ex.getLocalizedMessage());
    }
}

我已經調試了代碼並且正在執行handleException方法,但奇怪的是拋出了MyCustomException,但控制器響應返回拋出的原始異常:

{timestamp=1473963128439, status=500, error=Internal Server Error, exception=org.hibernate.metamodel.relational.IllegalIdentifierException, message=test whatever exception, path=/exception/}

我期待有這樣的事情:

exception=com.myapp.MyCustomException

據我所知,控制器建議是捕獲控制器中所有異常的通用方法,以便綁定一些邏輯(在我的情況下是記錄器),然后我使用自定義異常自定義意外異常。

我錯過了Spring Boot如何處理異常的任何內容?

這不完全是ControllerAdvice的目的。

怎么了

  • 你拋出IllegalIdentifierException
  • 你在ControllerAdvice中捕獲它
  • 自拋出MyCustomException以來,handleException未完成
  • 這會在DispatcherServlet中引發異常,並將原始異常(IllegalIdentifierException)作為根本原因。

你應該做什么

Controller Advice用於在出現錯誤時返回有效的Http響應。

例如,您可以將其更改為:

@ControllerAdvice
public class GlobalExceptionHandler {
    @ExceptionHandler(Exception.class)
    public ResponseEntity<String> handleException(Exception ex) throws Exception {
        System.out.println("Exception Occured: " + ex);
        return ResponseEntity
                .status(HttpStatus.INTERNAL_SERVER_ERROR)
                .body("Exception: " + ex.getLocalizedMessage());
    }
}

從而:

  • ControllerAdvice的方法將成功完成(返回響應);
  • DispatcherServlet會很高興你。
  • 原始異常不是新錯誤的根本原因,現在已成功吞並
  • 客戶端收到帶有HTTP錯誤代碼的消息“異常:測試任何異常”(我選擇了HttpStatus.INTERNAL_SERVER_ERROR)。

你可以用MockMvc測試它:

@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(Launcher.class)
@WebAppConfiguration
public class ControllerTest {
    @Autowired
    private WebApplicationContext webApplicationContext;

    @Test
    public void testCustomExceptionResponse() throws Exception {
        MockMvc mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build();

        mockMvc.perform(MockMvcRequestBuilders.get("/your/uri"))
        .andExpect(MockMvcResultMatchers.status().isInternalServerError())
        .andExpect(MockMvcResultMatchers.content().string("Exception: test whatever exception"));

        assertTrue(true);
    }
}

我剛剛根據您的代碼創建了一個示例項目,嘗試更改此行:

Map error = restTemplate.getForObject("/exception/", Map.class);

Map error = restTemplate.getForObject("http://localhost:9000/", Map.class); 

因為您的RequestMapping正在尋找/我認為其他一些方法正在處理您的http請求,這也解釋了hibernate錯誤消息,因為1<2始終返回true。

我的日志看起來像這樣:

2016-09-15 22:21:32.101 ERROR 7688 --- [nio-9000-exec-1] tonakai.GlobalExceptionHandler       : Exception Occured: 

tonakai.IllegalIdentifierException: test whatever exception
    at tonakai.SampleController.findAll(SampleController.java:19) ~[classes/:na]
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_102]
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_102]
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_102]
    at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_102]
    at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:221) ~[spring-web-4.2.5.RELEASE.jar:4.2.5.RELEASE]
    at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:136) ~[spring-web-4.2.5.RELEASE.jar:4.2.5.RELEASE]
    at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:110) ~[spring-webmvc-4.2.5.RELEASE.jar:4.2.5.RELEASE]
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:817) ~[spring-webmvc-4.2.5.RELEASE.jar:4.2.5.RELEASE]
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:731) ~[spring-webmvc-4.2.5.RELEASE.jar:4.2.5.RELEASE]
    at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85) ~[spring-webmvc-4.2.5.RELEASE.jar:4.2.5.RELEASE]
    at org.springframework.web.servlet.DispatcherServlet

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM