【问题标题】:Spring Boot: Exception Handling if mongo diconnects after application start upSpring Boot:如果应用程序启动后mongo断开连接,则异常处理
【发布时间】:2017-09-13 09:31:53
【问题描述】:

我的 Spring Boot 应用程序在启动过程中使用了 mongo,并且启动非常顺利。 现在启动后,我关闭了 mongo 并点击了我的应用程序的任何控制器。但是控制永远不会达到控制器级别因此@ControllerAdvice无法处理mongo异常。 我还尝试制作一个通用异常处理程序并像这样在 application.java 中注册该类

@Bean
public EmbeddedServletContainerCustomizer containerCustomizer() {

    return container -> {
        ErrorPage error401Page = new ErrorPage(HttpStatus.INTERNAL_SERVER_ERROR,"/error");
        container.addErrorPages(error401Page);
    };

只要 mongo 启动并运行,它就可以正常工作。 一旦 mongo 关闭,我会得到以下堆栈跟踪

org.springframework.data.mongodb.core.MongoExceptionTranslator.translateExceptionIfPossible(MongoExceptionTranslator.java:77)
org.springframework.data.mongodb.core.MongoTemplate.potentiallyConvertRuntimeException(MongoTemplate.java:2114)
org.springframework.data.mongodb.core.MongoTemplate.executeFindOneInternal(MongoTemplate.java:1904)
org.springframework.data.mongodb.core.MongoTemplate.doFindOne(MongoTemplate.java:1712)
org.springframework.data.mongodb.core.MongoTemplate.findById(MongoTemplate.java:636)
org.springframework.session.data.mongo.MongoOperationsSessionRepository.findSession(MongoOperationsSessionRepository.java:127)
org.springframework.session.data.mongo.MongoOperationsSessionRepository.getSession(MongoOperationsSessionRepository.java:78)
org.springframework.session.data.mongo.MongoOperationsSessionRepository.getSession(MongoOperationsSessionRepository.java:44)
org.springframework.session.web.http.SessionRepositoryFilter$SessionRepositoryRequestWrapper.getSession(SessionRepositoryFilter.java:326)
org.springframework.session.web.http.SessionRepositoryFilter$SessionRepositoryRequestWrapper.getSession(SessionRepositoryFilter.java:343)
org.springframework.session.web.http.SessionRepositoryFilter$SessionRepositoryRequestWrapper.getSession(SessionRepositoryFilter.java:214)
javax.servlet.http.HttpServletRequestWrapper.getSession(HttpServletRequestWrapper.java:255)
org.springframework.web.util.WebUtils.getSessionId(WebUtils.java:288)
org.springframework.web.servlet.FrameworkServlet.publishRequestHandledEvent(FrameworkServlet.java:1077)
org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1005)
org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:872)
javax.servlet.http.HttpServlet.service(HttpServlet.java:754)
org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846)
javax.servlet.http.HttpServlet.service(HttpServlet.java:847)
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:101)
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:101)
org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:208)
org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:177)
org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:346)
org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:262)
org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:99)
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:101)
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:101)
org.springframework.session.web.http.SessionRepositoryFilter.doFilterInternal(SessionRepositoryFilter.java:164)
org.springframework.session.web.http.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:80)
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:101)
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:101)
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:101)
org.springframework.boot.web.support.ErrorPageFilter.doFilter(ErrorPageFilter.java:112)
org.apache.logging.log4j.web.Log4jServletFilter.doFilter(Log4jServletFilter.java:64)
org.springframework.boot.web.support.ErrorPageFilter.forwardToErrorPage(ErrorPageFilter.java:187)
org.springframework.boot.web.support.ErrorPageFilter.handleException(ErrorPageFilter.java:170)
org.springframework.boot.web.support.ErrorPageFilter.doFilter(ErrorPageFilter.java:134)
org.springframework.boot.web.support.ErrorPageFilter.access$000(ErrorPageFilter.java:61)
org.springframework.boot.web.support.ErrorPageFilter$1.doFilterInternal(ErrorPageFilter.java:94)
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
org.springframework.boot.web.support.ErrorPageFilter.doFilter(ErrorPageFilter.java:112)
org.apache.logging.log4j.web.Log4jServletFilter.doFilter(Log4jServletFilter.java:71)

JBWEB000071:根本原因

