如何动态禁用 spring 中的特定 API?
How to dynamically disable specific API in spring?
我有一个标志 DISABLE_FLAG
,我想用它来控制不同控制器中的多个特定 API。
@RestController
public final class Controller1 {
@RequestMapping(value = "/foo1", method = RequestMethod.POST)
public String foo1()
}
@RestController
public final class Controller2 {
@RequestMapping(value = "/foo2", method = RequestMethod.POST)
public String foo2()
}
我可以使用拦截器来处理所有 url。有没有简单的方法来做到这一点,比如注释?
我认为没有直接的方法来禁用构造的请求映射,但我们可以在某些条件下以多种方式禁用 API。
这是通过 spring 配置文件或 JVM 属性禁用的 2 种方法。
public class SampleController {
@Autowired
Environment env;
@RequestMapping(value = "/foo", method = RequestMethod.POST)
public String foo(HttpServletResponse response) {
// Using profile
if (env.acceptsProfiles("staging")) {
response.setStatus(404);
return "";
}
// Using JVM options
if("true".equals(System.getProperty("DISABLE_FOO"))) {
response.setStatus(404);
return "";
}
return "";
}
}
如果您认为使用云配置的未来解决方案是最佳方法。 https://spring.io/guides/gs/centralized-configuration/
使用条件组件
这允许构建带有条件的bean,如果条件在启动时失败,则永远不会构建整个组件。将所有可选请求映射分组到新控制器并添加条件注释
@Conditional(ConditionalController.class)
public class SampleController {
@Autowired
Environment env;
@RequestMapping(value = "/foo", method = RequestMethod.POST)
public String foo(HttpServletResponse response) {
return "";
}
public static class ConditionalController implements Condition {
@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
return context.getEnvironment().acceptsProfiles("staging"); // Or whatever condition
}
}
}
您可以使用 AOP 来做类似的事情。
创建您自己的注释...
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Maybe { }
和相应的方面...
@Aspect
public class MaybeAspect {
@Pointcut("@annotation(com.example.Maybe)")
public void callMeMaybe() {}
@Around("callMeMaybe()")
public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
// do your logic here..
if(DISABLE_FOO) {
// do nothing ? throw exception?
// return null;
throw new IllegalStateException();
} else {
// process the request normally
return joinPoint.proceed();
}
}
}
您可以利用 spring 配置文件通过注释解决此问题。您定义两个配置文件,一个用于启用标志,另一个配置文件用于禁用标志。您的示例如下所示:
@Profile("DISABLED_FLAG")
@RestController
public final class Controller1 {
@RequestMapping(value = "/foo1", method = RequestMethod.POST)
public String foo1()
}
@Profile("ENABLED_FLAG")
@RestController
public final class Controller2 {
@RequestMapping(value = "/foo2", method = RequestMethod.POST)
public String foo2()
}
这是此功能的 link 到 spring 框架文档:https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/context/annotation/Profile.html
我是这样做的:
@Retention(RUNTIME)
@Target(ElementType.METHOD)
public @interface DisableApiControl {
}
这个class是我的自定义语句。之后可以使用 AOP :
对于 AbstractBaseServiceImpl:
public abstract class AbstractBaseServiceImpl {
private static boolean disableCheck = false;
public void setDisableChecker(boolean checkParameter) {
disableCheck = checkParameter;
}
public boolean getDisableChecker() {
return disableCheck;
}
}
注意 : 以上class已准备好提供动态结构
@Aspect
@Component
public class DisableApiControlAspect extends AbstractBaseServiceImpl {
@Autowired
private HttpServletResponse httpServletResponse;
@Pointcut(" @annotation(disableMe)")
protected void disabledMethods(DisableApiControl disableMe) {
// comment line
}
@Around("disabledMethods(disableMe)")
public Object dontRun(ProceedingJoinPoint joinPoint, DisableApiControl disableMe) throws Throwable {
if (getDisableChecker()) {
httpServletResponse.sendError(HttpStatus.NOT_FOUND.value(), "Not found");
return null;
} else {
return joinPoint.proceed();
}
}
}
此时添加了全局检查器参数。当需要时将值指定为 true / false 时,剩下的事情会更容易。
@GetMapping("/map")
@DisableApiControl
public List<?> stateMachineFindMap() {
return new ArrayList<>;
}
我有一个标志 DISABLE_FLAG
,我想用它来控制不同控制器中的多个特定 API。
@RestController
public final class Controller1 {
@RequestMapping(value = "/foo1", method = RequestMethod.POST)
public String foo1()
}
@RestController
public final class Controller2 {
@RequestMapping(value = "/foo2", method = RequestMethod.POST)
public String foo2()
}
我可以使用拦截器来处理所有 url。有没有简单的方法来做到这一点,比如注释?
我认为没有直接的方法来禁用构造的请求映射,但我们可以在某些条件下以多种方式禁用 API。
这是通过 spring 配置文件或 JVM 属性禁用的 2 种方法。
public class SampleController {
@Autowired
Environment env;
@RequestMapping(value = "/foo", method = RequestMethod.POST)
public String foo(HttpServletResponse response) {
// Using profile
if (env.acceptsProfiles("staging")) {
response.setStatus(404);
return "";
}
// Using JVM options
if("true".equals(System.getProperty("DISABLE_FOO"))) {
response.setStatus(404);
return "";
}
return "";
}
}
如果您认为使用云配置的未来解决方案是最佳方法。 https://spring.io/guides/gs/centralized-configuration/
使用条件组件
这允许构建带有条件的bean,如果条件在启动时失败,则永远不会构建整个组件。将所有可选请求映射分组到新控制器并添加条件注释
@Conditional(ConditionalController.class)
public class SampleController {
@Autowired
Environment env;
@RequestMapping(value = "/foo", method = RequestMethod.POST)
public String foo(HttpServletResponse response) {
return "";
}
public static class ConditionalController implements Condition {
@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
return context.getEnvironment().acceptsProfiles("staging"); // Or whatever condition
}
}
}
您可以使用 AOP 来做类似的事情。
创建您自己的注释...
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Maybe { }
和相应的方面...
@Aspect
public class MaybeAspect {
@Pointcut("@annotation(com.example.Maybe)")
public void callMeMaybe() {}
@Around("callMeMaybe()")
public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
// do your logic here..
if(DISABLE_FOO) {
// do nothing ? throw exception?
// return null;
throw new IllegalStateException();
} else {
// process the request normally
return joinPoint.proceed();
}
}
}
您可以利用 spring 配置文件通过注释解决此问题。您定义两个配置文件,一个用于启用标志,另一个配置文件用于禁用标志。您的示例如下所示:
@Profile("DISABLED_FLAG")
@RestController
public final class Controller1 {
@RequestMapping(value = "/foo1", method = RequestMethod.POST)
public String foo1()
}
@Profile("ENABLED_FLAG")
@RestController
public final class Controller2 {
@RequestMapping(value = "/foo2", method = RequestMethod.POST)
public String foo2()
}
这是此功能的 link 到 spring 框架文档:https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/context/annotation/Profile.html
我是这样做的:
@Retention(RUNTIME)
@Target(ElementType.METHOD)
public @interface DisableApiControl {
}
这个class是我的自定义语句。之后可以使用 AOP :
对于 AbstractBaseServiceImpl:
public abstract class AbstractBaseServiceImpl {
private static boolean disableCheck = false;
public void setDisableChecker(boolean checkParameter) {
disableCheck = checkParameter;
}
public boolean getDisableChecker() {
return disableCheck;
}
}
注意 : 以上class已准备好提供动态结构
@Aspect
@Component
public class DisableApiControlAspect extends AbstractBaseServiceImpl {
@Autowired
private HttpServletResponse httpServletResponse;
@Pointcut(" @annotation(disableMe)")
protected void disabledMethods(DisableApiControl disableMe) {
// comment line
}
@Around("disabledMethods(disableMe)")
public Object dontRun(ProceedingJoinPoint joinPoint, DisableApiControl disableMe) throws Throwable {
if (getDisableChecker()) {
httpServletResponse.sendError(HttpStatus.NOT_FOUND.value(), "Not found");
return null;
} else {
return joinPoint.proceed();
}
}
}
此时添加了全局检查器参数。当需要时将值指定为 true / false 时,剩下的事情会更容易。
@GetMapping("/map")
@DisableApiControl
public List<?> stateMachineFindMap() {
return new ArrayList<>;
}