如何防止 Spring Boot Web 应用程序在启动时接受 http 请求?

Mau*_*ice 6 spring spring-mvc spring-boot

我有一个带有角度前端的 Spring Boot Web 应用程序。当我在 Web 应用程序仍在启动时使用 Angular 应用程序发送请求时,Web 应用程序可能会接受该请求并尝试处理它。我相信应用程序能够在WebSecurityConfigurerAdapter扩展类初始化后接收请求。

当其余类尚未完全初始化时,这会导致问题。例如,当我尝试注销在 Web 应用程序启动时仍然登录的用户时,可能会导致 SQLException,因为它还找不到数据库表user

@SpringBootApplication在最终类(用 注释的类)初始化之前,如何防止应用程序接受请求?

Mau*_*ice 2

根据@Fullslack.dev 的提示,我提出了以下解决方案。

@WebFilter(urlPatterns = {"/*"})
public class MyFilter implements Filter, ApplicationListener<ApplicationReadyEvent> {

    private boolean webApplicationReadyToAcceptRequests = false;

    @Override 
    public void onApplicationEvent(ApplicationReadyEvent applicationReadyEvent) {
        webApplicationReadyToAcceptRequests = true;
    }
    
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)
            throws IOException, ServletException {
            if(!webApplicationReadyToAcceptRequests) {
                httpServletResponse.setHeader("Retry-After","35");
                httpServletResponse.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE, "The server is currently starting up. Please try again in a moment.");
                return;
            }
            else
                filterChain.doFilter(servletRequest, servletResponse);
            }
    }

}
Run Code Online (Sandbox Code Playgroud)

这是一个过滤器类,每个请求在提交给 @Controller 和/或 @Service 注解的类之前都必须首先通过。如果该变量webApplicationReadyToAcceptRequests仍然为 false,则过滤器不会将请求传递到下游,而是会发送带有 httpstatus 503(服务不可用)的错误消息响应。

确保您至少使用以下注释注释了您的 @Configuration 配置类之一:

@ComponentScan(basePackages={ "FolderWhereMyFilterIsLocated"})
Run Code Online (Sandbox Code Playgroud)

这将确保 spring 知道过滤器的存在。

  • 对于独立应用程序来说,这是一个很好的解决方案,并且与我们为应用程序实现的相同方法相匹配。对于@NewBee 的观点,Spring Boot 在使用负载均衡器时通过检查“就绪状态”并仅将流量路由到接受流量的实例提供了更好的解决方案,但许多环境没有负载均衡器。更多信息:https://www.baeldung.com/spring-liveness-readiness-probes (2认同)