com.mongodb.MongoTimeoutException:在等待与 ReadPreferenceServerSelector{readPreference=primary} 匹配的服务器时,在 30000 毫秒后超时。集群状态的客户端视图是 {type=STANDALONE, servers=[{address=localhost:27017, type=UNKNOWN, state=CONNECTING, exception={com.mongodb.MongoSocketOpenException: Exception opening socket}, 由 {java.net. ConnectException:连接被拒绝:连接}}]
    com.mongodb.connection.BaseCluster.createTimeoutException(BaseCluster.java:369)
    com.mongodb.connection.BaseCluster.selectServer(BaseCluster.java:101)
    com.mongodb.binding.ClusterBinding$ClusterBindingConnectionSource.(ClusterBinding.java:75)
    com.mongodb.binding.ClusterBinding$ClusterBindingConnectionSource.(ClusterBinding.java:71)
    com.mongodb.binding.ClusterBinding.getReadConnectionSource(ClusterBinding.java:63)
    com.mongodb.operation.OperationHelper.withConnection(OperationHelper.java:210)
    com.mongodb.operation.FindOperation.execute(FindOperation.java:482)
    com.mongodb.operation.FindOperation.execute(FindOperation.java:79)
    com.mongodb.Mongo.execute(Mongo.java:772)
    com.mongodb.Mongo$2.execute(Mongo.java:759)
    com.mongodb.DBCollection.findOne(DBCollection.java:777)
    com.mongodb.DBCollection.findOne(DBCollection.java:747)
    com.mongodb.DBCollection.findOne(DBCollection.java:694)
    org.springframework.data.mongodb.core.MongoTemplate$FindOneCallback.doInCollection(MongoTemplate.java:2143)
    org.springframework.data.mongodb.core.MongoTemplate$FindOneCallback.doInCollection(MongoTemplate.java:2127)
    org.springframework.data.mongodb.core.MongoTemplate.executeFindOneInternal(MongoTemplate.java:1901)
    org.springframework.data.mongodb.core.MongoTemplate.doFindOne(MongoTemplate.java:1712)
    org.springframework.data.mongodb.core.MongoTemplate.findById(MongoTemplate.java:636)
    org.springframework.session.data.mongo.MongoOperationsSessionRepository.findSession(MongoOperationsSessionRepository.java:127)
    org.springframework.session.data.mongo.MongoOperationsSessionRepository.getSession(MongoOperationsSessionRepository.java:78)
    org.springframework.session.data.mongo.MongoOperationsSessionRepository.getSession(MongoOperationsSessionRepository.java:44)
    org.springframework.session.web.http.SessionRepositoryFilter$SessionRepositoryRequestWrapper.getSession(SessionRepositoryFilter.java:326)
    org.springframework.session.web.http.SessionRepositoryFilter$SessionRepositoryRequestWrapper.getSession(SessionRepositoryFilter.java:343)
    org.springframework.session.web.http.SessionRepositoryFilter$SessionRepositoryRequestWrapper.getSession(SessionRepositoryFilter.java:214)
    javax.servlet.http.HttpServletRequestWrapper.getSession(HttpServletRequestWrapper.java:255)
    org.springframework.web.util.WebUtils.getSessionId(WebUtils.java:288)
    org.springframework.web.servlet.FrameworkServlet.publishRequestHandledEvent(FrameworkServlet.java:1077)
    org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1005)
    org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:872)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:754)
    org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:847)
    org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:101)
    org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:101)
    org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:208)
    org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:177)
    org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:346)
    org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:262)
    org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:99)
    org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:101)
    org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:101)
    org.springframework.session.web.http.SessionRepositoryFilter.doFilterInternal(SessionRepositoryFilter.java:164)
    org.springframework.session.web.http.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:80)
    org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:101)
    org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:101)
    org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:101)
    org.springframework.boot.web.support.ErrorPageFilter.doFilter(ErrorPageFilter.java:112)
    org.apache.logging.log4j.web.Log4jServletFilter.doFilter(Log4jServletFilter.java:64)
    org.springframework.boot.web.support.ErrorPageFilter.forwardToErrorPage(ErrorPageFilter.java:187)
    org.springframework.boot.web.support.ErrorPageFilter.handleException(ErrorPageFilter.java:170)
    org.springframework.boot.web.support.ErrorPageFilter.doFilter(ErrorPageFilter.java:134)
    org.springframework.boot.web.support.ErrorPageFilter.access$000(ErrorPageFilter.java:61)
    org.springframework.boot.web.support.ErrorPageFilter$1.doFilterInternal(ErrorPageFilter.java:94)
    org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    org.springframework.boot.web.support.ErrorPageFilter.doFilter(ErrorPageFilter.java:112)
    org.apache.logging.log4j.web.Log4jServletFilter.doFilter(Log4jServletFilter.java:71)

对于每个控制器,我都会得到这个堆栈跟踪。我想优雅地处理这件事。请建议在应用程序启动后我应该在什么时候处理 mongo 连接异常。我正在为我的项目使用 spring-boot-starter-data-mongodb maven 依赖项

【问题讨论】:

  • SessionRepositoryFilter docs.spring.io/spring-session/docs/current/api/org/… 是此处失败的代码。它在任何与控制器相关的机器(包括通知)可能发挥作用之前执行,因此如果它失败,它会在创建任何控制器范围之前执行。您在哪里配置了该过滤器?
  • 这是我的安全配置
  • 我正在使用 @EnableMongoHttpSession 创建一个名为 springSessionRepositoryFilter 的 Spring Bean,它实现了过滤器。过滤器负责替换 Spring Session 支持的 HttpSession 实现。在这种情况下,Spring Session 由 Mongo 支持。如上所述docs.spring.io/spring-session/docs/current/reference/html5/…

标签: spring mongodb spring-boot exception-handling spring-session


【解决方案1】:

SessionRepositoryFilter http://docs.spring.io/spring-session/docs/current/api/org/... 由您的@EnableMongoHttpSession 添加是此处失败的代码。它在任何与控制器相关的机制(包括通知)可能发挥作用之前执行,因此如果它失败,它会在创建任何控制器范围之前执行。

但是您可以创建一个过滤器,将其插入到 Mongo Http Session 过滤器之前的过滤器链中,并尝试捕获并处理该异常:

public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) {
    try {
        chain.doFilter(request, response);
    } catch (TranslatedException e) {
        // somehow handle it, like display an error message
    }
}

其中TranslatedException 是spring 转换为MongoTimeoutException 的异常(从您的堆栈跟踪中看不到)。

【讨论】:

  • 谢谢。这对我有用:)。但是我们不能设置任何内容来响应显示内部服务器错误或服务不可用错误
猜你喜欢
  • 1970-01-01
  • 2019-02-18
  • 2023-03-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-07-18
  • 2017-12-14
  • 2017-05-07
相关资源
最近更新 更多