自定义注解属性动态赋值

背景描述

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

  • 自定义注解:@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
    评论
Java中,自定义注解(Annotation)是一种元数据,用于在代码中提供附加信息,而这些信息通常不会直接影响程序的执行。自定义注解实体类是一种用户创建的注解类型,它包含一个或多个字段,这些字段可以存储额外的数据。 要创建一个自定义注解,你需要按照以下步骤操作: 1. 定义注解类:创建一个新的Java接口,添加你想要的属性(@Retention, @Target, 或者你自己定义的字段),例如: ```java import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Retention(RetentionPolicy.RUNTIME) // 表示注解在运行时可用 @Target(ElementType.METHOD) // 指定注解可以应用在方法上 public @interface MyCustomAnnotation { String value(); int priority() default 0; } ``` 这里定义了一个名为`MyCustomAnnotation`的注解,有两个属性:`value`和`priority`。 2. 在目标类中使用注解:在需要应用注解的方法上添加注解,例如: ```java public class MyClass { @MyCustomAnnotation(value = "Important Method", priority = 1) public void myMethod() { // 方法体... } } ``` 3. AOP(面向切面编程)与自定义注解:Spring AOP或AspectJ等工具可以让你在运行时扫描并处理带有特定注解的方法。你可以编写一个切面(Aspect),使用`@Around`, `@Before`, 或 `@After` 等通知处理`@MyCustomAnnotation`注解的方法。例如,你可能想在方法执行前后执行一些额外的操作,或者根据`priority`属性决定是否执行某些操作。 ```java @Aspect @Component public class MyAspect { @Around("@annotation(myCustomAnnotation)") public Object advice(ProceedingJoinPoint joinPoint, MyCustomAnnotation myCustomAnnotation) throws Throwable { System.out.println("Before executing method with priority: " + myCustomAnnotation.priority); Object result = joinPoint.proceed(); System.out.println("After executing method with priority: " + myCustomAnnotation.priority); return result; } } ```
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值