Filter 写好了,那么就需要配置上去,我们需要的 优雅的 功能开关,毕竟不是每个项目都要默认启用此FIlter。
听起来最简单的是,读取配置,根据配置项来决定是否注入 某Filter。
遗憾的是,我看到了一个 更装逼,更优雅的方式。
注解。
@UrlParamCheck // 只需要增加这个注解,就可以启用 UrlParamFilter。反之,不启用
public class App {
public static void main(String[] args) {
SpringApplication.run(App.class, args);
}
}
现在开始动手实现。
第一步 肯定是 定义注解
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE) // 此注解作用于类 上
@Documented
@Import(UrlParamCheckConfigRegistrar.class)
public @interface UrlParamCheck {
int order() default Ordered.LOWEST_PRECEDENCE;
}
第二步 编写一个工具类,用于 将一个filter 转换为 一份 Bean声明,并注册到 spring bean 声明的注册中心去。
@UtilityClass
@Slf4j
public class BeanDefinitionUtils {
/**
* 注册一个 filter
* @param registry 注册中心 ,待传入
* @param order Filter的挂载顺序
* @param name spring bean 的名称,全局唯一
* @param urlPatterns url过滤规则
* @param filter 待注册的filter
*/
public static void registerFilter(BeanDefinitionRegistry registry, int order, String name, Collection<String> urlPatterns, Object filter) {
if (registry.containsBeanDefinition(name)) {
log.warn("duplicate beanName, the bean exist in spring IOC,will skip :" + name);
return;
}
BeanDefinition annotationProcessor = BeanDefinitionBuilder
.genericBeanDefinition(FilterRegistrationBean.class)
.addPropertyValue("urlPatterns", urlPatterns)
.addPropertyValue("name", name)
.addPropertyValue("order", order)
.addPropertyValue("filter", filter)
.getBeanDefinition();
registry.registerBeanDefinition(name, annotationProcessor);
}
}
第三步,也是最重要的一步 编写 一个bean 声明 注册器
public class UrlParamCheckConfigRegistrar implements ImportBeanDefinitionRegistrar {
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
AnnotationAttributes attributes = AnnotationAttributes //固定写法,用于后续获取 此注解使用时所 定义的属性的值
.fromMap(importingClassMetadata
.getAnnotationAttributes(UrlParamCheck.class.getName()));
int order = attributes.getNumber("order"); // 通过attributes 可以获取注解所定义的属性的值
// 使用钢材声明的工具类,将 UrlParamCheckFilter 注册进spring
BeanDefinitionUtils.registerFilter(registry, order, "urlParamCheckFilter", Collections.singleton("/*"), new UrlParamCheckFilter());
}
}
实现完毕,最核心的就是 通过 注解上的 @Import(UrlParamCheckConfigRegistrar.class) 来引导spring 导入新的注册器,再通过注册器,注册一份新的 bean 声明,此处声明的是一个filter bean。其他的bean可以同样处理。
网友评论