簡體   English   中英

發生異常時未調用 ResponseEntityExceptionHandler

[英]ResponseEntityExceptionHandler is not getting called when exception occurs

我是 spring 的新手。 我正在使用 spring webmvc 開發 REST api。 對於錯誤處理,我得到了這個鏈接http://docs.spring.io/spring/docs/3.2.x/spring-framework-reference/html/mvc.html#mvc-ann-rest-spring-mvc-exceptions

我曾嘗試在我的項目中使用 ResponseEntityExceptionHandler。 但每當我的 controller 拋出異常時,它永遠不會到達這個 ResponseEntityExceptionHandler。

以下是我的代碼片段

Controller

@Controller
@RequestMapping("/hello")
public class HelloController {  
    private static final Logger logger = Logger.getLogger(HelloController.class);
    @RequestMapping(value="/{name}", method=RequestMethod.GET)
    public @ResponseBody String greet(@PathVariable(value = "name")String name ) throws InvalidInputException, ResourceNotFoundException{
        logger.info("start greet() "+name );
        System.out.println("start greet() "+name);
        String message = null;
        if("".equalsIgnoreCase(name))
        {
            throw new InvalidInputException("Invalid Input");
        }
        List<String> names = new ArrayList<String>();
        names.add("Harshal");
        names.add("Smitesh");
        if(names.contains(name)){
            message = "Hello "+ name;
        }else{
            throw new ResourceNotFoundException("Requested Resource not found");
        }
        System.out.println("end greet");
        logger.info("end greet()");
        return message;
    }
}

例外

package com.practice.errorhandlerdemo.exception;

public class InvalidInputException extends RuntimeException{
    private static final long serialVersionUID = 5489516240608806490L;
    public InvalidInputException() {
        super("Invalid Input");
    }
    public InvalidInputException(String message) {
        super(message);
    }
}

package com.practice.errorhandlerdemo.exception;

public class ResourceNotFoundException extends RuntimeException {
    private static final long serialVersionUID = -4041009155673754859L;
    public ResourceNotFoundException() {
        super("requested resource not found");
    }
    public ResourceNotFoundException(String message) {
        super(message);
    }
}

異常處理程序

@ControllerAdvice
public class RestResponseEntityExceptionHandler extends ResponseEntityExceptionHandler {
    private static final Logger logger = Logger.getLogger(RestResponseEntityExceptionHandler.class);
    @ExceptionHandler(value={ResourceNotFoundException.class})
    @ResponseStatus(value=HttpStatus.NOT_FOUND)
    protected ResponseEntity<Object> handleResourceNotFound(RuntimeException ex, WebRequest request){
        logger.info("start handleResourceNotFound()");
        String bodyOfResponse = "Requested resource does not found";
        HttpHeaders httpHeaders = new HttpHeaders();
        httpHeaders.setContentType(MediaType.APPLICATION_JSON);
        return handleExceptionInternal(ex, bodyOfResponse, httpHeaders, HttpStatus.NOT_FOUND, request);
    }

    @ExceptionHandler(value={InvalidInputException.class})
    @ResponseStatus(value=HttpStatus.BAD_REQUEST)
    protected ResponseEntity<Object> handleInvalidInput(RuntimeException ex, WebRequest request){
        logger.info("start handleInvalidInput()");
        String bodyOfResponse = "Invalid Input";
        HttpHeaders httpHeaders = new HttpHeaders();
        httpHeaders.setContentType(MediaType.APPLICATION_JSON);
        return handleExceptionInternal(ex, bodyOfResponse, httpHeaders, HttpStatus.BAD_REQUEST, request);
    }
}

調度程序 servlet

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd http://www.springframework.org/schema/context  http://www.springframework.org/schema/context/spring-context-4.0.xsd">

   <context:component-scan base-package="com.practice.errorhandlerdemo.controller"/>
   <context:annotation-config/>  

</beans>

web.xml

<web-app>
    <display-name>ErrorHandlerDemo</display-name>
    <servlet>
        <servlet-name>dispatcher</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>/WEB-INF/my-servlet.xml</param-value>
        </init-param>
    </servlet>
    <servlet-mapping>
        <servlet-name>dispatcher</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>
