Java自定义注解并实现注解的伪动态参数传递
自定义注解,此注解可以实现参数的伪动态传递,废话不多说直接上代码:一、需要引入的jar包:<dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId>&l
·
自定义注解,实现记录接口的调用日志,此注解可以实现传递伪动态参数。
一、需要引入的jar包:
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
<!-- test -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-test</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<!-- json -->
<dependency>
<groupId>commons-lang</groupId>
<artifactId>commons-lang</artifactId>
<version>2.4</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</dependency>
<dependency>
<groupId>commons-beanutils</groupId>
<artifactId>commons-beanutils</artifactId>
<version>1.8.0</version>
</dependency>
<dependency>
<groupId>commons-collections</groupId>
<artifactId>commons-collections</artifactId>
<version>3.2.1</version>
</dependency>
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.1.1</version>
</dependency>
<dependency>
<groupId>net.sf.json-lib</groupId>
<artifactId>json-lib</artifactId>
<version>2.4</version>
</dependency>
</dependencies>
二、自定义注解:
package com.example.demo.annotation;
import java.lang.annotation.*;
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ApiOperationLog {
String resourceId() default "";
String operationType();
String description() default "";
}
三、定义切面:
package com.example.demo.aspect;
import com.example.demo.annotation.ApiOperationLog;
import net.sf.json.JSONObject;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import java.util.HashMap;
import java.util.Map;
@Aspect
@Component
public class ApiOperationAspect {
@Pointcut("@annotation ( com.example.demo.annotation.ApiOperationLog)")
public void apiLog() {
}
@AfterReturning(pointcut = "apiLog()")
public void recordLog(JoinPoint joinPoint) {
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
// 获取方法上的指定注解
ApiOperationLog annotation = signature.getMethod().getAnnotation(ApiOperationLog.class);
// 获取注解中的参数
String resourceId = getAnnotationValue(joinPoint, annotation.resourceId());
String operationType = getAnnotationValue(joinPoint, annotation.operationType());
String description = getAnnotationValue(joinPoint, annotation.description());
System.out.println("resourceId:" + resourceId);
System.out.println("operationType:" + operationType);
System.out.println("description:" + description);
// 将注解中测参数值保存到数据库,实现记录接口调用日志的功能(以下内容省略...)
}
/**
* 获取注解中传递的动态参数的参数值
*
* @param joinPoint
* @param name
* @return
*/
public String getAnnotationValue(JoinPoint joinPoint, String name) {
String paramName = name;
// 获取方法中所有的参数
Map<String, Object> params = getParams(joinPoint);
// 参数是否是动态的:#{paramName}
if (paramName.matches("^#\\{\\D*\\}")) {
// 获取参数名
paramName = paramName.replace("#{", "").replace("}", "");
// 是否是复杂的参数类型:对象.参数名
if (paramName.contains(".")) {
String[] split = paramName.split("\\.");
// 获取方法中对象的内容
Object object = getValue(params, split[0]);
// 转换为JsonObject
JSONObject jsonObject = JSONObject.fromObject(object);
// 获取值
Object o = jsonObject.get(split[1]);
return String.valueOf(o);
}
// 简单的动态参数直接返回
return String.valueOf(getValue(params, paramName));
}
// 非动态参数直接返回
return name;
}
/**
* 根据参数名返回对应的值
*
* @param map
* @param paramName
* @return
*/
public Object getValue(Map<String, Object> map, String paramName) {
for (Map.Entry<String, Object> entry : map.entrySet()) {
if (entry.getKey().equals(paramName)) {
return entry.getValue();
}
}
return null;
}
/**
* 获取方法的参数名和值
*
* @param joinPoint
* @return
*/
public Map<String, Object> getParams(JoinPoint joinPoint) {
Map<String, Object> params = new HashMap<>(8);
Object[] args = joinPoint.getArgs();
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
String[] names = signature.getParameterNames();
for (int i = 0; i < args.length; i++) {
params.put(names[i], args[i]);
}
return params;
}
}
四:测试前的准备内容:
// 实体类
package com.example.demo.model;
public class User {
private Long id;
private String name;
private int age;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", name='" + name + '\'' +
", age=" + age +
'}';
}
}
// controller层内容
package com.example.demo.controller;
import com.example.demo.annotation.ApiOperationLog;
import com.example.demo.model.User;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class LoginController {
@ApiOperationLog(resourceId = "#{user.id}",operationType = "SAVE",description = "测试注解传递复杂动态参数")
public void saveUser(User user,String id){
System.out.println("测试注解...");
}
@ApiOperationLog(resourceId = "#{id}",operationType = "UPDATE",description = "测试注解传递简单动态参数")
public void updateUser(User user,String id){
System.out.println("测试注解...");
}
}
五、测试类:
package com.example.demo.aspect;
import com.example.demo.DemoApplication;
import com.example.demo.controller.LoginController;
import com.example.demo.model.User;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = DemoApplication.class)
public class ControllerTest {
@Autowired
private LoginController loginController;
@Test
public void test(){
User user = new User();
user.setId(1L);
user.setName("test");
user.setAge(20);
loginController.saveUser(user,"123");
loginController.updateUser(user,"666");
}
}
测试结果:
测试注解...
resourceId:1
operationType:SAVE
description:测试注解传递复杂动态参数
测试注解...
resourceId:666
operationType:UPDATE
description:测试注解传递简单动态参数
以上便是个人的学习分享,如有问题欢迎大家指正。
开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!
更多推荐
已为社区贡献5条内容
所有评论(0)