SpringBoot使用AOP与注解实现请求参数自动填充流程详解
愿做无知一猿 人气:0首先定义一个加在方法上的注解
import java.lang.annotation.*; /** * 开启自动参数填充 */ @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.METHOD}) @Documented @Inherited public @interface AutoParameterFill { /** * 要填充的字段名,不写的话默认下面类的子类中的字段都要填充 * * @see AutoParameterFillConstantsBase */ String[] includes() default {}; }
编写参数常量类
也就是参数名称,例如 String username 的 username ;
基础常量类:
/** * 便于扩展,后续反射获取所有子类的常量值 */ public class AutoParameterFillConstantsBase { //do nothing }
扩展的一个常量,拆分是为了将要填充的参数可以进行分类管理,避免一个类过大。
/** * 需要自动填充参数的字段名称 */ public class AutoParameterFillConstants extends AutoParameterFillConstantsBase { public final static String ID = "id"; public final static String ZHANG_SAN = "zhangsan"; public final static String TEST_ENTITY = "testEntity"; }
定义一个接口
@AutoParameterFill @RequestMapping("/test1") public Object test1(@RequestParam(required = false) String id, @RequestParam(required = false) String zhangsan, @RequestBody TestEntity testEntity) { return id + "----" + zhangsan + "----" + testEntity; }
TestEntity:
import lombok.Data; @Data public class TestEntity { private String id; private String name; }
编写对于不同参数的处理接口及实现
该类用于根据参数名获得指定实现:
import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.InitializingBean; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationContext; import org.springframework.stereotype.Component; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; /** * 处理并找到适配的实现 */ @Component public class AutoParameterAdapter implements InitializingBean { private final Map<String, AutoParameterHandler> handlerMap = new ConcurrentHashMap<>(); @Autowired private ApplicationContext applicationContext; @Override public void afterPropertiesSet() throws Exception { applicationContext.getBeansOfType(AutoParameterHandler.class).forEach((k, v) -> { if (StringUtils.isBlank(v.support())) { return; } handlerMap.put(v.support(), v); } ); } public void addParameter(String support, Object[] args, int i) { handlerMap.get(support).handle(args, i); } }
该类为统一接口:
/** * 处理统一接口 */ public interface AutoParameterHandler { /** * 处理参数赋值 * */ void handle(Object[] args, int i); /** * 支持的类型 */ String support(); }
该类为id参数处理实现:
import com.kusch.ares.annos.AutoParameterFillConstants; import org.springframework.stereotype.Component; /** * 处理ID参数 */ @Component public class IdAutoParameterFillHandler implements AutoParameterHandler { @Override public void handle(Object[] args, int i) { args[i] = "idididiidididididididid"; } @Override public String support() { return AutoParameterFillConstants.ID; } }
该类为zhangsan参数处理实现:
import com.kusch.ares.annos.AutoParameterFillConstants; import org.springframework.stereotype.Component; /** * 处理zhangsan参数 */ @Component public class ZhangSanAutoParameterFillHandler implements AutoParameterHandler { @Override public void handle(Object[] args, int i) { args[i] = "0000000000000000"; } @Override public String support() { return AutoParameterFillConstants.ZHANG_SAN; } }
该类为TestEntity参数处理实现:
import com.kusch.ares.annos.AutoParameterFillConstants; import com.kusch.ares.annos.TestEntity; import org.springframework.stereotype.Component; /** * 处理TestEntity参数 */ @Component public class TestEntityAutoParameterFillHandler implements AutoParameterHandler { @Override public void handle(Object[] args, int i) { TestEntity testEntity = new TestEntity(); testEntity.setId("TestEntityAutoParameterFillHandler"); testEntity.setName("TestEntityAutoParameterFillHandler"); args[i] = testEntity; } @Override public String support() { return AutoParameterFillConstants.TEST_ENTITY; } }
AOP具体实现
import com.kusch.ares.annos.handler.AutoParameterAdapter; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.reflect.MethodSignature; import org.reflections.Reflections; import org.springframework.core.MethodParameter; import org.springframework.stereotype.Component; import org.springframework.util.ObjectUtils; import org.springframework.web.method.HandlerMethod; import javax.annotation.Resource; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Set; /** * 处理参数自动填充 */ @Aspect @Component public class AutoParameterFillAop { @Resource private AutoParameterAdapter autoParameterAdapter; @Around(value = "@annotation(com.kusch.ares.annos.AutoParameterFill)") public Object around(ProceedingJoinPoint joinPoint) throws Throwable { Object[] args = joinPoint.getArgs(); MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature(); Method method = methodSignature.getMethod(); HandlerMethod handlerMethod = new HandlerMethod(joinPoint.getTarget(), method); //方法参数 MethodParameter[] methodParameters = handlerMethod.getMethodParameters(); //先获取方法注解,如果没有方法注解再去寻找参数注解 AutoParameterFill annotation = method.getAnnotation(AutoParameterFill.class); List<String> list = new ArrayList<>(); //获取注解的 includes 属性的值 String[] includes = annotation.includes(); if (ObjectUtils.isEmpty(includes)) { //获取 AutoParameterFillConstantsBase 所有子类常量类中的所有值 Reflections reflections = new Reflections(); Set<Class<? extends AutoParameterFillConstantsBase>> classes = reflections.getSubTypesOf(AutoParameterFillConstantsBase.class); for (Class<? extends AutoParameterFillConstantsBase> item : classes) { Field[] fields = item.getDeclaredFields(); for (Field field : fields) { list.add(String.valueOf(field.get(field.getName()))); } } } else { list.addAll(Arrays.asList(includes)); } //遍历方法参数 for (MethodParameter methodParameter : methodParameters) { for (String autoParameterFillConstants : list) { if (autoParameterFillConstants.equals(methodParameter.getParameter().getName())) { autoParameterAdapter.addParameter(autoParameterFillConstants, args, methodParameter.getParameterIndex()); } } } return joinPoint.proceed(args); } }
开启AOP记得在启动类加上 @EnableAspectJAutoProxy
补充关键jar包:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-aop</artifactId> </dependency> <!-- 反射工具包 --> <dependency> <groupId>org.reflections</groupId> <artifactId>reflections</artifactId> <version>0.10.2</version> </dependency> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-lang3</artifactId> </dependency>
使用方式
将你自己的参数名编写到 AutoParameterFillConstants
中,你也可以自己新建常量类,继承AutoParameterFillConstantsBase
即可。
实现AutoParameterHandler
接口,完成其中两个方法的编写。
在要填充的接口上,加上该注解,例如上述controller
@AutoParameterFill @RequestMapping("/test1") public Object test1(@RequestParam(required = false) String id, @RequestParam(required = false) String zhangsan, @RequestBody TestEntity testEntity) { return id + "----" + zhangsan + "----" + testEntity; }
不带参数,就说明只要参数名和 常量类中的匹配上,并且存在对应的实现类,就会自动填充参数。
带参数例如 @AutoParameterFill(includes = {AutoParameterFillConstants.ID,AutoParameterFillConstants.ZHANG_SAN})
这就代表这个接口只需要填充id和张三两个属性。
加载全部内容