有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java自定义注释过滤器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它将触发每个请求的反应过滤器实现

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

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

问候


共 (2) 个答案

  1. # 1 楼答案

    我将在这里详细介绍Spring中的定制注释和处理器

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

    你有两个选择:

    • 豆处理器
    • 手持拦截器

    BeanProcessor

    基本上,您需要构建三个组件:注释器、BeanProcessor和一个回调,以便在注释后执行逻辑。下面是一个示例及其工作原理:

    1.创建注释

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

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

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

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

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

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

    并注册你的处理程序:

    @Configuration
    public class WebMvcConfig extends WebMvcConfigurer {
    
      @Autowired 
      ReactiveFilterHandlerInterceptor reactiveFilterHandlerInterceptor;
    
      @Override
      public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(reactiveFilterHandlerInterceptor);
      }
    }
    
  2. # 2 楼答案

    如果我正确理解了您的需求,那么主要问题是如何基于自定义注释应用过滤器

    首先,是的,你可以使用一个常规的Spring过滤器(Spring Webflux是WebFilter,Spring MVC是Filter),但是你需要编写一些自定义逻辑

    要根据注释进行过滤,您应该:

    1. 使用RequestMappingHandlerMapping#getHandlerInternal()方法检索对处理请求的方法的引用(在您的例子中是getSingle()
    2. 当您设法检索HandlerMethod时,您可以检查该方法是否使用hasMethodAnnotation(Class<A> annotationType)方法应用了自定义注释
    3. 当您知道这一点时,您可以做出相应的反应:要么chain.doFilter(request, response)而不执行任何操作,要么应用自定义逻辑,然后触发过滤器链的其余部分