You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Spring中动态禁用指定API?寻求注解式简便实现方案

自定义注解 + AOP/拦截器实现精准API控制

当然有!这种场景下,自定义注解配合AOP或者拦截器是非常合适的方案——既能精准控制你指定的那些API,又不像全局拦截器那样需要处理所有URL,代码侵入性低,维护起来也方便。下面给你具体的实现步骤:

第一步:自定义控制注解

首先创建一个专门用来标记需要被控制的API的注解,这样你可以灵活地在任意API方法上添加标记:

import java.lang.annotation.*;

@Target(ElementType.METHOD) // 只作用在方法上
@Retention(RetentionPolicy.RUNTIME) // 运行时可被反射获取
public @interface ApiDisableControl {
    // 可选:如果后续需要多开关控制,可以加个属性指定开关key
    // String flagKey() default "DISABLE_FLAG";
}

第二步:在目标API上添加注解

把这个注解加到你需要控制的foo1和foo2方法上,非常直观:

@RestController
public final class Controller1 {
    @ApiDisableControl // 标记这个API需要被开关控制
    @RequestMapping(value = "/foo1", method = RequestMethod.POST)
    public String foo1() {
        return "foo1 response";
    }
}

@RestController
public final class Controller2 {
    @ApiDisableControl // 同样标记
    @RequestMapping(value = "/foo2", method = RequestMethod.POST)
    public String foo2() {
        return "foo2 response";
    }
}

第三步:实现开关逻辑(两种可选方案)

方案一:使用AOP切面(推荐,代码更简洁)

通过Spring AOP拦截所有标记了@ApiDisableControl的方法,在方法执行前检查DISABLE_FLAG的状态,决定是否放行:

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
// 若需要HTTP状态码,可引入import org.springframework.http.ResponseEntity;

@Component
@Aspect
public class ApiDisableAspect {

    // 这里的DISABLE_FLAG可以从配置文件、数据库或配置中心动态获取,比如用@Value("${api.disable.flag}")注入
    private boolean DISABLE_FLAG = false;

    // 定义切点:匹配所有带有@ApiDisableControl注解的方法
    @Pointcut("@annotation(com.yourpackage.ApiDisableControl)")
    public void apiDisablePointcut() {}

    // 环绕通知:在方法执行前后做处理
    @Around("apiDisablePointcut()")
    public Object handleApiDisable(ProceedingJoinPoint joinPoint) throws Throwable {
        if (DISABLE_FLAG) {
            // 开关开启时,返回禁用提示(可自定义响应内容或HTTP状态码)
            // return ResponseEntity.status(HttpStatus.SERVICE_UNAVAILABLE).body("This API is temporarily disabled");
            return "This API is temporarily disabled";
        }
        // 开关关闭时,正常执行原方法
        return joinPoint.proceed();
    }
}

方案二:使用拦截器(适合需要处理HTTP细节的场景)

如果需要在请求处理的更早阶段干预(比如操作HttpServletResponse),可以用Spring MVC拦截器实现:

import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@Component
public class ApiDisableInterceptor implements HandlerInterceptor {

    private boolean DISABLE_FLAG = false;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        // 判断当前请求是否对应一个带注解的Controller方法
        if (handler instanceof HandlerMethod) {
            HandlerMethod handlerMethod = (HandlerMethod) handler;
            ApiDisableControl annotation = handlerMethod.getMethodAnnotation(ApiDisableControl.class);
            
            if (annotation != null && DISABLE_FLAG) {
                // 禁用API:设置HTTP状态码并返回提示
                response.setStatus(HttpServletResponse.SC_SERVICE_UNAVAILABLE);
                response.getWriter().write("This API is temporarily disabled");
                return false; // 阻止请求继续执行
            }
        }
        return true; // 放行请求
    }
}

// 别忘了注册拦截器
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 WebConfig implements WebMvcConfigurer {

    private final ApiDisableInterceptor apiDisableInterceptor;

    public WebConfig(ApiDisableInterceptor apiDisableInterceptor) {
        this.apiDisableInterceptor = apiDisableInterceptor;
    }

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(apiDisableInterceptor);
    }
}

方案对比与优化建议

  • AOP方案:代码更简洁,专注于方法逻辑的拦截,适合不需要操作HTTP请求/响应细节的场景。
  • 拦截器方案:能在请求处理的更早阶段介入,适合需要修改HTTP状态码、响应头等场景。
  • 优化点:如果后续需要多开关控制不同组的API,可以给@ApiDisableControl注解添加flagKey属性,在切面/拦截器中根据key动态获取对应开关的值,进一步提升灵活性。

内容的提问来源于stack exchange,提问作者eriee

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 08:37:06