自定义注解过滤器 Spring boot

pau*_*aul 2 java spring spring-boot

我看到使用 Spring Boot 创建过滤器非常简单。只需关注这样的帖子https://www.baeldung.com/spring-boot-add-filter

我找不到的是如何创建将控制器中的特定端点订阅到一个过滤器的注释。

类似于 Jax-RS 中的东西,它看起来像

 @GET
    @Path("jax-rs-single")
    @Reactive(ttlRequest = 2000)
    @Produces(MediaType.APPLICATION_JSON)
    public Single getSingle() {
        return Single.just("Hello world single");
    }
Run Code Online (Sandbox Code Playgroud)

在哪里 @Reactive,将触发每个请求的ReactiveFilter实施。

我也看到了@WebFlow 注释,但这不是我想要的。我想创建一个库,让消费者决定使用哪个过滤器,只需在控制器中添加注释。

知道如何用 Spring boot/MVC 做类似的事情吗?

问候

Bro*_*her 6

我将在这里尝试更多地描述自定义注解和 Spring 中的处理器。

我不知道你想要什么或你需要什么,但我会举一个通用的例子。

您有 2 个选择:

  • 豆处理器
  • 处理程序拦截器

豆处理器

您基本上需要构建 3 样东西:Annotaton、BeanProcessor 和回调以在注释时执行您的逻辑。这是它的一个例子以及它是如何工作的:

1 - 创建注释

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD})
@Documented
public @interface Reactive {
    Integer ttlRequest;
}
Run Code Online (Sandbox Code Playgroud)

2 - 实现一个 BeanPostProcessor

 @Component 
 public class ReactiveAnnotationProcessor implements BeanPostProcessor {

    private ConfigurableListableBeanFactory configurableBeanFactory;

    @Autowired
    public ReactiveAnnotationProcessor(ConfigurableListableBeanFactory beanFactory) {
        this.configurableBeanFactory = beanFactory;
    }

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) 
      throws BeansException {
        this.scanReactiveAnnotation(bean, beanName);
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) 
      throws BeansException {
        return bean;
    }

    protected void scanReactiveAnnotation(Object bean, String beanName) {
        this.configureMethodInjection(bean);
    }

    private void configureMethodInjection(Object bean) {
        Class<?> managedBeanClass = bean.getClass();
        MethodCallback methodCallback = 
          new ReactiveMethodCallback(configurableBeanFactory, bean);
        ReflectionUtils.doWithMethod(managedBeanClass, methodCallback);
    } 
}
Run Code Online (Sandbox Code Playgroud)

3 - 创建方法回调(这里是要执行的逻辑)

public ReactiveMethodCallback implements MethodCallback {

    private ConfigurableListableBeanFactory configurableBeanFactory;
    private Object bean;

    public ReactiveMethodCallback(ConfigurableListableBeanFactory bf, Object bean) {
        configurableBeanFactory = bf;
        this.bean = bean;
    }

    @Override
    public void doWith(Method method) throws IllegalArgumentException, IllegalAccessException {
    if (!method.isAnnotationPresent(Reactive.class)){
      return;
    }
    //YOUR LOGIC HERE
  }

}
Run Code Online (Sandbox Code Playgroud)

这是关于注释处理的一个很好的来源,它是关于 FieldProcessing 但如果您有疑问,您可以更改接口以实现您需要的内容:https : //www.baeldung.com/spring-annotation-bean-pre-processor

[更新] 你也可以创建一个 HandlerInterceptor 来代替:

处理程序拦截器

public class ReactiveFilterHandlerInterceptor extends HandlerInterceptorAdapter {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws
    Exception {

        if (handler instanceof HandlerMethod) {
            HandlerMethod handlerMethod = (HandlerMethod) handler;
            // Test if the controller-method is annotated with @CustomFilter
            Reactive filter = handlerMethod.getMethod().getAnnotation(Reactive.class);
            if (filter != null) {
                // ... do the filtering, or call the Component for filtering
            }
        }
        return true;
    }
}
Run Code Online (Sandbox Code Playgroud)

并注册您的处理程序:

@Configuration
public class WebMvcConfig extends WebMvcConfigurer {

  @Autowired 
  ReactiveFilterHandlerInterceptor reactiveFilterHandlerInterceptor;

  @Override
  public void addInterceptors(InterceptorRegistry registry) {
    registry.addInterceptor(reactiveFilterHandlerInterceptor);
  }
}
Run Code Online (Sandbox Code Playgroud)

  • 感谢您的解决方案。奇怪的是你不能只使用弹簧过滤器,你必须做所有这些曼波·詹博 (3认同)