我仍然在努力让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似乎正在返回我的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消息传递 - 有人知道我错过了什么吗?我希望该消息只是“未找到”以及用于解析视图/控制器以呈现错误页面的路径/错误/ 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在两者中是相同的(将web.xml从eclipse复制到dev服务器),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安装上正常工作 - 任何想法可能会导致请求链接的RequestDispatcher出现问题,而ServletContext RequestDispatcher仍然有效吗? ErrorPageFilter使用请求链接的RequestDispatcher,因此遇到了这个问题。
答案 0 :(得分:0)
最后它是因为在tomcat appBase中创建了一个ROOT目录(这是作为WAR部署过程的一部分而创建的) - 看起来这样会导致两个ROOT上下文混淆( WAR被部署为ROOT战争。)
修复tomcat设置,使其只有预期的WAR文件开始工作。