java - Spring Boot 2+ Thymeleaf 3.0.10 异常处理 - 无法返回 error.html

标签 java spring spring-mvc spring-boot thymeleaf

我正在使用 SpringBoot2 和 Thymeleaf 3.0.10 版本,我想通过使用 ErrorController 使用/error 路径来处理 thymeleaf 异常。我成功地将错误输入 Controller 。但它没有返回我的自定义错误 View 页面(/错误)。它返回我有错误的页面(/errorPageUrl)。

我的 Controller 类是

@Controller 
public class AppErrorController extends AbstractControllerImpl implements ErrorController {

private static final String PATH = "/error";

@Autowired
private ErrorAttributes errorAttributes;

@RequestMapping(value = PATH)
public ModelAndView error(HttpServletRequest request, HttpServletResponse response) {
    ModelAndView mav = new ModelAndView();
    ServletWebRequest webRequest = new ServletWebRequest(request);
    PageError pageError = new PageError(response.getStatus(), getErrorAttributes(webRequest, true), false);
    mav.addObject("pageError", pageError);
    mav.setViewName("common/error");
    log.error("Page Error: " + pageError.error + "\n" + pageError.trace);
    return mav;
}

@Override
public String getErrorPath() {
    return PATH;
}

private Map<String, Object> getErrorAttributes(ServletWebRequest request, boolean includeStackTrace) {
    return errorAttributes.getErrorAttributes(request, includeStackTrace);
}
}

这里我得到错误路径,然后重定向到“常见/错误”页面。但它正在重定向到另一个页面,我有错误片段“testing/testEntries”。

堆栈跟踪是

