Java 百里香叶+;Spring启动:错误页

Java 百里香叶+;Spring启动:错误页,java,spring,spring-mvc,spring-boot,thymeleaf,Java,Spring,Spring Mvc,Spring Boot,Thymeleaf,我有一个基本的SpringBoot应用程序。使用Spring初始值设定项、嵌入式Tomcat、Thymeleaf模板引擎和作为可执行JAR文件的包 我想将所有应用程序错误重定向到一个公共页面。 我已经创建了这个控制器: @Controller public class AppErrorController implements ErrorController { /** * Error Attributes in the Application */ pri

我有一个基本的SpringBoot应用程序。使用Spring初始值设定项、嵌入式Tomcat、Thymeleaf模板引擎和作为可执行JAR文件的包

我想将所有应用程序错误重定向到一个公共页面。 我已经创建了这个控制器:

@Controller
public class AppErrorController implements ErrorController {

    /**
     * Error Attributes in the Application
     */
    private ErrorAttributes errorAttributes;

    private final static String ERROR_PATH = "/error";

    /**
     * Controller for the Error Controller
     * @param errorAttributes
     */
    public AppErrorController(ErrorAttributes errorAttributes) {
        this.errorAttributes = errorAttributes;
    }

    /**
     * Supports the HTML Error View
     * @param request
     * @return
     */
    @RequestMapping(value = ERROR_PATH, produces = "text/html")
    public ModelAndView errorHtml(HttpServletRequest request) {
        return new ModelAndView("/errors/error", getErrorAttributes(request, false));
    }

    /**
     * Supports other formats like JSON, XML
     * @param request
     * @return
     */
    @RequestMapping(value = ERROR_PATH)
    @ResponseBody
    public ResponseEntity<Map<String, Object>> error(HttpServletRequest request) {
        Map<String, Object> body = getErrorAttributes(request, getTraceParameter(request));
        HttpStatus status = getStatus(request);
        return new ResponseEntity<Map<String, Object>>(body, status);
    }

    /**
     * Returns the path of the error page.
     *
     * @return the error path
     */
    @Override
    public String getErrorPath() {
        return ERROR_PATH;
    }


    private boolean getTraceParameter(HttpServletRequest request) {
        String parameter = request.getParameter("trace");
        if (parameter == null) {
            return false;
        }
        return !"false".equals(parameter.toLowerCase());
    }

    private Map<String, Object> getErrorAttributes(HttpServletRequest request,
                                                   boolean includeStackTrace) {
        RequestAttributes requestAttributes = new ServletRequestAttributes(request);
        return this.errorAttributes.getErrorAttributes(requestAttributes,
                includeStackTrace);
    }

    private HttpStatus getStatus(HttpServletRequest request) {
        Integer statusCode = (Integer) request
                .getAttribute("javax.servlet.error.status_code");
        if (statusCode != null) {
            try {
                return HttpStatus.valueOf(statusCode);
            }
            catch (Exception ex) {
            }
        }
        return HttpStatus.INTERNAL_SERVER_ERROR;
    }

}
以及错误模板

<!DOCTYPE html SYSTEM "http://www.thymeleaf.org/dtd/xhtml1-strict-thymeleaf-spring4-4.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
    xmlns:th="http://www.thymeleaf.org">

<body>
    <h1>Support Friendly Error Page</h1>

    <!--  As we are using Thymeleaf, you might consider using
          ${#httpServletRequest.requestURL}. But that returns the path
          to this error page.  Hence we explicitly add the url to the
          Model in some of the example code. -->
    <p th:if="${url}">
        <b>Page:</b> <span th:text="${url}">Page URL</span>
    </p>

    <p th:if="${timestamp}" id='created'>
        <b>Occurred:</b> <span th:text="${timestamp}">Timestamp</span>
    </p>

    <p th:if="${status}">
        <b>Response Status:</b> <span th:text="${status}">status-code</span> <span
            th:if="${error}" th:text="'('+${error}+')'">error ...</span>
    </p>

    <p>Application has encountered an error. Please contact support on
        ...</p>

    <p>Support may ask you to right click to view page source.</p>

    <!--
      // Hidden Exception Details  - this is not a recommendation, but here is
      // how you hide an exception in the page using Thymeleaf
      -->
    <div th:utext="'&lt;!--'" th:remove="tag"></div>
    <div th:utext="'Failed URL: ' +  ${url}" th:remove="tag">${url}</div>
    <div th:utext="'Exception: ' + ${exception.message}" th:remove="tag">${exception.message}</div>
    <ul th:remove="tag">
        <li th:each="ste : ${exception.stackTrace}" th:remove="tag"><span
            th:utext="${ste}" th:remove="tag">${ste}</span></li>
    </ul>
    <div th:utext="'--&gt;'" th:remove="tag"></div>

</body>
</html>
这就是提出的解决方案的结果:

69995 [http-nio-8080-exec-5] ERROR org.thymeleaf.TemplateEngine - [THYMELEAF][http-nio-8080-exec-5] Exception processing template "/errors/error": Exception evaluating SpringEL expression: "exception.message" (/errors/error:39)
69995 [http-nio-8080-exec-5] ERROR o.a.c.c.C.[.[.[.[dispatcherServlet] - Servlet.service() for servlet dispatcherServlet threw exception
org.springframework.expression.spel.SpelEvaluationException: EL1008E: Property or field 'message' cannot be found on object of type 'java.lang.String' - maybe not public?
    at org.springframework.expression.spel.ast.PropertyOrFieldReference.readProperty(PropertyOrFieldReference.java:224)
    at org.springframework.expression.spel.ast.PropertyOrFieldReference.getValueInternal(PropertyOrFieldReference.java:94)
    at org.springframework.expression.spel.ast.PropertyOrFieldReference.access$000(PropertyOrFieldReference.java:46)
    at org.springframework.expression.spel.ast.PropertyOrFieldReference$AccessorLValue.getValue(PropertyOrFieldReference.java:375)
    at org.springframework.expression.spel.ast.CompoundExpression.getValueInternal(CompoundExpression.java:88)
    at org.springframework.expression.spel.ast.SpelNodeImpl.getValue(SpelNodeImpl.java:120)
    at org.springframework.expression.spel.standard.SpelExpression.getValue(SpelExpression.java:267)
    at org.thymeleaf.spring4.expression.SpelVariableExpressionEvaluator.evaluate(SpelVariableExpressionEvaluator.java:139)
    at org.thymeleaf.standard.expression.VariableExpression.executeVariable(VariableExpression.java:154)
    at org.thymeleaf.standard.expression.SimpleExpression.executeSimple(SimpleExpression.java:59)
    at org.thymeleaf.standard.expression.Expression.execute(Expression.java:103)
    at org.thymeleaf.standard.expression.AdditionExpression.executeAddition(AdditionExpression.java:92)
    at org.thymeleaf.standard.expression.ComplexExpression.executeComplex(ComplexExpression.java:55)
    at org.thymeleaf.standard.expression.Expression.execute(Expression.java:107)
    at org.thymeleaf.standard.expression.Expression.execute(Expression.java:133)
    at org.thymeleaf.standard.processor.attr.AbstractStandardUnescapedTextChildModifierAttrProcessor.getText(AbstractStandardUnescapedTextChildModifierAttrProcessor.java:70)
    at org.thymeleaf.processor.attr.AbstractUnescapedTextChildModifierAttrProcessor.getModifiedChildren(AbstractUnescapedTextChildModifierAttrProcessor.java:60)
    at org.thymeleaf.processor.attr.AbstractChildrenModifierAttrProcessor.processAttribute(AbstractChildrenModifierAttrProcessor.java:59)
    at org.thymeleaf.processor.attr.AbstractAttrProcessor.doProcess(AbstractAttrProcessor.java:87)
    at org.thymeleaf.processor.AbstractProcessor.process(AbstractProcessor.java:212)
    at org.thymeleaf.dom.Node.applyNextProcessor(Node.java:1017)
    at org.thymeleaf.dom.Node.processNode(Node.java:972)
    at org.thymeleaf.dom.NestableNode.computeNextChild(NestableNode.java:695)
    at org.thymeleaf.dom.NestableNode.doAdditionalProcess(NestableNode.java:668)
    at org.thymeleaf.dom.Node.processNode(Node.java:990)
    at org.thymeleaf.dom.NestableNode.computeNextChild(NestableNode.java:695)
    at org.thymeleaf.dom.NestableNode.doAdditionalProcess(NestableNode.java:668)
    at org.thymeleaf.dom.Node.processNode(Node.java:990)
    at org.thymeleaf.dom.NestableNode.computeNextChild(NestableNode.java:695)
    at org.thymeleaf.dom.NestableNode.doAdditionalProcess(NestableNode.java:668)
    at org.thymeleaf.dom.Node.processNode(Node.java:990)
    at org.thymeleaf.dom.Document.process(Document.java:93)
    at org.thymeleaf.TemplateEngine.process(TemplateEngine.java:1155)
    at org.thymeleaf.TemplateEngine.process(TemplateEngine.java:1060)
    at org.thymeleaf.TemplateEngine.process(TemplateEngine.java:1011)
    at org.thymeleaf.spring4.view.ThymeleafView.renderFragment(ThymeleafView.java:335)
    at org.thymeleaf.spring4.view.ThymeleafView.render(ThymeleafView.java:190)
    at org.springframework.web.servlet.DispatcherServlet.render(DispatcherServlet.java:1282)
    at org.springframework.web.servlet.DispatcherServlet.processDispatchResult(DispatcherServlet.java:1037)
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:980)
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:897)
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970)
    at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:861)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:635)
    at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:742)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    at org.apache.catalina.core.ApplicationDispatcher.invoke(ApplicationDispatcher.java:728)
    at org.apache.catalina.core.ApplicationDispatcher.processRequest(ApplicationDispatcher.java:469)
    at org.apache.catalina.core.ApplicationDispatcher.doForward(ApplicationDispatcher.java:392)
    at org.apache.catalina.core.ApplicationDispatcher.forward(ApplicationDispatcher.java:311)
    at org.apache.catalina.core.StandardHostValve.custom(StandardHostValve.java:395)
    at org.apache.catalina.core.StandardHostValve.status(StandardHostValve.java:254)
    at org.apache.catalina.core.StandardHostValve.throwable(StandardHostValve.java:349)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:175)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:80)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:342)
    at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:799)
    at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)
    at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:861)
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1455)
    at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
    at java.lang.Thread.run(Thread.java:745)
