简体   繁体   English

发生异常时未调用 ResponseEntityExceptionHandler

[英]ResponseEntityExceptionHandler is not getting called when exception occurs

I am new to spring.我是 spring 的新手。 I am developing a REST api with spring webmvc.我正在使用 spring webmvc 开发 REST api。 For Error Handling I got this link http://docs.spring.io/spring/docs/3.2.x/spring-framework-reference/html/mvc.html#mvc-ann-rest-spring-mvc-exceptions对于错误处理,我得到了这个链接http://docs.spring.io/spring/docs/3.2.x/spring-framework-reference/html/mvc.html#mvc-ann-rest-spring-mvc-exceptions

I have tried to use ResponseEntityExceptionHandler in my project.我曾尝试在我的项目中使用 ResponseEntityExceptionHandler。 but whenever my controller throws exception it never reaches to this ResponseEntityExceptionHandler.但每当我的 controller 抛出异常时,它永远不会到达这个 ResponseEntityExceptionHandler。

Following are my code snippet以下是我的代码片段

Controller 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;
    }
}

Exceptions例外

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);
    }
}

exceptionhandler异常处理程序

@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);
    }
}

dispatcher servlet调度程序 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.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>

First, check that your @ControllerAdvice annotated class is taken into account by your configuration: is it located in a package that's scanned by Spring?首先,检查您的配置是否考虑了您的@ControllerAdvice注释类:它是否位于 Spring 扫描的包中? Did you declare it as a bean in any other way?您是否以其他方式将其声明为 bean?

Also, you don't need to extend ResponseEntityExceptionHandler if you don't need all the exception mappings it provides.此外,如果您不需要它提供的所有异常映射,则不需要扩展ResponseEntityExceptionHandler

A simpler way to write your exception handling:编写异常处理的更简单方法:

@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");
    }
}

Note that the ResponseEntity builder API has been in introduced in Spring 4.1, but you can use the regular constructor on 4.0.x.请注意, ResponseEntity builder API 已在 Spring 4.1 中引入,但您可以在 4.0.x 上使用常规构造函数。

I got the same issue in Spring WebMVC 4.2.5.我在 Spring WebMVC 4.2.5 中遇到了同样的问题。 The reason was throwExceptionIfNoHandlerFound parameter of DispatcherServlet .原因是DispatcherServletthrowExceptionIfNoHandlerFound参数。 By default it's value is false , so all errors generates HttpServletResponse.SC_NOT_FOUND servlet response and no exceptions throwes.默认情况下,它的值为false ,因此所有错误都会生成HttpServletResponse.SC_NOT_FOUND servlet 响应,并且不会抛出异常。

After I set it to true, my @ExceptionHandlers started to work将其设置为 true 后,我的@ExceptionHandlers开始工作

The issue is that your @ExceptionHandler declares ResourceNotFoundException whereas as a parameter to the handleResourceNotFound you expect RuntimeException.问题是您的@ExceptionHandler 声明了ResourceNotFoundException,而作为handleResourceNotFound 的参数,您期望RuntimeException。 The parameter exception and the value of ExceptionHandler should match.参数 exception 和 ExceptionHandler 的值应该匹配。

So it should be:所以应该是:

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

Some workarounds,一些解决方法,

  • Double check that you use the correct signature for your overriding method.仔细检查您是否为覆盖方法使用了正确的签名。
  • If you use any IDE, check if there is any @Override mark/sign/arrow that will ensure your override is valid.如果您使用任何 IDE,请检查是否有任何 @Override 标记/符号/箭头可以确保您的覆盖有效。
  • Check if you already extend the ResponseEntityExceptionHandler from another class of your project OR from any other class of your dependencies.检查您是否已经从项目的另一个类或依赖项的任何其他类扩展了ResponseEntityExceptionHandler
  • Put a breakpoint to the ResponseEntityExceptionHandler::handleException method.ResponseEntityExceptionHandler::handleException方法中放置一个断点。
  • For the NoHandlerFoundException you should configure the DispatcherServlet to throw and exception if it doesn't find any handlers, link here .对于NoHandlerFoundException ,您应该将 DispatcherServlet 配置为在找不到任何处理程序时抛出异常,请在此处链接

There are some reported situations where both ResponseEntityExceptionHandler and @ControllerAdvice didn't work.有一些报告的情况是ResponseEntityExceptionHandler@ControllerAdvice都不起作用。

Both of them are supposed to compile the methods annotated with @ExceptionHandler under the class into a common place where all the controllers can refer from.他们都应该将类下带有@ExceptionHandler注解的方法编译到所有控制器都可以引用的公共位置。

If it doesn't work for you.如果它不适合你。 You can add you @ExceptionHandler methods into a common AbstractController class which is extended by all other controllers.您可以将@ExceptionHandler方法添加到由所有其他控制器扩展的通用AbstractController类中。

You just need some configuration你只需要一些配置

In the application.properties or application.yml :在 application.properties 或 application.yml 中:

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

on springboot load your configuration file :在 springboot 上加载您的配置文件:

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

Provide an @ExceptionHandler method for handling internal Spring MVC exceptions.提供一个@ExceptionHandler方法来处理内部 Spring MVC 异常。 This method returns a ResponseEntity for writing to the response with a message converter, in contrast to DefaultHandlerExceptionResolver which returns a ModelAndView .此方法返回一个ResponseEntity用于使用消息转换器写入响应,而DefaultHandlerExceptionResolver返回一个ModelAndView

To improve on @Javasick's answer which worked for me.改进@Javasick 对我有用的答案。

How to setThrowExceptionIfNoHandlerFound to true.如何将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