自定义注解属性动态赋值

背景描述

通过使用自定义注解和拦截器的方式,来拦截请求验证用户权限。

  • 自定义注解:@UserAuth
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD,ElementType.TYPE})
public @interface UserAuth {
    	String[] value() default {};
}
  • 拦截器:
@Component
public class MyInterceptor implements HandlerInterceptor {
	    @Override
	    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
		        if(handler instanceof HandlerMethod){
		           	 	UserAuth userAuth = ((HandlerMethod) handler).getMethodAnnotation(UserAuth.class);
		          			if(userAuth != null){
		          					//权限验证
							}
		        }
		        return true;
	    }
}
@Configuration
public class InterceptorConfig implements WebMvcConfigurer {
	    private final MyInterceptor myInterceptor;
	
	    public InterceptorConfig(MyInterceptor myInterceptor) {
	        	this.myInterceptor = myInterceptor;
	    }
	
	    @Override
	    public void addInterceptors(InterceptorRegistry registry) {
	        	registry.addInterceptor(myInterceptor).addPathPatterns("/*");
	    }
}

@UserAuth中的value属性值想通过properties或yml配置文件动态注入。

  • application.properties
auth.key=search_list
  • Controller
@RestController
public class DemoController {
		@RequestMapping("/")
	    @UserAuth("${auth.key}")
	    public String demo(){
	        	return "hello world!" ;
	    }
}
  • 使用ConfigurableEnvironment类用来解析"${auth.key}"字符串。对拦截器进行改造:
@Component
public class MyInterceptor implements HandlerInterceptor {
	    @Autowired
	    private ConfigurableEnvironment environment;
	
	    @Override
	    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
		        if(handler instanceof HandlerMethod){
		        		//通过反射得到自定义注解
			            UserAuth userAuth = ((HandlerMethod) handler).getMethodAnnotation(UserAuth.class);
			            if(userAuth != null && userAuth.value().length > 0){
			            		//得到配置文件中对应的值
				                String codes = Arrays.stream(userAuth.value())
				                        .map(key -> environment.resolvePlaceholders(key))
				                        .collect(Collectors.joining(","));
				                System.out.println(codes);
			            }
			     }
		        return true;
	    }
}

首先通过反射得到自定义注解@UserAuthvalue"${auth.key}",然后以此作为key,通过environment.resolvePlaceholders()方法得到配置文件中对应的值。也可以把@UserAuthvalue值设为"auth.key",然后通过environment.getProperty()方法得到对应的值。

以上,已经实现了功能。但在得到这个方案的过程中,发现了更深层次的知识点,下面详细记录下。

知识点

  • 使用@ConfigurationProperties注解把application.properties的值注入到对象里

    @Component
    @ConfigurationProperties(prefix="auth")
    public class MyProperties{
    		private String key;
    		//set,get...
    }
    

    Controller改造

    @RestController
    public class DemoController {
    		@Autowired
        	private MyProperties properties;
        	
    		@RequestMapping("/")
    	    @UserAuth(properties.getKey())
    	    public String demo(){
    	        	return "hello world!" ;
    	    }
    }
    

    @UserAuth(properties.getKey())报错Attribute value must be constant注解里的属性值必须为常量,即static final修饰
    发现@ConfigurationProperties注解可以注入静态属性,参考:

    https://www.jianshu.com/p/149c5a951ffc

    使用静态还是同样的错,@UserAuth(MyProperties.key)

  • 查找注解的原理,发现了可以通过反射来动态修改注解属性的值,可参考:

    https://blog.csdn.net/u014750606/article/details/79977114
    https://www.cnblogs.com/acm-bingzi/p/javaAnnotation.html

    其中memberValues 的来源是Java 常量池

  • 2
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值