自定义注释过滤器Spring Boot

时间:2019-10-17 15:10:34

标签: 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");
    }

@Reactive会在每个请求触发ReactiveFilter实现。

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

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

致谢

2 个答案:

答案 0 :(得分:2)

我将在这里尝试描述有关自定义注释和Spring中的处理器的更多信息。

我不知道您想要什么,但我将举一个通用的例子。

您有2个选择:

  • BeanProcessor
  • HandlerInterceptor

BeanProcessor

您基本上需要构建3件事:Annotaton,BeanProcessor和Callback,如果有注释,则执行您的逻辑。这是一个示例及其工作方式:

1-创建注释

className

2-实现BeanPostProcessor

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

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

 @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);
    } 
}

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

[更新],您也可以改为创建HandlerInterceptor:

HandlerInterceptor

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
  }

}

并注册您的处理程序:

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;
    }
}

答案 1 :(得分:0)

如果我正确理解了您想要的内容,则主要问题是如何基于自定义注释应用过滤器。

因此,首先,是的,您可以使用常规的Spring过滤器(对于Spring Webflux,使用WebFilter;对于Spring MVC,则使用Filter),但是您需要编写一些自定义逻辑

要基于注释进行过滤,您应该:

  1. 使用RequestMappingHandlerMapping#getHandlerInternal()方法检索对处理请求的方法的引用(在您的情况下为getSingle()
  2. 当您设法检索HandlerMethod时,可以检查该方法是否将您的自定义注释与hasMethodAnnotation(Class<A> annotationType)方法一起应用。
  3. 知道这一点后,您可以做出相应的反应:chain.doFilter(request, response)不执行任何操作,或者应用您的自定义逻辑,然后触发其余的过滤器链。
相关问题