69996 [http-nio-8080-exec-5] ERROR o.a.c.c.C.[Tomcat].[localhost] - Exception Processing ErrorPage[errorCode=0, location=/error]
org.springframework.web.util.NestedServletException: Request processing failed; nested exception is org.thymeleaf.exceptions.TemplateProcessingException: Exception evaluating SpringEL expression: "exception.message" (/errors/error:39)
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:982)
    at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:861)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:635)
    at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:742)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    at org.apache.catalina.core.ApplicationDispatcher.invoke(ApplicationDispatcher.java:728)
    at org.apache.catalina.core.ApplicationDispatcher.processRequest(ApplicationDispatcher.java:469)
    at org.apache.catalina.core.ApplicationDispatcher.doForward(ApplicationDispatcher.java:392)
    at org.apache.catalina.core.ApplicationDispatcher.forward(ApplicationDispatcher.java:311)
    at org.apache.catalina.core.StandardHostValve.custom(StandardHostValve.java:395)
    at org.apache.catalina.core.StandardHostValve.status(StandardHostValve.java:254)
    at org.apache.catalina.core.StandardHostValve.throwable(StandardHostValve.java:349)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:175)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:80)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:342)
    at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:799)
    at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)
    at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:861)
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1455)
    at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
    at java.lang.Thread.run(Thread.java:745)
