我仍在努力使Spring-boot错误页面的内容完全在带有已部署WAR文件的独立tomcat中工作。
我有一个配置类,如下所示:
@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似乎确实像Tomcat页面一样返回了我的ErrorPage路径看起来像这样:
HTTP Status 404 - //errors/404 type Status report message //errors/404 description The requested resource is not available. Apache Tomcat/7.0.54
如果我更改错误配置并使用其他路径,则该路径将作为404消息通过-有人知道我错过了什么吗?我期望该消息只是类似于“未找到”之类的东西,并且路径/ errors / 404将用于解析视图/控制器以呈现错误页面。
更新 我在我的Web配置中将错误路径映射为标准视图控制器:
@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 Boot Web应用程序,并将其部署到在Eclipse中运行的tomcat中,并且whitelabel错误页面正确显示。然后,将其部署到我的开发服务器tomcat上,whitelabel错误页面停止工作(我看到默认的tomcat 404页面)。
我的web.xml都是相同的(从eclipse复制了web.xml到开发服务器),而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>
此外:
更新3
我进行了进一步的调查,即使我在本地干净的tomcat安装上使用完全相同的server.xml和web.xml,它在本地仍然可以使用。
我还看到请求的RequestDispatch似乎有问题。
如果我在开发服务器上(在任何地方,但例如从控制器)运行以下代码,它将无法正常工作:
request.getRequestDispatcher("/errors/404").forward(request,response);
但是以下内容可以:
servletContext.getRequestDispatcher("/errors/404").forward(request,response);
(其中请求和响应是HttpServletRequest / Response,而ServletContext是自动连接的ServletContext对象)
上面的两个示例都在干净的本地tomcat安装上正常工作-在ServletContext RequestDispatcher仍然有效的情况下,有什么想法可能导致请求链接的RequestDispatcher出现问题?ErrorPageFilter使用请求链接的RequestDispatcher,因此遇到了此问题。
最后,这是由于在tomcat appBase中创建了一个ROOT目录(此目录是作为WAR部署过程的一部分而创建的)-看起来这随后引起了两个ROOT上下文的混淆(已部署WAR)作为根源战争)。
修复tomcat安装程序,使其仅具有预期的WAR文件,此文件开始起作用。