我们可以使用状态代码修改错误处理方法吗?

时间:2017-07-18 01:06:20

标签: spring spring-boot error-handling

我正在开发一个Spring Boot项目。我正在使用this post提供的名为ExceptionHandlerController的类检出代码,并在我的项目中尝试了它。它有效,但对于状态代码为400或500系列的错误,我需要包含状态代码。当我在浏览器地址字段中尝试一个简单的无效URL时,视图页面error.jsp会进行渲染,但不会根据模型信息访问状态代码。我已经包含了HttpServletResponse参数来获取状态代码,但代码和消息并未显示在404错误上。 defaultErrorHanddler方法甚至不会触发404错误。我们如何强制该方法触发400和500错误?

ExceptionHandlerController:

@ControllerAdvice
public class ExceptionHandlerController
{
   public static final String DEFAULT_ERROR_VIEW = "error";

   private static final HashMap<Integer, String> statusCodes = new HashMap<Integer, String>();

   static {
       statusCodes.put(HttpServletResponse.SC_OK, "OK");
       statusCodes.put(HttpServletResponse.SC_CREATED, "Created");
       statusCodes.put(HttpServletResponse.SC_ACCEPTED, "Accepted");
       statusCodes.put(HttpServletResponse.SC_NON_AUTHORITATIVE_INFORMATION, "Non-authoritative Information");
       statusCodes.put(HttpServletResponse.SC_NO_CONTENT, "No Content");
       statusCodes.put(HttpServletResponse.SC_RESET_CONTENT, "Reset Content");
       statusCodes.put(HttpServletResponse.SC_PARTIAL_CONTENT, "Partial Content");         
       statusCodes.put(HttpServletResponse.SC_BAD_REQUEST, "Bad Request");
       statusCodes.put(HttpServletResponse.SC_UNAUTHORIZED, "Unauthorized");
       statusCodes.put(HttpServletResponse.SC_PAYMENT_REQUIRED, "Payment Required");
       statusCodes.put(HttpServletResponse.SC_FORBIDDEN, "Forbidden");
       statusCodes.put(HttpServletResponse.SC_NOT_FOUND, "Not Found");
       statusCodes.put(HttpServletResponse.SC_METHOD_NOT_ALLOWED, "Method Not Allowed");
       statusCodes.put(HttpServletResponse.SC_NOT_ACCEPTABLE, "Not Acceptable");
       statusCodes.put(HttpServletResponse.SC_PROXY_AUTHENTICATION_REQUIRED, "Proxy Authentication Required");
       statusCodes.put(HttpServletResponse.SC_REQUEST_TIMEOUT, "Request Timeout");
       statusCodes.put(HttpServletResponse.SC_CONFLICT, "Conflict");
       statusCodes.put(HttpServletResponse.SC_GONE, "Gone");       
       statusCodes.put(HttpServletResponse.SC_LENGTH_REQUIRED, "Length Required");
       statusCodes.put(HttpServletResponse.SC_PRECONDITION_FAILED, "Precondition Failed");
       statusCodes.put(HttpServletResponse.SC_REQUEST_ENTITY_TOO_LARGE, "Request entity Too Large");
       statusCodes.put(HttpServletResponse.SC_REQUEST_URI_TOO_LONG, "Request-URI Too Long");
       statusCodes.put(HttpServletResponse.SC_UNSUPPORTED_MEDIA_TYPE, "Unsupported Media Type");
       statusCodes.put(HttpServletResponse.SC_REQUESTED_RANGE_NOT_SATISFIABLE, "Requested Range Not Satisfiable");
       statusCodes.put(HttpServletResponse.SC_EXPECTATION_FAILED, "Expectation Failed");
       statusCodes.put(HttpServletResponse.SC_PRECONDITION_FAILED, "Precondition Required");           
       statusCodes.put(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "Internal Server Error");
       statusCodes.put(HttpServletResponse.SC_NOT_IMPLEMENTED, "Not Implemented");
       statusCodes.put(HttpServletResponse.SC_BAD_GATEWAY, "Bad Gateway");
       statusCodes.put(HttpServletResponse.SC_SERVICE_UNAVAILABLE, "Service Unavailable");
       statusCodes.put(HttpServletResponse.SC_GATEWAY_TIMEOUT, "Gateway Timeout");
       statusCodes.put(HttpServletResponse.SC_HTTP_VERSION_NOT_SUPPORTED, "HTTP Version Not Supported");

   }  


   @ExceptionHandler(value={Exception.class, RuntimeException.class})
   public ModelAndView defaultErrorHanddler(HttpServletRequest request, Exception e, HttpServletResponse response)
   {
       ModelAndView mav = new ModelAndView(DEFAULT_ERROR_VIEW);
       int scode = response.getStatus();
       System.out.println("scode: " + scode);
       mav.addObject("statuscode", String.valueOf(scode));
       mav.addObject("message", statusCodes.get(scode));
       mav.addObject("datetime", new Date());
       mav.addObject("exception", e);
       mav.addObject("url", request.getRequestURL());
       return mav;
   }
}

的error.jsp:

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="ISO-8859-1"%>
<!DOCTYPE HTML>
<html>
<head>
<title></title>
...
</head>
<body>
<div class="container">
<h1>Error Details</h1> 
    <p>Status Code: ${statuscode}</p>
    <p>Message: ${message}</p>
    <p>TimeStamp: ${datetime}</p>
    <p>Exception: ${exception}</p>
    <p>URL: ${url}</p>
    <p><a href="/">Home Page</a></p>    
</div>
</body>
</html>

2 个答案:

答案 0 :(得分:2)

或者,您可以使用@ResponseStatus为方法添加注释,例如:

@ResponseStatus(HttpStatus.BAD_REQUEST)
@ExceptionHandler(value = {Exception.class, RuntimeException.class})
public ModelAndView defaultErrorHandler(HttpServletRequest request, Exception e) {
        ModelAndView mav = new ModelAndView(DEFAULT_ERROR_VIEW);

    mav.addObject("datetime", new Date());
    mav.addObject("exception", e);
    mav.addObject("url", request.getRequestURL());
    return mav;
}

答案 1 :(得分:1)

HttpServletResponse作为参数添加到defaultErrorHandler方法,然后致电response.setStatusCode

修改

如果要将404视为例外,如果使用Spring Boot,请设置spring.mvc.throwExceptionIfNoHandlerFound = true。如果不使用Spring Boot,请参阅this thread。