Caused by: org.thymeleaf.exceptions.TemplateProcessingException: Exception evaluating SpringEL expression: "exception.message" (/errors/error:39)
    at org.thymeleaf.spring4.expression.SpelVariableExpressionEvaluator.evaluate(SpelVariableExpressionEvaluator.java:161)
    at org.thymeleaf.standard.expression.VariableExpression.executeVariable(VariableExpression.java:154)
    at org.thymeleaf.standard.expression.SimpleExpression.executeSimple(SimpleExpression.java:59)
    at org.thymeleaf.standard.expression.Expression.execute(Expression.java:103)
    at org.thymeleaf.standard.expression.AdditionExpression.executeAddition(AdditionExpression.java:92)
    at org.thymeleaf.standard.expression.ComplexExpression.executeComplex(ComplexExpression.java:55)
    at org.thymeleaf.standard.expression.Expression.execute(Expression.java:107)
    at org.thymeleaf.standard.expression.Expression.execute(Expression.java:133)
    at org.thymeleaf.standard.processor.attr.AbstractStandardUnescapedTextChildModifierAttrProcessor.getText(AbstractStandardUnescapedTextChildModifierAttrProcessor.java:70)
    at org.thymeleaf.processor.attr.AbstractUnescapedTextChildModifierAttrProcessor.getModifiedChildren(AbstractUnescapedTextChildModifierAttrProcessor.java:60)
    at org.thymeleaf.processor.attr.AbstractChildrenModifierAttrProcessor.processAttribute(AbstractChildrenModifierAttrProcessor.java:59)
    at org.thymeleaf.processor.attr.AbstractAttrProcessor.doProcess(AbstractAttrProcessor.java:87)
    at org.thymeleaf.processor.AbstractProcessor.process(AbstractProcessor.java:212)
    at org.thymeleaf.dom.Node.applyNextProcessor(Node.java:1017)
    at org.thymeleaf.dom.Node.processNode(Node.java:972)
    at org.thymeleaf.dom.NestableNode.computeNextChild(NestableNode.java:695)
    at org.thymeleaf.dom.NestableNode.doAdditionalProcess(NestableNode.java:668)
    at org.thymeleaf.dom.Node.processNode(Node.java:990)
    at org.thymeleaf.dom.NestableNode.computeNextChild(NestableNode.java:695)
    at org.thymeleaf.dom.NestableNode.doAdditionalProcess(NestableNode.java:668)
    at org.thymeleaf.dom.Node.processNode(Node.java:990)
    at org.thymeleaf.dom.NestableNode.computeNextChild(NestableNode.java:695)
    at org.thymeleaf.dom.NestableNode.doAdditionalProcess(NestableNode.java:668)
    at org.thymeleaf.dom.Node.processNode(Node.java:990)
    at org.thymeleaf.dom.Document.process(Document.java:93)
    at org.thymeleaf.TemplateEngine.process(TemplateEngine.java:1155)
    at org.thymeleaf.TemplateEngine.process(TemplateEngine.java:1060)
    at org.thymeleaf.TemplateEngine.process(TemplateEngine.java:1011)
    at org.thymeleaf.spring4.view.ThymeleafView.renderFragment(ThymeleafView.java:335)
    at org.thymeleaf.spring4.view.ThymeleafView.render(ThymeleafView.java:190)
    at org.springframework.web.servlet.DispatcherServlet.render(DispatcherServlet.java:1282)
    at org.springframework.web.servlet.DispatcherServlet.processDispatchResult(DispatcherServlet.java:1037)
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:980)
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:897)
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970)
    ... 26 common frames omitted