00:43:07,689 ERROR [io.undertow.request] (default task-21) UT005023: Exception handling request to /XXXX/error: org.springframework.web.util.NestedServletException: Request processing failed; nested exception is org.thymeleaf.exceptions.TemplateInputException: An error happened during template parsing (template: "class path resource [templates/common/error.html]")
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:982)
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:866)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:687)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:851)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:790)
at io.undertow.servlet.handlers.ServletHandler.handleRequest(ServletHandler.java:85)
at io.undertow.servlet.handlers.FilterHandler.handleRequest(FilterHandler.java:81)
at io.undertow.servlet.handlers.security.ServletSecurityRoleHandler.handleRequest(ServletSecurityRoleHandler.java:62)
at io.undertow.servlet.handlers.ServletDispatchingHandler.handleRequest(ServletDispatchingHandler.java:36)
at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
at io.undertow.servlet.handlers.ServletInitialHandler.dispatchRequest(ServletInitialHandler.java:274)
at io.undertow.servlet.handlers.ServletInitialHandler.dispatchToPath(ServletInitialHandler.java:209)
at io.undertow.servlet.spec.RequestDispatcherImpl.forwardImpl(RequestDispatcherImpl.java:221)
at io.undertow.servlet.spec.RequestDispatcherImpl.forwardImplSetup(RequestDispatcherImpl.java:147)
at io.undertow.servlet.spec.RequestDispatcherImpl.forward(RequestDispatcherImpl.java:111)
at org.springframework.boot.web.servlet.support.ErrorPageFilter.forwardToErrorPage(ErrorPageFilter.java:197)
at org.springframework.boot.web.servlet.support.ErrorPageFilter.handleException(ErrorPageFilter.java:180)
at org.springframework.boot.web.servlet.support.ErrorPageFilter.doFilter(ErrorPageFilter.java:145)
at org.springframework.boot.web.servlet.support.ErrorPageFilter.access$000(ErrorPageFilter.java:66)
at org.springframework.boot.web.servlet.support.ErrorPageFilter$1.doFilterInternal(ErrorPageFilter.java:105)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.springframework.boot.web.servlet.support.ErrorPageFilter.doFilter(ErrorPageFilter.java:123)
at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:61)
at io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:131)
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:200)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:61)
at io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:131)
at io.undertow.servlet.handlers.FilterHandler.handleRequest(FilterHandler.java:84)
at io.undertow.servlet.handlers.security.ServletSecurityRoleHandler.handleRequest(ServletSecurityRoleHandler.java:62)
at io.undertow.servlet.handlers.ServletDispatchingHandler.handleRequest(ServletDispatchingHandler.java:36)
at org.wildfly.extension.undertow.security.SecurityContextAssociationHandler.handleRequest(SecurityContextAssociationHandler.java:78)
at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
at io.undertow.servlet.handlers.security.SSLInformationAssociationHandler.handleRequest(SSLInformationAssociationHandler.java:131)
at io.undertow.servlet.handlers.security.ServletAuthenticationCallHandler.handleRequest(ServletAuthenticationCallHandler.java:57)
at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
at io.undertow.security.handlers.AbstractConfidentialityHandler.handleRequest(AbstractConfidentialityHandler.java:46)
at io.undertow.servlet.handlers.security.ServletConfidentialityConstraintHandler.handleRequest(ServletConfidentialityConstraintHandler.java:64)
at io.undertow.security.handlers.AuthenticationMechanismsHandler.handleRequest(AuthenticationMechanismsHandler.java:60)
at io.undertow.servlet.handlers.security.CachedAuthenticatedSessionHandler.handleRequest(CachedAuthenticatedSessionHandler.java:77)
at io.undertow.security.handlers.NotificationReceiverHandler.handleRequest(NotificationReceiverHandler.java:50)
at io.undertow.security.handlers.AbstractSecurityContextAssociationHandler.handleRequest(AbstractSecurityContextAssociationHandler.java:43)
at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
at org.wildfly.extension.undertow.security.jacc.JACCContextIdHandler.handleRequest(JACCContextIdHandler.java:61)
at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
at org.wildfly.extension.undertow.deployment.GlobalRequestControllerHandler.handleRequest(GlobalRequestControllerHandler.java:68)
at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
at io.undertow.servlet.handlers.ServletInitialHandler.handleFirstRequest(ServletInitialHandler.java:292)
at io.undertow.servlet.handlers.ServletInitialHandler.access$100(ServletInitialHandler.java:81)
at io.undertow.servlet.handlers.ServletInitialHandler$2.call(ServletInitialHandler.java:138)
at io.undertow.servlet.handlers.ServletInitialHandler$2.call(ServletInitialHandler.java:135)
at io.undertow.servlet.core.ServletRequestContextThreadSetupAction$1.call(ServletRequestContextThreadSetupAction.java:48)
at io.undertow.servlet.core.ContextClassLoaderSetupAction$1.call(ContextClassLoaderSetupAction.java:43)
at org.wildfly.extension.undertow.security.SecurityContextThreadSetupAction.lambda$create$0(SecurityContextThreadSetupAction.java:105)
at org.wildfly.extension.undertow.deployment.UndertowDeploymentInfoService$UndertowThreadSetupAction.lambda$create$0(UndertowDeploymentInfoService.java:1508)
at org.wildfly.extension.undertow.deployment.UndertowDeploymentInfoService$UndertowThreadSetupAction.lambda$create$0(UndertowDeploymentInfoService.java:1508)
at org.wildfly.extension.undertow.deployment.UndertowDeploymentInfoService$UndertowThreadSetupAction.lambda$create$0(UndertowDeploymentInfoService.java:1508)
at org.wildfly.extension.undertow.deployment.UndertowDeploymentInfoService$UndertowThreadSetupAction.lambda$create$0(UndertowDeploymentInfoService.java:1508)
at io.undertow.servlet.handlers.ServletInitialHandler.dispatchRequest(ServletInitialHandler.java:272)
at io.undertow.servlet.handlers.ServletInitialHandler.access$000(ServletInitialHandler.java:81)
at io.undertow.servlet.handlers.ServletInitialHandler$1.handleRequest(ServletInitialHandler.java:104)
at io.undertow.server.Connectors.executeRootHandler(Connectors.java:326)
at io.undertow.server.HttpServerExchange$1.run(HttpServerExchange.java:812)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:748)Caused by: org.thymeleaf.exceptions.TemplateInputException: An error happened during template parsing (template: "class path resource [templates/common/error.html]")
at org.thymeleaf.templateparser.markup.AbstractMarkupTemplateParser.parse(AbstractMarkupTemplateParser.java:241)
at org.thymeleaf.templateparser.markup.AbstractMarkupTemplateParser.parseStandalone(AbstractMarkupTemplateParser.java:100)
at org.thymeleaf.engine.TemplateManager.parseAndProcess(TemplateManager.java:666)
at org.thymeleaf.TemplateEngine.process(TemplateEngine.java:1098)
at org.thymeleaf.TemplateEngine.process(TemplateEngine.java:1072)
at org.thymeleaf.spring5.view.ThymeleafView.renderFragment(ThymeleafView.java:362)
at org.thymeleaf.spring5.view.ThymeleafView.render(ThymeleafView.java:189)
at org.springframework.web.servlet.DispatcherServlet.render(DispatcherServlet.java:1325)
at org.springframework.web.servlet.DispatcherServlet.processDispatchResult(DispatcherServlet.java:1069)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1008)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:925)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:974)
... 67 more Caused by: org.attoparser.ParseException: Error during execution of processor 'org.thymeleaf.spring5.processor.SpringInputGeneralFieldTagProcessor' (template: "testing/testEntries" - line 24, col 32)
at org.attoparser.MarkupParser.parseDocument(MarkupParser.java:393)
at org.attoparser.MarkupParser.parse(MarkupParser.java:257)
at org.thymeleaf.templateparser.markup.AbstractMarkupTemplateParser.parse(AbstractMarkupTemplateParser.java:230)
... 78 more

