Spring-boot ErrorPage 不适用于独立 Tomcat
Spring-boot ErrorPage not working with standalone Tomcat
我仍在努力让 Spring-boot 错误页面的东西在部署了 WAR 文件的独立 tomcat 中完全工作。
我的配置class如下:
@Configuration
@ComponentScan
@EnableAutoConfiguration(exclude = [ GroovyTemplateAutoConfiguration, SecurityAutoConfiguration, ErrorMvcAutoConfiguration, JmxAutoConfiguration ] )
class Application extends SpringBootServletInitializer {
@Override protected SpringApplicationBuilder configure( SpringApplicationBuilder application ) {
application.sources( Application )
}
还有我的错误处理配置如下:
@Configuration
class ErrorConfiguration implements EmbeddedServletContainerCustomizer {
@Override public void customize( ConfigurableEmbeddedServletContainer container ) {
container.addErrorPages(new ErrorPage( HttpStatus.NOT_FOUND, "/errors/404" ))
}
此信息似乎已被使用,但并不像我预期的那样 - 如果我只是转到一个不存在的 URL 然后我会得到 tomcat 默认 404 页面 - 但是,Spring 似乎返回了我的 ErrorPage 路径,因为 Tomcat 页面如下所示:
HTTP Status 404 - //errors/404
type Status report
message //errors/404
description The requested resource is not available.
Apache Tomcat/7.0.54
如果我更改我的错误配置并使用不同的路径,那么该路径将作为 404 消息通过 - 有人知道我错过了什么吗?我希望消息类似于 "Not found" 和路径 /errors/404 用于解析 view/controller 以呈现错误页面。
更新
我在我的网络配置中将错误路径映射为标准视图控制器:
@Configuration
@EnableWebMvc
class WebMvcConfiguration extends WebMvcConfigurerAdapter {
/**
* Register static views that dont need controller calls - map URLs direct to views
*/
@Override public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/errors/404").setViewName("errors/404")
registry.addViewController("/errors/500").setViewName("errors/500")
}
此外,如果我直接进入浏览器中的错误路径 - /errors/404 - 然后我会得到我期望的错误页面。
更新 2
我创建了一个带有自动错误处理功能的虚拟 Spring 引导 Web 应用程序,并将其部署到我在 Eclipse 中运行的 tomcat,并且白标签错误页面显示正确。然后我将它部署到我的开发服务器 tomcat 并且白标错误页面停止工作(我看到默认的 tomcat 404 页面)。
我的 web.xml 在两者上是相同的(将 web.xml 从 eclipse 复制到开发服务器)并且 server.xml 在下面(实际上与 eclipse 版本基本相同)
<Server port="8005" shutdown="SHUTDOWN">
<Listener SSLEngine="on" className="org.apache.catalina.core.AprLifecycleListener"/>
<Listener className="org.apache.catalina.core.JasperListener"/>
<Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener"/>
<Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener"/>
<GlobalNamingResources>
<Resource auth="Container" description="User database that can be updated and saved" factory="org.apache.catalina.users.MemoryUserDatabaseFactory" name="UserDatabase" pathname="conf/tomcat-users.xml" type="org.apache.catalina.UserDatabase"/>
</GlobalNamingResources>
<Service name="Custom">
<Executor name="tomcatThreadPoolwr" minSpareThreads="4" maxThreads="500" namePrefix="catalina-execwr-"></Executor>
<Connector port="8081" protocol="org.apache.coyote.http11.Http11Protocol" connectionTimeout="20000" redirectPort="8443" executor="tomcatThreadPoolwr" maxThreads="10"></Connector>
<Connector port="9998" protocol="AJP/1.3" redirectPort="8445" maxThreads="500" tomcatAuthentication="false" connectionTimeout="21000"></Connector>
<Engine jvmRoute="custom" name="Custom" defaultHost="localhost">
<Realm className="org.apache.catalina.realm.LockOutRealm">
<Realm className="org.apache.catalina.realm.UserDatabaseRealm" resourceName="UserDatabase"></Realm>
</Realm>
<Host name="localhost" autoDeploy="true" deployOnStartup="true" unpackWARs="false" appBase="/tmp/dev/custom" workDir="/tmp/dev/custom/work" createDirs="true">
<Context docBase="/tmp/dev/ROOT" path="/" reloadable="true" override="true"/>
<Valve pattern="common" directory="/var/log/tmp" prefix="custom_access_log." className="org.apache.catalina.valves.AccessLogValve" suffix=".log" resolveHosts="false"/>
</Host>
</Engine>
</Service>
</Server>
此外:
- 如果我直接导航到 /error,我会看到白标签页面,所以端点工作正常
- 如果我在 webroot 中创建一个名为 "error" 的文件,它会被拾取并显示。所以看起来应用程序正在尝试正确地重新路由我的 404,但由于某种原因只是在寻找 "error" 文件,而不是应用程序中的 "error" 端点
更新 3
我已经进一步调查,即使我在本地使用完全相同的 server.xml 和 web.xml,干净的 tomcat 安装它仍然可以在本地工作。
我还看到请求的 RequestDispatch 似乎有问题。
如果我在我的开发服务器上运行以下代码(任何地方,但例如从控制器)它不起作用:
request.getRequestDispatcher("/errors/404").forward(request,response);
但以下内容确实如此:
servletContext.getRequestDispatcher("/errors/404").forward(request,response);
(其中请求和响应是 HttpServletRequest/Response 并且 servletContext 是一个自动装配的 ServletContext 对象)
以上两个示例在干净的本地 tomcat 安装上都可以正常工作 - 有什么想法可能会导致请求链接 RequestDispatcher 出现问题,而 ServletContext RequestDispatcher 仍然有效吗? ErrorPageFilter 使用请求链接的 RequestDispatcher 所以遇到了这个问题。
最后是因为在 tomcat appBase 中创建了一个 ROOT 目录(这是作为 WAR 部署过程的一部分创建的)- 看起来像这样然后引起了一些与两个 ROOT 上下文的混淆(WAR 被部署为 ROOT war)。
正在修复 tomcat 设置,因此它只有 WAR 文件,这开始工作了。
我仍在努力让 Spring-boot 错误页面的东西在部署了 WAR 文件的独立 tomcat 中完全工作。
我的配置class如下:
@Configuration
@ComponentScan
@EnableAutoConfiguration(exclude = [ GroovyTemplateAutoConfiguration, SecurityAutoConfiguration, ErrorMvcAutoConfiguration, JmxAutoConfiguration ] )
class Application extends SpringBootServletInitializer {
@Override protected SpringApplicationBuilder configure( SpringApplicationBuilder application ) {
application.sources( Application )
}
还有我的错误处理配置如下:
@Configuration
class ErrorConfiguration implements EmbeddedServletContainerCustomizer {
@Override public void customize( ConfigurableEmbeddedServletContainer container ) {
container.addErrorPages(new ErrorPage( HttpStatus.NOT_FOUND, "/errors/404" ))
}
此信息似乎已被使用,但并不像我预期的那样 - 如果我只是转到一个不存在的 URL 然后我会得到 tomcat 默认 404 页面 - 但是,Spring 似乎返回了我的 ErrorPage 路径,因为 Tomcat 页面如下所示:
HTTP Status 404 - //errors/404
type Status report
message //errors/404
description The requested resource is not available.
Apache Tomcat/7.0.54
如果我更改我的错误配置并使用不同的路径,那么该路径将作为 404 消息通过 - 有人知道我错过了什么吗?我希望消息类似于 "Not found" 和路径 /errors/404 用于解析 view/controller 以呈现错误页面。
更新 我在我的网络配置中将错误路径映射为标准视图控制器:
@Configuration
@EnableWebMvc
class WebMvcConfiguration extends WebMvcConfigurerAdapter {
/**
* Register static views that dont need controller calls - map URLs direct to views
*/
@Override public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/errors/404").setViewName("errors/404")
registry.addViewController("/errors/500").setViewName("errors/500")
}
此外,如果我直接进入浏览器中的错误路径 - /errors/404 - 然后我会得到我期望的错误页面。
更新 2
我创建了一个带有自动错误处理功能的虚拟 Spring 引导 Web 应用程序,并将其部署到我在 Eclipse 中运行的 tomcat,并且白标签错误页面显示正确。然后我将它部署到我的开发服务器 tomcat 并且白标错误页面停止工作(我看到默认的 tomcat 404 页面)。
我的 web.xml 在两者上是相同的(将 web.xml 从 eclipse 复制到开发服务器)并且 server.xml 在下面(实际上与 eclipse 版本基本相同)
<Server port="8005" shutdown="SHUTDOWN">
<Listener SSLEngine="on" className="org.apache.catalina.core.AprLifecycleListener"/>
<Listener className="org.apache.catalina.core.JasperListener"/>
<Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener"/>
<Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener"/>
<GlobalNamingResources>
<Resource auth="Container" description="User database that can be updated and saved" factory="org.apache.catalina.users.MemoryUserDatabaseFactory" name="UserDatabase" pathname="conf/tomcat-users.xml" type="org.apache.catalina.UserDatabase"/>
</GlobalNamingResources>
<Service name="Custom">
<Executor name="tomcatThreadPoolwr" minSpareThreads="4" maxThreads="500" namePrefix="catalina-execwr-"></Executor>
<Connector port="8081" protocol="org.apache.coyote.http11.Http11Protocol" connectionTimeout="20000" redirectPort="8443" executor="tomcatThreadPoolwr" maxThreads="10"></Connector>
<Connector port="9998" protocol="AJP/1.3" redirectPort="8445" maxThreads="500" tomcatAuthentication="false" connectionTimeout="21000"></Connector>
<Engine jvmRoute="custom" name="Custom" defaultHost="localhost">
<Realm className="org.apache.catalina.realm.LockOutRealm">
<Realm className="org.apache.catalina.realm.UserDatabaseRealm" resourceName="UserDatabase"></Realm>
</Realm>
<Host name="localhost" autoDeploy="true" deployOnStartup="true" unpackWARs="false" appBase="/tmp/dev/custom" workDir="/tmp/dev/custom/work" createDirs="true">
<Context docBase="/tmp/dev/ROOT" path="/" reloadable="true" override="true"/>
<Valve pattern="common" directory="/var/log/tmp" prefix="custom_access_log." className="org.apache.catalina.valves.AccessLogValve" suffix=".log" resolveHosts="false"/>
</Host>
</Engine>
</Service>
</Server>
此外:
- 如果我直接导航到 /error,我会看到白标签页面,所以端点工作正常
- 如果我在 webroot 中创建一个名为 "error" 的文件,它会被拾取并显示。所以看起来应用程序正在尝试正确地重新路由我的 404,但由于某种原因只是在寻找 "error" 文件,而不是应用程序中的 "error" 端点
更新 3
我已经进一步调查,即使我在本地使用完全相同的 server.xml 和 web.xml,干净的 tomcat 安装它仍然可以在本地工作。
我还看到请求的 RequestDispatch 似乎有问题。
如果我在我的开发服务器上运行以下代码(任何地方,但例如从控制器)它不起作用:
request.getRequestDispatcher("/errors/404").forward(request,response);
但以下内容确实如此:
servletContext.getRequestDispatcher("/errors/404").forward(request,response);
(其中请求和响应是 HttpServletRequest/Response 并且 servletContext 是一个自动装配的 ServletContext 对象)
以上两个示例在干净的本地 tomcat 安装上都可以正常工作 - 有什么想法可能会导致请求链接 RequestDispatcher 出现问题,而 ServletContext RequestDispatcher 仍然有效吗? ErrorPageFilter 使用请求链接的 RequestDispatcher 所以遇到了这个问题。
最后是因为在 tomcat appBase 中创建了一个 ROOT 目录(这是作为 WAR 部署过程的一部分创建的)- 看起来像这样然后引起了一些与两个 ROOT 上下文的混淆(WAR 被部署为 ROOT war)。
正在修复 tomcat 设置,因此它只有 WAR 文件,这开始工作了。