当服务器端出现故障时,因为数据库和应用程序不同步而不是出错并且应用程序崩溃spring / tomcat似乎吞下了异常并假装没有发生任何事情。
叫我疯了,但如果程序灾难性地失败,我希望它实际上是灾难性的失败!反正有关闭此行为?当服务器假装一切都很好时,当它刚刚被扔进日志中时,它真的会减慢开发速度。
如果这不是spring / tomcat的默认值,那么还有什么可能导致它? 不幸的是,我们正在使用大量的库和框架。春天将是通常的嫌疑人,但它可能是别的。
更新
它是我们使用SqlServerDataSource
连接的SQL Server数据库。 Hibernate在项目的某些部分使用,但用于在登录时查询数据库。在客户端,我们使用extjs,我们也使用ExtDirectSpring来注释客户端进行通信的方法。为了翻译线路上的数据,杰克逊将被extdirect json处理程序包裹起来。
有一些AOP的东西与记录异常有关,但删除该代码会导致相同的行为。
进一步更新
好吧让你的服务器崩溃不是一个好主意!请参阅下面的答案,了解我提出的中间立场。
答案 0 :(得分:1)
如果你真的想这样做(但恕我直言,你不应该...)你可以使用一个过滤器,一旦它让一个未捕获的异常消失,它就会阻止它。它可能是这样的:
public class CrashFilter implements Filter {
private boolean crashed = false;
private String msg = "Major problem : application stopped";
@Override
public void doFilter(ServletRequest sr, ServletResponse sr1, FilterChain fc) throws IOException, ServletException {
if (crashed) {
HttpServletResponse resp = (HttpServletResponse) sr1;
resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, msg);
return;
}
try {
fc.doFilter(sr, sr1);
}
catch (Exception ex) {
crashed = true;
throw new ServletException(ex);
}
}
// init and destroy omitted from brevity
}
答案 1 :(得分:1)
好的,我最后这样做了。我基本上已经使用了上面的想法,但认为有足够的额外发表我自己的答案。
事实证明你真的不应该像其他人建议的那样这样做,我在底部添加了一点来说出原因!
这是我的过滤器:
public class FailOnErrorFilter implements Filter
{
@Override
public void init(FilterConfig config) throws ServletException
{
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws IOException, ServletException
{
try {
filterChain.doFilter(request, response);
}
catch (Exception exception) {
System.exit(1);
}
}
@Override
public void destroy()
{
}
}
要使其正常工作,您必须修改web.xml:
<filter>
<filter-name>failingFilter</filter-name>
<filter-class>fullyQualified.FailOnErrorFilter</filter-class>
<async-supported>true</async-supported>
</filter>
<filter-mapping>
<filter-name>failingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
最上面一个定义过滤器+第二个定义使用它到处都是。
<强> ExtDirectSpring 强>
完成上述操作后,我意识到ExtDirectSpring是另一个罪魁祸首。它的默认行为是吞下服务器端方法中的所有异常。
我担心我将不得不修补图书馆,但幸好其他人已经抱怨过这个问题并在1.3.6中修复了。最初我尝试升级到最新版本但它破坏了大量代码!多么棒的图书馆。无论如何1.3.6增加了通过执行以下操作来关闭错误抑制的能力:
//this is to switch off blanket switching of exceptions in extdirect spring
@Component
public class NoExceptionHandling implements RouterExceptionHandler
{
@Override
public Object handleException(MethodInfo methodInfo, BaseResponse baseResponse, Exception e, HttpServletRequest httpServletRequest)
{
throw new RuntimeException(e);
}
}
顾名思义extdirectspring使用spring,因此不会使其依赖关系明显调用代码,但是如果你去挖掘它(在github上)。您将在RouterController中看到它在catch
中调用以下方法private Object handleException(MethodInfo methodInfo, BaseResponse response, Exception e, HttpServletRequest request) {
return configurationService.getRouterExceptionHandler().handleException(methodInfo, response, e, request);
}
路由器控制器执行此操作:
@Autowired(required = false)
private RouterExceptionHandler routerExceptionHandler;
public RouterExceptionHandler getRouterExceptionHandler() {
return routerExceptionHandler;
}
如果您不提供默认值,则设置默认值。
更新 - 为什么你不应该这样做
事实证明你真的不应该在tomcat应用程序中调用System.exit
。它不仅会降低您的应用程序,还会导致服务器退出。这会导致任何其他运行应用程序停止运行!
由于其他一些原因,它也不合适:
同样地:
我在做什么
错误已经写入了tomcat日志+数据库。
只是为了让事情变得更复杂,不出所料,原始的webapp太脆弱,不能掩盖错误,所以我保留了旧的错误抑制,因为我们目前还没有积极开发/修复它。