Tomcat - 当应用程序没有正确部署时,如何获取http 500而不是404?

时间:2012-05-14 19:32:23

标签: java tomcat deployment http-status-codes

我们有几个使用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

2 个答案:

答案 0 :(得分:0)

HTTP代理

如果您在Tomcat服务器前面有某种代理(例如),我相信它可以配置为将404转换为不同的状态代码和错误页面。如果您没有任何代理或希望解决方案保持独立:

自定义Spring加载程序和servlet过滤器

由于您使用的是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)

是的,有可能会有一些变化。

我们做什么:

  • 编写一个类似于:

    的servlet
    if (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。