我的应用程序中有几个相互独立的Spring Services。在以@PostConstruct
注释的服务的初始化方法中,将初始化对外部服务的某些依赖关系。但是,如果此初始化过程失败,则会显示错误消息,屏幕上显示消息500 javax.servlet.ServletException: Servlet.init() exception
,其服务的BeanCreationException
初始化的根本原因@PostConstruct
无法成功执行。
我知道在Bean初始化失败的情况下,该应用程序将不再保持一致,因此整个应用程序可能无法按预期运行。但是,由于服务与应用程序的其余部分是独立的,因此我想捕获此初始化异常,并仍然以某种维护模式访问该应用程序,在这种情况下,如果服务的页面无法初始化,则会出现错误屏幕,应该被访问。
我尝试了使用带有@ControllerAdvice
或@ExceptionHandler
方法注释的Global Controller Exception的几种方法,但是它们不会被触发。错误屏幕将立即显示。
另一种尝试是使用Filter
或HandlerExceptionResolver
,但在这种情况下都不会被触发。
经过一些研究,我发现一些讨论表明此错误是致命的,因此无法处理或缓存。同样,在将请求传递给控制器句柄方法或任何已配置的过滤器之前,似乎引发了异常,因此也不会触发控制器异常处理程序。
现在我的问题是:为了处理BeanCreationExceptions
,我还缺少其他方法吗?最终的解决方案应该以某种维护模式启动应用程序,当需要访问失败的Bean / Service时,它将提供一个错误屏幕,或者提供有关失败的初始化服务的信息。
在此先感谢任何有提示或进一步解释的人。
答案 0 :(得分:0)
我发现了一些变通办法,可能会帮助其他面临相同问题的人,所以我想分享我的方法。
我最终使用了@Conditional
批注(用于管理bean的创建)和在web.xml
中配置的客户错误页面的组合。
基本上,我在取决于外部资源的每项服务上都使用@Conditional
。条件检查是否可以初始化任何需要的外部依赖项。
如果Condition的matches
方法返回true
,则将创建用我的Condition类注释的服务,否则spring将忽略该服务的bean创建。
这是我的Condition实现的一个示例(我只是在matches
中执行服务的@PostConstruct
init
方法中包含的内容)
public class ModuleCondition implements Condition {
@Override
public boolean matches(ConditionContext arg0, AnnotatedTypeMetadata arg1) {
if (/*check external dependencies*/)
return true;
else
return false;
}
}
这是使用条件的示例:
@Service
@Conditional(value = ModuleCondition.class)
public class MyService {
...
}
为了在无法初始化服务接口的情况下处理404
错误,我使用了一个客户错误页面和一个CustomerErrorController
。 (我遵循了以下教程here)
因此,如果由于外部资源初始化失败而导致服务无法初始化,则会将用户转发到客户错误页面,通知用户当前所访问的模块不可用。