代码之家  ›  专栏  ›  技术社区  ›  Andrej Flieger

从Spring Boot 3.0.x到3.1.x的迁移中断了自动布线

  •  0
  • Andrej Flieger  · 技术社区  · 2 年前

    我正在从SpringBoot 3.0.11迁移到SpringBoot 3.1.4 到目前为止,我收到了一个关于servlet注册的警告,3.1中的内容会导致错误。 为了保持相同的行为,我更改了代码如下。 但现在自动布线坏了。

    任何小费,我做错了什么

    这是我在SpringBoot 3.0.11中的代码

    @EnableConfigurationProperties({ DataSourceMonitoringProperties.class})
    public class DataSourceServletConfiguration {
        
        public static final String DATASOURCE_MONITORING_PATH = "/datasource";
    
        @Bean(name = Const.DATASOURCE_SERVLET_BEAN_NAME)
        @ConditionalOnMissingBean(name = Const.DATASOURCE_SERVLET_BEAN_NAME)
        public Servlet monitoringDatasourceServlet(ServletContext servletContext, DataSourceMonitoringProperties dataSourceMonitoringProperties) {
            RequestDispatcher namedDispatcher = servletContext.getNamedDispatcher(Const.DATASOURCE_SERVLET_BEAN_NAME);
            if (namedDispatcher != null) {
                return new DataSourceMonitoringServlet();
            }
    
            DataSourceMonitoringServlet monitoringDatasourceServlet = new DataSourceMonitoringServlet();
            monitoringDatasourceServlet.setJavamelody(null != servletContext.getFilterRegistration("javamelody"));
            Dynamic monitoringDataSourceServletDynamic = servletContext.addServlet(Const.DATASOURCE_SERVLET_BEAN_NAME, monitoringDatasourceServlet);
            monitoringDataSourceServletDynamic.setLoadOnStartup(1);
            monitoringDataSourceServletDynamic.setAsyncSupported(true);
            monitoringDataSourceServletDynamic.addMapping(DATASOURCE_MONITORING_PATH);
    
    
            return monitoringDatasourceServlet;
        }
    

    我不得不将其更改为以下内容,以使其与Springboot 3.0.11兼容

    monitoringDatasourceServlet注册。setIgnoreRegistrationFailure(true);

        @Bean(name = Const.DATASOURCE_SERVLET_BEAN_NAME)
        @ConditionalOnMissingBean(name = Const.DATASOURCE_SERVLET_BEAN_NAME)
        public ServletRegistrationBean<DataSourceMonitoringServlet> monitoringDatasourceServlet(ServletContext servletContext, DataSourceMonitoringProperties dataSourceMonitoringProperties) throws ServletException {
            RequestDispatcher namedDispatcher = servletContext.getNamedDispatcher(Const.DATASOURCE_SERVLET_BEAN_NAME);
            if (namedDispatcher != null) {
                ServletRegistrationBean<DataSourceMonitoringServlet> servletRegistrationBean = new ServletRegistrationBean<>(new DataSourceMonitoringServlet());
                servletRegistrationBean.onStartup(servletContext);
                return servletRegistrationBean;
            }
    
            DataSourceMonitoringServlet monitoringDatasourceServlet = new DataSourceMonitoringServlet();
            monitoringDatasourceServlet.setJavamelody(null != servletContext.getFilterRegistration("javamelody"));
            Dynamic monitoringDataSourceServletDynamic = servletContext.addServlet(Const.DATASOURCE_SERVLET_BEAN_NAME, monitoringDatasourceServlet);
            monitoringDataSourceServletDynamic.setLoadOnStartup(1);
            monitoringDataSourceServletDynamic.setAsyncSupported(true);
            monitoringDataSourceServletDynamic.addMapping(DATASOURCE_MONITORING_PATH);
            
            ServletRegistrationBean<DataSourceMonitoringServlet> monitoringDatasourceServletRegistration = new ServletRegistrationBean<>(monitoringDatasourceServlet, DATASOURCE_MONITORING_PATH);
            monitoringDatasourceServletRegistration.onStartup(servletContext);
            ** monitoringDatasourceServletRegistration.setIgnoreRegistrationFailure(true); **
            monitoringDatasourceServletRegistration.setLoadOnStartup(1);
            monitoringDatasourceServletRegistration.setAsyncSupported(true);
    
    
            return monitoringDatasourceServletRegistration;
        }
    

    在测试执行期间,Servlet被调用,并在

    data.setCollectedDatasourceTraces(datasourceMetricsCollector.collecteDatasourceMetrics());

    public class DataSourceMonitoringServlet extends GenericServlet {
    
        @Autowired
        private DatasourceMetricsCollector datasourceMetricsCollector;
        private boolean javamelody;
    
        public HtmlReportData datasourceReport() {
            // curl -i -H "Accept: application/json" http://localhost:8080
            HtmlReportData data = new HtmlReportData();
            data.setCollectedDatasourceTraces(datasourceMetricsCollector.collectDatasourceMetrics());
            data.setFindLockRows(datasourceMetricsCollector.collectRecordLockInfo());
            return data;
        }
    

    这是我在测试执行中得到的Stacktrace

    
    java.lang.NullPointerException: Cannot invoke "de.mydomain.framework.monitoring.datasource.collector.DatasourceMetricsCollector.collectDatasourceMetrics()" because "this.datasourceMetricsCollector" is null
        at de.mydomian.framework.monitoring.datasource.html.report.DataSourceMonitoringServlet.datasourceReport(DataSourceMonitoringServlet.java:40) ~[classes/:na]
        at de.mydomain.framework.monitoring.datasource.html.report.DataSourceMonitoringServlet.service(DataSourceMonitoringServlet.java:48) ~[classes/:na]
        at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:764) ~[jetty-servlet-11.0.16.jar:11.0.16]
        at org.eclipse.jetty.servlet.ServletHandler$ChainEnd.doFilter(ServletHandler.java:1665) ~[jetty-servlet-11.0.16.jar:11.0.16]
        at org.eclipse.jetty.websocket.servlet.WebSocketUpgradeFilter.doFilter(WebSocketUpgradeFilter.java:170) ~[websocket-servlet-11.0.16.jar:11.0.16]
        at org.eclipse.jetty.servlet.FilterHolder.doFilter(FilterHolder.java:202) ~[jetty-servlet-11.0.16.jar:11.0.16]
        at org.eclipse.jetty.servlet.ServletHandler$Chain.doFilter(ServletHandler.java:1635) ~[jetty-servlet-11.0.16.jar:11.0.16]
        at org.springframework.security.web.FilterChainProxy.lambda$doFilterInternal$3(FilterChainProxy.java:231) ~[spring-security-web-6.1.1.jar:6.1.1]
        at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:365) ~[spring-security-web-6.1.1.jar:6.1.1]
        at org.springframework.security.web.access.intercept.AuthorizationFilter.doFilter(AuthorizationFilter.java:100) ~[spring-security-web-6.1.1.jar:6.1.1]
        at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:374) ~[spring-security-web-6.1.1.jar:6.1.1]
        at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:126) ~[spring-security-web-6.1.1.jar:6.1.1]
        at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:120) ~[spring-security-web-6.1.1.jar:6.1.1]
        at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:374) ~[spring-security-web-6.1.1.jar:6.1.1]
        at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:100) ~[spring-security-web-6.1.1.jar:6.1.1]
        at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:374) ~[spring-security-web-6.1.1.jar:6.1.1]
        at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:179) ~[spring-security-web-6.1.1.jar:6.1.1]
        at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:374) ~[spring-security-web-6.1.1.jar:6.1.1]
        at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:63) ~[spring-security-web-6.1.1.jar:6.1.1]
        at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:374) ~[spring-security-web-6.1.1.jar:6.1.1]
        at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:107) ~[spring-security-web-6.1.1.jar:6.1.1]
        at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:93) ~[spring-security-web-6.1.1.jar:6.1.1]
        at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:374) ~[spring-security-web-6.1.1.jar:6.1.1]
        at org.springframework.security.web.csrf.CsrfFilter.doFilterInternal(CsrfFilter.java:117) ~[spring-security-web-6.1.1.jar:6.1.1]
        at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) ~[spring-web-6.0.12.jar:6.0.12]
        at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:374) ~[spring-security-web-6.1.1.jar:6.1.1]
        at org.springframework.security.web.header.HeaderWriterFilter.doHeadersAfter(HeaderWriterFilter.java:90) ~[spring-security-web-6.1.1.jar:6.1.1]
        at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:75) ~[spring-security-web-6.1.1.jar:6.1.1]
        at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) ~[spring-web-6.0.12.jar:6.0.12]
        at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:374) ~[spring-security-web-6.1.1.jar:6.1.1]
        at org.springframework.security.web.context.SecurityContextHolderFilter.doFilter(SecurityContextHolderFilter.java:82) ~[spring-security-web-6.1.1.jar:6.1.1]
        at org.springframework.security.web.context.SecurityContextHolderFilter.doFilter(SecurityContextHolderFilter.java:69) ~[spring-security-web-6.1.1.jar:6.1.1]
        at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:374) ~[spring-security-web-6.1.1.jar:6.1.1]
        at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:62) ~[spring-security-web-6.1.1.jar:6.1.1]
        at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) ~[spring-web-6.0.12.jar:6.0.12]
        at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:374) ~[spring-security-web-6.1.1.jar:6.1.1]
        at org.springframework.security.web.session.DisableEncodeUrlFilter.doFilterInternal(DisableEncodeUrlFilter.java:42) ~[spring-security-web-6.1.1.jar:6.1.1]
        at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) ~[spring-web-6.0.12.jar:6.0.12]
        at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:374) ~[spring-security-web-6.1.1.jar:6.1.1]
        at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:233) ~[spring-security-web-6.1.1.jar:6.1.1]
        at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:191) ~[spring-security-web-6.1.1.jar:6.1.1]
        at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:352) ~[spring-web-6.0.12.jar:6.0.12]
        at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:268) ~[spring-web-6.0.12.jar:6.0.12]
        at org.eclipse.jetty.servlet.FilterHolder.doFilter(FilterHolder.java:202) ~[jetty-servlet-11.0.16.jar:11.0.16]
        at org.eclipse.jetty.servlet.ServletHandler$Chain.doFilter(ServletHandler.java:1635) ~[jetty-servlet-11.0.16.jar:11.0.16]
        at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100) ~[spring-web-6.0.12.jar:6.0.12]
        at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) ~[spring-web-6.0.12.jar:6.0.12]
        at org.eclipse.jetty.servlet.FilterHolder.doFilter(FilterHolder.java:202) ~[jetty-servlet-11.0.16.jar:11.0.16]
        at org.eclipse.jetty.servlet.ServletHandler$Chain.doFilter(ServletHandler.java:1635) ~[jetty-servlet-11.0.16.jar:11.0.16]
        at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93) ~[spring-web-6.0.12.jar:6.0.12]
        at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) ~[spring-web-6.0.12.jar:6.0.12]
        at org.eclipse.jetty.servlet.FilterHolder.doFilter(FilterHolder.java:202) ~[jetty-servlet-11.0.16.jar:11.0.16]
        at org.eclipse.jetty.servlet.ServletHandler$Chain.doFilter(ServletHandler.java:1635) ~[jetty-servlet-11.0.16.jar:11.0.16]
        at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201) ~[spring-web-6.0.12.jar:6.0.12]
        at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) ~[spring-web-6.0.12.jar:6.0.12]
        at org.eclipse.jetty.servlet.FilterHolder.doFilter(FilterHolder.java:202) ~[jetty-servlet-11.0.16.jar:11.0.16]
        at org.eclipse.jetty.servlet.ServletHandler$Chain.doFilter(ServletHandler.java:1635) ~[jetty-servlet-11.0.16.jar:11.0.16]
        at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:527) ~[jetty-servlet-11.0.16.jar:11.0.16]
        at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:131) ~[jetty-server-11.0.16.jar:11.0.16]
        at org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:578) ~[jetty-security-11.0.16.jar:11.0.16]
        at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:122) ~[jetty-server-11.0.16.jar:11.0.16]
        at org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:223) ~[jetty-server-11.0.16.jar:11.0.16]
        at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:1570) ~[jetty-server-11.0.16.jar:11.0.16]
        at org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:221) ~[jetty-server-11.0.16.jar:11.0.16]
        at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1381) ~[jetty-server-11.0.16.jar:11.0.16]
        at org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:176) ~[jetty-server-11.0.16.jar:11.0.16]
        at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:484) ~[jetty-servlet-11.0.16.jar:11.0.16]
        at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:1543) ~[jetty-server-11.0.16.jar:11.0.16]
        at org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:174) ~[jetty-server-11.0.16.jar:11.0.16]
        at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1303) ~[jetty-server-11.0.16.jar:11.0.16]
        at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:129) ~[jetty-server-11.0.16.jar:11.0.16]
        at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:122) ~[jetty-server-11.0.16.jar:11.0.16]
        at org.eclipse.jetty.server.Server.handle(Server.java:563) ~[jetty-server-11.0.16.jar:11.0.16]
        at org.eclipse.jetty.server.HttpChannel$RequestDispatchable.dispatch(HttpChannel.java:1598) ~[jetty-server-11.0.16.jar:11.0.16]
        at org.eclipse.jetty.server.HttpChannel.dispatch(HttpChannel.java:753) ~[jetty-server-11.0.16.jar:11.0.16]
        at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:501) ~[jetty-server-11.0.16.jar:11.0.16]
        at org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:282) ~[jetty-server-11.0.16.jar:11.0.16]
        at org.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:314) ~[jetty-io-11.0.16.jar:11.0.16]
        at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:100) ~[jetty-io-11.0.16.jar:11.0.16]
        at org.eclipse.jetty.io.SelectableChannelEndPoint$1.run(SelectableChannelEndPoint.java:53) ~[jetty-io-11.0.16.jar:11.0.16]
        at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:969) ~[jetty-util-11.0.16.jar:11.0.16]
        at org.eclipse.jetty.util.thread.QueuedThreadPool$Runner.doRunJob(QueuedThreadPool.java:1194) ~[jetty-util-11.0.16.jar:11.0.16]
        at org.eclipse.jetty.util.thread.QueuedThreadPool$Runner.run(QueuedThreadPool.java:1149) ~[jetty-util-11.0.16.jar:11.0.16]
        at java.base/java.lang.Thread.run(Thread.java:833) ~[na:na]
    
    
    0 回复  |  直到 2 年前
        1
  •  0
  •   M. Deinum    2 年前

    您的代码既奇怪又复杂。您应该有两个简单的bean:一个用于servlet,一个用于注册。你添加的所有其他内容都很混乱。

    public static final String DATASOURCE_MONITORING_PATH = "/datasource";
    
    @Bean(name = Const.DATASOURCE_SERVLET_BEAN_NAME)
    @ConditionalOnMissingBean(name = Const.DATASOURCE_SERVLET_BEAN_NAME)
    public DataSourceMonitoringServlet monitoringDatasourceServlet(DataSourceMonitoringProperties dataSourceMonitoringProperties, ServletContext ctx) {
        var monitoringDatasourceServlet = new DataSourceMonitoringServlet();
        monitoringDatasourceServlet.setJavamelody(null != ctx.getFilterRegistration("javamelody"));
        return monitoringDatasourceServlet;
    }
    
    @Bean
    public ServletRegistrationBean< DataSourceMonitoringServlet > servletRegistation(DataSourceMonitoringServlet servlet) {
     var registration = new ServletRegistrationBean(servlet, DATASOURCE_MONITORING_PATH);
     registration.setLoadOnStartup(1);
     return registration;
    
    }
    

    Spring Boot将在上下文中处理此bean和servlet的注册。你不应该自己做这件事,尤其是在 @Bean 方法