我们有几个使用Spring MVC的REST应用程序。部署后不时启动某些应用程序的时间。当我们的Javascript客户端尝试访问资源URL时,它会获得404状态代码。因此,它假设该资源不存在。更适合我们的是Tomcat响应中返回的http状态500。是否可以更改此默认的Tomcat行为?
我发现JBoss有类似问题(使用嵌入式Tomcat),但没有回答: https://serverfault.com/questions/367986/mod-jk-fails-to-detect-error-state-because-jboss-gives-404-not-500
答案 0 :(得分:0)
如果您在Tomcat服务器前面有某种代理(例如apache或nginx),我相信它可以配置为将404转换为不同的状态代码和错误页面。如果您没有任何代理或希望解决方案保持独立:
由于您使用的是Spring,我猜您使用web.xml
中的ContextLoaderListener
来引导它:
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
此类负责引导Spring,这是在大多数情况下导致应用程序启动失败的步骤。只需扩展该类并吞下任何异常,使其永远不会到达servlet容器,因此Tomcat不会认为您的应用程序部署失败:
public class FailSafeLoaderListener extends ContextLoaderListener {
private static final Logger log = LoggerFactory.getLogger(FailSafeLoaderListener.class);
@Override
public void contextInitialized(ServletContextEvent event) {
try {
super.contextInitialized(event);
} catch (Exception e) {
log.error("", e);
event.getServletContext().setAttribute("deployException", e);
}
}
}
代码非常简单 - 如果Spring初始化失败,请记录异常并将其全局存储在ServletContext
中。新加载程序必须替换web.xml
中的旧加载程序:
<listener>
<listener-class>com.blogspot.nurkiewicz.download.FailSafeLoaderListener</listener-class>
</listener>
现在你所要做的就是从全局过滤器中的servlet上下文中读取该属性,如果应用程序无法启动Spring,则拒绝所有请求:
public class FailSafeFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {}
@Override
public void destroy() {}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
Exception deployException = (Exception) request.getServletContext().getAttribute("deployException");
if (deployException == null) {
chain.doFilter(request, response);
} else {
((HttpServletResponse) response).sendError(500, deployException.toString());
}
}
}
将此过滤器映射到所有请求(或者可能只有控制器?):
<filter-mapping>
<filter-name>failSafeFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
解决方案可能不是您想要的,但我给您一个通用的,有效的例子。
答案 1 :(得分:0)
是的,有可能会有一些变化。
我们做什么:
编写一个类似于:
的servletif (req.getContextPath().isEmpty()){
resp.setStatus(HttpServletResponse.SC_SERVICE_UNAVAILABLE);
} else {
resp.setStatus(HttpServletResponse.SC_NOT_FOUND);
}
将包含此类的jar放入tomcat lib。
更改conf / web.xml以添加servlet并将其映射到*.404
将全局错误404
设置为/404.404
。
<error-page>
<error-code>404</error-code>
<location>/404.404</location>
</error-page>
将使用root应用程序和所有已部署的应用程序调用您的servlet。