我查看了error.html。没关系,我在这里没有使用任何东西。我只是显示 PageError 类属性。

此错误 Controller 在 SpringBoot 1.5.7 和 Thymeleaf 2.x 上运行良好。 我在这里错过了什么吗?

更新 error.html

    <html xmlns:th="http://www.thymeleaf.org"
    xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity5"
    xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
    layout:decorate="~{common/layout}">
<head>
    <link rel="stylesheet" type="text/css" th:href="@{/css/common/error.css}" />
</head> 
<body>
    <!--/* This error page is shown if any exception occurs during the Thymeleaf processing of the page/view. Typically caused by a thymeleaf syntax error or null view objects */-->
    <th:block layout:fragment="topBar"></th:block>
    <th:block layout:fragment="sideBar"></th:block>

    <!--/* Error Page Content */--> 
    <th:block layout:fragment="content">
        <div id="errorInfo" class="container-fluid">
            <div class="header">
                <span class="prefix">Error </span>
                <span class="cls" th:text="${pageError?.status}"></span>: &nbsp;<span class="cls" th:text="${pageError?.error}"></span>
            </div>          
            <div class="header">
                <span class="msg" th:text="${pageError?.message}"></span>
            </div>
            <br/>
            <button type="button" class="btn btn-primary" id="btnDetail">Show Detail</button>
            <pre class="detail display-none" id="detailContent" th:text="${pageError?.trace}"></pre>
        </div>      
    </th:block> 
</body>
</html>

更新2 Pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<groupId>com.fami.app</groupId>
<artifactId>app-builder</artifactId>
<version>1.0.0</version>
<packaging>pom</packaging>

<name>app-builder</name>

<properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <poi.version>3.13</poi.version>
    <app.version>1.0.0</app.version>
</properties>

<profiles>
    <profile>
        <id>web</id>
        <activation>
            <activeByDefault>true</activeByDefault>
        </activation>
        <properties>
            <!-- This files should not exist. Will force it to not run tests -->
            <jUnitInclude>**/SkipTests.java</jUnitInclude>
        </properties>
    </profile>
    <profile>
        <!-- Profile to enable specific jUnits Test to be ran, This will be executed on certain regions in harvest to validate code. -->
        <id>smokeTest</id>
        <properties>
            <!-- This is the jUnit Test case to add your jUnit tests to. Please read the java doc on the file for more information -->
            <jUnitInclude>**/SkipTests.java</jUnitInclude>
        </properties>
    </profile>
</profiles>

<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>3.5.1</version>
            <configuration>
                <source>1.8</source>
                <target>1.8</target>
            </configuration>
        </plugin>
        <!-- Plugin to specify jUnit Tests-->
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-surefire-plugin</artifactId>
            <version>2.19.1</version>
            <configuration>
                <includes>
                    <!-- Parameter should be initialized in the profile section -->
                    <include>${jUnitInclude}</include>
                </includes>
            </configuration>
        </plugin>
    </plugins>
