Spring Boot维护期间拦截请求并返回503错误的实现方法
Spring Boot 维护状态返回503错误实现方案
要实现API维护期间拦截所有请求并返回503(服务不可用)响应,以下是几种实用的Spring Boot方案:
方案一:基于Servlet Filter(全局拦截所有请求)
Filter属于Servlet层面,能拦截所有进入应用的请求(包括静态资源、Actuator端点等),适合全量拦截场景。
1. 定义维护状态配置类
通过配置文件读取维护开关和提示信息:
import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.stereotype.Component; @Component @ConfigurationProperties(prefix = "maintenance") public class MaintenanceProperties { private boolean enabled; private String message = "服务正在维护中,请稍后重试"; // Getter & Setter public boolean isEnabled() { return enabled; } public void setEnabled(boolean enabled) { this.enabled = enabled; } public String getMessage() { return message; } public void setMessage(String message) { this.message = message; } }
2. 实现维护拦截Filter
继承OncePerRequestFilter确保每个请求只执行一次拦截逻辑:
import jakarta.servlet.FilterChain; import jakarta.servlet.ServletException; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import org.springframework.stereotype.Component; import org.springframework.web.filter.OncePerRequestFilter; import java.io.IOException; @Component public class MaintenanceFilter extends OncePerRequestFilter { private final MaintenanceProperties maintenanceProps; public MaintenanceFilter(MaintenanceProperties maintenanceProps) { this.maintenanceProps = maintenanceProps; } @Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { if (maintenanceProps.isEnabled()) { response.setStatus(HttpServletResponse.SC_SERVICE_UNAVAILABLE); response.setContentType("application/json;charset=UTF-8"); response.getWriter().write("{\"code\":503,\"message\":\"" + maintenanceProps.getMessage() + "\"}"); return; // 终止请求链,不执行后续逻辑 } filterChain.doFilter(request, response); } }
3. 配置文件开关
在application.yml中配置维护状态:
maintenance: enabled: false # 需要维护时改为true message: "系统升级维护中,预计1小时后恢复"
方案二:基于Spring MVC HandlerInterceptor
Interceptor属于Spring MVC层面,仅拦截DispatcherServlet处理的请求(如控制器接口),适合只拦截业务API的场景。
1. 实现维护拦截器
在preHandle方法中判断维护状态,阻止后续请求处理:
import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import org.springframework.stereotype.Component; import org.springframework.web.servlet.HandlerInterceptor; import java.io.IOException; @Component public class MaintenanceInterceptor implements HandlerInterceptor { private final MaintenanceProperties maintenanceProps; public MaintenanceInterceptor(MaintenanceProperties maintenanceProps) { this.maintenanceProps = maintenanceProps; } @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws IOException { if (maintenanceProps.isEnabled()) { response.setStatus(HttpServletResponse.SC_SERVICE_UNAVAILABLE); response.setContentType("application/json;charset=UTF-8"); response.getWriter().write("{\"code\":503,\"message\":\"" + maintenanceProps.getMessage() + "\"}"); return false; // 返回false阻止控制器方法执行 } return true; } }
2. 注册拦截器
通过WebMvcConfigurer将拦截器注册到Spring MVC:
import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.InterceptorRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; @Configuration public class WebMvcConfig implements WebMvcConfigurer { private final MaintenanceInterceptor maintenanceInterceptor; public WebMvcConfig(MaintenanceInterceptor maintenanceInterceptor) { this.maintenanceInterceptor = maintenanceInterceptor; } @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(maintenanceInterceptor) .addPathPatterns("/**"); // 拦截所有API路径 } }
进阶:动态维护开关(无需重启应用)
如果需要不重启应用就能切换维护状态,可以将开关状态存储到Redis等外部存储中,修改MaintenanceProperties实时读取:
import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.stereotype.Component; @Component public class MaintenanceProperties { private final StringRedisTemplate redisTemplate; public MaintenanceProperties(StringRedisTemplate redisTemplate) { this.redisTemplate = redisTemplate; } public boolean isEnabled() { String enabled = redisTemplate.opsForValue().get("maintenance.enabled"); return "true".equals(enabled); } public String getMessage() { String message = redisTemplate.opsForValue().get("maintenance.message"); return message != null ? message : "服务正在维护中,请稍后重试"; } }
此时可以通过Redis客户端设置maintenance.enabled为true/false来动态开启或关闭维护模式。
内容的提问来源于stack exchange,提问作者TDev
相关产品推荐
相关产品推荐