Caused by: org.springframework.expression.spel.SpelEvaluationException: EL1008E: Property or field 'message' cannot be found on object of type 'java.lang.String' - maybe not public?
    at org.springframework.expression.spel.ast.PropertyOrFieldReference.readProperty(PropertyOrFieldReference.java:224)
    at org.springframework.expression.spel.ast.PropertyOrFieldReference.getValueInternal(PropertyOrFieldReference.java:94)
    at org.springframework.expression.spel.ast.PropertyOrFieldReference.access$000(PropertyOrFieldReference.java:46)
    at org.springframework.expression.spel.ast.PropertyOrFieldReference$AccessorLValue.getValue(PropertyOrFieldReference.java:375)
    at org.springframework.expression.spel.ast.CompoundExpression.getValueInternal(CompoundExpression.java:88)
    at org.springframework.expression.spel.ast.SpelNodeImpl.getValue(SpelNodeImpl.java:120)
    at org.springframework.expression.spel.standard.SpelExpression.getValue(SpelExpression.java:267)
    at org.thymeleaf.spring4.expression.SpelVariableExpressionEvaluator.evaluate(SpelVariableExpressionEvaluator.java:139)
并检查属性
getErrorAttributes(request,false)
,这些是属性,消息就在那里:

{timestamp=Sat May 20 13:58:56 CEST 2017, status=404, error=Not Found, message=No message available, path=/tdk/company/list}

您可以在
异常中检查空值

<div th:if="${exception != null}" 
 th:utext="'Exception: ' + ${exception.message}" th:remove="tag">
</div>

或者您可以使用速记:

 <div th:utext="'Exception: ' + ${exception?.message}" th:remove="tag"></div>

堆栈跟踪非常清晰,它“谈论”了这一行:

<div th:utext="'Exception: ' + ${exception.message}" th:remove="tag">${exception.message}</div>
${exception.message}
您的服务器似乎无法解析Thymeleaf页面

它找不到带有消息字段的异常对象

我试图找出将异常传递到模型中的确切位置,但没有找到它

此函数不执行以下操作:

private Map<String, Object> getErrorAttributes(HttpServletRequest request,
                                                   boolean includeStackTrace) {
        RequestAttributes requestAttributes = new ServletRequestAttributes(request);
        return this.errorAttributes.getErrorAttributes(requestAttributes,
                includeStackTrace);
    }
私有映射getErrorAttributes(HttpServletRequest请求,
布尔值(includeStackTrace){
RequestAttributes RequestAttributes=新的ServletRequestAttributes(请求);
返回此.errorAttributes.getErrorAttributes(requestAttributes,
includeStackTrace);
}
<div th:utext="'Exception: ' + ${exception.message}" th:remove="tag">${exception.message}</div>
private Map<String, Object> getErrorAttributes(HttpServletRequest request,
                                                   boolean includeStackTrace) {
        RequestAttributes requestAttributes = new ServletRequestAttributes(request);
        return this.errorAttributes.getErrorAttributes(requestAttributes,
                includeStackTrace);
    }