</build>

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-dependencies</artifactId>
            <version>2.0.6.RELEASE</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter</artifactId>
        <exclusions>
            <exclusion>
                <groupId>ch.qos.logback</groupId>
                <artifactId>logback-classic</artifactId>
            </exclusion>
            <exclusion>
                <groupId>org.slf4j</groupId>
                <artifactId>log4j-over-slf4j</artifactId>
            </exclusion>
            <exclusion>
                <groupId>org.apache.logging.log4j</groupId>
                <artifactId>log4j-to-slf4j</artifactId>
            </exclusion>
        </exclusions>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-aop</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-log4j2</artifactId>
    </dependency>
    <dependency>
        <groupId>com.oracle.jdbc</groupId>
        <artifactId>ojdbc7</artifactId>
        <version>12.1.0.2</version>
    </dependency>
    <dependency>
        <groupId>org.springframework.security</groupId>
        <artifactId>spring-security-web</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.security</groupId>
        <artifactId>spring-security-config</artifactId>
    </dependency>

    <dependency>
        <groupId>org.thymeleaf.extras</groupId>
        <artifactId>thymeleaf-extras-springsecurity5</artifactId>
    </dependency>

    <dependency>
        <groupId>nz.net.ultraq.thymeleaf</groupId>
        <artifactId>thymeleaf-layout-dialect</artifactId>
    </dependency>

    <!-- saxon - XSLT and XQuery Processor -->
    <dependency>
        <groupId>net.sourceforge.saxon</groupId>
        <artifactId>saxon</artifactId>
        <version>9.1.0.8</version>
    </dependency>
    <!-- saxon-dom - added this dependency for the print batch xml conversion -->
    <dependency>
        <groupId>net.sourceforge.saxon</groupId>
        <artifactId>saxon</artifactId>
        <version>9.1.0.8</version>
        <classifier>dom</classifier>
    </dependency>

    <!-- Oracle Wallet -->
    <dependency>
        <groupId>com.oracle.jdbc</groupId>
        <artifactId>oraclepki</artifactId>
        <version>12.1.0.2</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>com.oracle.jdbc</groupId>
        <artifactId>osdt_cert</artifactId>
        <version>12.1.0.2</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>com.oracle.jdbc</groupId>
        <artifactId>osdt_core</artifactId>
        <version>12.1.0.2</version>
        <scope>test</scope>
    </dependency>
    <!-- End Oracle Wallet -->
    <!-- apache common libraries -->
    <dependency>
        <groupId>org.apache.commons</groupId>
        <artifactId>commons-lang3</artifactId>
    </dependency>

    <dependency>
        <groupId>org.apache.commons</groupId>
        <artifactId>commons-collections4</artifactId>
        <version>4.1</version>
    </dependency>

    <dependency>
        <groupId>commons-beanutils</groupId>
        <artifactId>commons-beanutils</artifactId>
        <version>1.9.3</version>
    </dependency>

    <!-- HTTPClient - web client API -->
    <dependency>
        <groupId>org.apache.httpcomponents</groupId>
        <artifactId>httpclient</artifactId>
    </dependency>

    <dependency>
        <groupId>commons-io</groupId>
        <artifactId>commons-io</artifactId>
        <version>2.6</version>
    </dependency>

    <!-- jDom for XML processing -->
    <dependency>
        <groupId>org.jdom</groupId>
        <artifactId>jdom2</artifactId>
    </dependency>

    <dependency>
        <groupId>jaxen</groupId>
        <artifactId>jaxen</artifactId>
        <exclusions>
            <exclusion>
                <groupId>maven-plugins</groupId>
                <artifactId>maven-cobertura-plugin</artifactId>
            </exclusion>
            <exclusion>
                <groupId>maven-plugins</groupId>
                <artifactId>maven-findbugs-plugin</artifactId>
            </exclusion>
        </exclusions>
    </dependency>

</dependencies>

更新3

@Configuration
public class ThymeleafConfig {
@Bean
    public CustomThymeleafDialect myDialect() {
        return new CustomThymeleafDialect();
    }

    @Bean
    public ViewResolver getViewResolver() {
        ThymeleafViewResolver resolver = new ThymeleafViewResolver();
        resolver.setProducePartialOutputWhileProcessing(false);
        resolver.setTemplateEngine(getTemplateEngine());
        resolver.setCache(false);
        resolver.setOrder(1);
        return resolver;
    }

    @Bean
    public LayoutDialect layoutDialect() {
        return new LayoutDialect();
    }

    @Bean
    public SpringSecurityDialect securityDialect() {
        return new SpringSecurityDialect();
    }

    @Bean
    public ITemplateResolver getResolver() {
        SpringResourceTemplateResolver resolver = new SpringResourceTemplateResolver();
        resolver.setPrefix("classpath:/templates/");
        resolver.setSuffix(".html");
        resolver.setOrder(2);
        resolver.setCacheable(false);
        resolver.setTemplateMode(TemplateMode.HTML);
        return resolver;
    }

    @Bean
    public SpringTemplateEngine getTemplateEngine(){
        SpringTemplateEngine engine = new SpringTemplateEngine();
        engine.addDialect(layoutDialect());
        engine.addDialect(securityDialect());
        engine.addDialect(myDialect());
        engine.setTemplateResolver(getResolver());
        engine.setEnableSpringELCompiler(true);
        return engine;
    }
    }

更新5 此配置适用于语法错误,例如(缺少像这样的 anchor 的结束标记..),当涉及到像 th:field="*{test.testingString}"这样的绑定(bind)结果时,它不起作用..我是否缺少为此配置的内容?

最佳答案

nested exception is org.thymeleaf.exceptions.TemplateInputException: An error happened during template parsing (template: "class path resource [templates/common/error.html]

通过上述异常,您似乎在某处缺少结束标记。请检查您的 html 页面是否所有标记都正确关闭。

关于java - Spring Boot 2+ Thymeleaf 3.0.10 异常处理 - 无法返回 error.html,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53039513/

相关文章:

java - 连接重置错误 - REST 服务客户端

java - 源代码管理中的 Eclipse 保存操作

java - spring mvc,css 不工作

java - startRecording() 在未初始化的 AudioRecord 上调用

java - Tomcat 无法使用 cargo maven 启动组件

java - Spring REST 从路由中获取 Controller +方法?

java - 通用 DAO 实现, Controller 级别注入(inject)失败

java - 调用servlet方法时出现错误 "java.io.IOException: Server returned HTTP response code: 406"

java - spring mvc拦截器如何获取方法执行流程

java - Spring Security 3.2 Java配置