</web-app>

首先,檢查您的配置是否考慮了您的@ControllerAdvice注釋類:它是否位於 Spring 掃描的包中? 您是否以其他方式將其聲明為 bean?

此外,如果您不需要它提供的所有異常映射,則不需要擴展ResponseEntityExceptionHandler

編寫異常處理的更簡單方法:

@ControllerAdvice
public class RestResponseEntityExceptionHandler {

    @ExceptionHandler(ResourceNotFoundException.class)
    protected ResponseEntity<String> handleResourceNotFound(ResourceNotFoundException ex){

      return ResponseEntity
              .status(HttpStatus.NOT_FOUND)
              .body("Requested resource does not found");
    }

    @ExceptionHandler(InvalidInputException.class)
    protected ResponseEntity<String> handleInvalidInput(InvalidInputException ex){

      return ResponseEntity
              .badRequest()
              .body("Invalid Input");
    }
}

請注意, ResponseEntity builder API 已在 Spring 4.1 中引入,但您可以在 4.0.x 上使用常規構造函數。

我在 Spring WebMVC 4.2.5 中遇到了同樣的問題。 原因是DispatcherServletthrowExceptionIfNoHandlerFound參數。 默認情況下,它的值為false ,因此所有錯誤都會生成HttpServletResponse.SC_NOT_FOUND servlet 響應,並且不會拋出異常。

將其設置為 true 后,我的@ExceptionHandlers開始工作

問題是您的@ExceptionHandler 聲明了ResourceNotFoundException,而作為handleResourceNotFound 的參數,您期望RuntimeException。 參數 exception 和 ExceptionHandler 的值應該匹配。

所以應該是:

@ExceptionHandler(value={ResourceNotFoundException.class})
protected ResponseEntity<Object> handleResourceNotFound(ResourceNotFoundException ex, WebRequest request){
    
}

一些解決方法,

  • 仔細檢查您是否為覆蓋方法使用了正確的簽名。
  • 如果您使用任何 IDE,請檢查是否有任何 @Override 標記/符號/箭頭可以確保您的覆蓋有效。
  • 檢查您是否已經從項目的另一個類或依賴項的任何其他類擴展了ResponseEntityExceptionHandler
  • ResponseEntityExceptionHandler::handleException方法中放置一個斷點。
  • 對於NoHandlerFoundException ,您應該將 DispatcherServlet 配置為在找不到任何處理程序時拋出異常,請在此處鏈接

有一些報告的情況是ResponseEntityExceptionHandler@ControllerAdvice都不起作用。

他們都應該將類下帶有@ExceptionHandler注解的方法編譯到所有控制器都可以引用的公共位置。

如果它不適合你。 您可以將@ExceptionHandler方法添加到由所有其他控制器擴展的通用AbstractController類中。

你只需要一些配置

在 application.properties 或 application.yml 中:

server.error.whitelabel.enabled=false
spring.mvc.throw-exception-if-no-handler-found=true
spring.resources.add-mappings=false

在 springboot 上加載您的配置文件:

@Configuration
@EnableWebMvc
@ComponentScan(basePackages = "xx.xxx.xxxx")
@PropertySource("classpath:application.yml")
public class WebAppConfig {
}

提供一個@ExceptionHandler方法來處理內部 Spring MVC 異常。 此方法返回一個ResponseEntity用於使用消息轉換器寫入響應,而DefaultHandlerExceptionResolver返回一個ModelAndView

改進@Javasick 對我有用的答案。

如何將ThrowExceptionIfNoHandlerFound 設置為true。

public class AppSetting extends AbstractAnnotationConfigDispatcherServletInitializer {
@NonNull
@Override
protected DispatcherServlet createDispatcherServlet(@NonNull WebApplicationContext servletAppContext) {
    final DispatcherServlet servlet = (DispatcherServlet) super.createDispatcherServlet(servletAppContext);
    servlet.setThrowExceptionIfNoHandlerFound(true);
    return servlet;
}

暫無
暫無

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

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