【问题标题】:can we modify method for error handling with status codes?我们可以使用状态码修改错误处理方法吗?
【发布时间】:2017-12-22 16:16:10
【问题描述】:

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

异常处理器控制器:

@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>

【问题讨论】:

    标签: spring spring-boot error-handling


    【解决方案1】:

    或者,您可以使用@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;
    }
    

    【讨论】:

    • 在这种情况下添加 @ResponseStatus(HttpStatus.BAD_REQUEST) 注释似乎没有帮助。
    【解决方案2】:

    HttpServletResponse作为参数添加到defaultErrorHandler方法并调用response.setStatusCode

    编辑

    为了将 404 视为异常,如果使用 Spring Boot,请设置 spring.mvc.throwExceptionIfNoHandlerFound = true。如果不使用 Spring Boot,请参阅this 线程。

    【讨论】:

    • 请参阅上面的代码更改。我已经按照建议包含了 HttpServletResponse,并向 HttpServletResponse 支持的所有状态代码添加了一个 HashMap,并为每个状态代码添加了适当的消息。但是对于无效的 URL 404 错误,error.jsp 页面仍然不显示状态代码和消息。请指教。
    • 什么都不显示,因为当出现 404 错误时,方法 defaultErrorHanddler 甚至不会触发。我知道这一点,因为我在方法中有一个 println 语句,它不会打印到控制台。
    • 我发现了另一篇讨论这个问题的帖子:stackoverflow.com/questions/28902374/… 它建议你做同样的事情。我在 application.properties 文件中添加了 spring.mvc.throw-exception-if-no-handler-found=true。这本身并没有做任何事情。然后我添加了 spring.resources.add-mappings=false。这一次,至少我得到了一些东西,但是显示的状态代码是 200,而不是 404。Firefox 中的 Firebug 正确显示 404。看起来我们走在正确的轨道上,但还没有完全到达那里。还有其他建议吗?
    • 另外,设置这两个属性时,显示的异常是; org.springframework.web.servlet.NoHandlerFoundException No Handler fund for GET localhost:8080/whatever 希望这会有所帮助。
    猜你喜欢
    • 2020-04-24
    • 2020-03-01
    • 1970-01-01
    • 1970-01-01
    • 2014-01-15
    • 2011-01-12
    • 2021-05-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多