Handle error 404 with Spring controller

2019-01-07 16:49发布

问题:

I use @ExceptionHandler to handle exceptions thrown by my web app, in my case my app returns JSON response with HTTP status for error responses to the client.

However, I am trying to figure out how to handle error 404 to return a similar JSON response like with the one handled by @ExceptionHandler

Update:

I mean, when a URL that does not exist is accessed

回答1:

Simplest way to find out is use the following:

@ExceptionHandler(Throwable.class)
  public String handleAnyException(Throwable ex, HttpServletRequest request) {
    return ClassUtils.getShortName(ex.getClass());
  }

If the URL is within the scope of DispatcherServlet then any 404 caused by mistyping or anything else will be caught by this method but if the URL typed is beyond the URL mapping of the DispatcherServlet then you have to either use:

<error-page>
   <exception-type>404</exception-type>
   <location>/404error.html</location>
</error-page>

or

Provide "/" mapping to your DispatcherServlet mapping URL so as to handle all the mappings for the particular server instance.



回答2:

I use spring 4.0 and java configuration. My working code is:

@ControllerAdvice
public class MyExceptionController {
    @ExceptionHandler(NoHandlerFoundException.class)
    public ModelAndView handleError404(HttpServletRequest request, Exception e)   {
            ModelAndView mav = new ModelAndView("/404");
            mav.addObject("exception", e);  
            //mav.addObject("errorcode", "404");
            return mav;
    }
}

In JSP:

    <div class="http-error-container">
        <h1>HTTP Status 404 - Page Not Found</h1>
        <p class="message-text">The page you requested is not available. You might try returning to the <a href="<c:url value="/"/>">home page</a>.</p>
    </div>

For Init param config:

public class AppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
    @Override
    public void customizeRegistration(ServletRegistration.Dynamic registration) {
        registration.setInitParameter("throwExceptionIfNoHandlerFound", "true");
    }
}

Or via xml:

<servlet>
    <servlet-name>rest-dispatcher</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>
</servlet>

See Also: Spring MVC Spring Security and Error Handling



回答3:

With spring > 3.0 use @ResponseStatus

  @ResponseStatus(value = HttpStatus.NOT_FOUND)
  public class ResourceNotFoundException extends RuntimeException {
    ...
}

    @Controller
    public class MyController {
    @RequestMapping.....
    public void handleCall() {
        if (isFound()) {
        // do some stuff
        }
        else {
              throw new ResourceNotFoundException(); 
        }
    }
}


回答4:

public final class ResourceNotFoundException extends RuntimeException {

}


@ControllerAdvice
public class AppExceptionHandler {
    @ExceptionHandler(ResourceNotFoundException.class)
    @ResponseStatus(HttpStatus.NOT_FOUND)
    public String handleNotFound() {
        return "404";
    }
}

Just define an Exception, an ExceptionHandler, throw the Exception from your business code controller.



回答5:

You can use servlet standard way to handle 404 error. Add following code in web.xml

<error-page>
   <exception-type>404</exception-type>
   <location>/404error.html</location>
</error-page>