实现一个类似SpringMVC的@RequestBody注解的部分小功能

在学习springMVC的时候,控制层方法参数上只需要加一个@RequestBody注解,然后就可以把前端传递get参数、post表单参数、Json数据转换成Java参数。这让我觉得非常神奇,非常厉害,为了学习,于是我打算实现一个这样的小小功能。

原理应该使用springAop功能对执行方法进行拦截,然后改变方法的执行参数。

一、先编写一个将普通字段值转换成Bean的类

public class parse {
    public static  <T> T read(Map<String,String> map, Class<T> clazz) throws Exception {
        Constructor<T> constructor = clazz.getConstructor();
        Method[] methods = clazz.getMethods();
        T object =constructor.newInstance();
        for (String key : map.keySet()){
            for (Method method : methods) {
                if (method.getName().contains("set"+key.replaceFirst(key.substring(0,1),key.substring(0,1).toUpperCase(Locale.ROOT)))) {
                    if (method.getParameterTypes()[0] == String.class) {
                        method.invoke(object, map.get(key));
                    }
                }
            }
        }
        return object;
    }
}

为了方便且容易实现,这里我使用的map作为参数。这里转换的JavaBean需要有无参构造方法,反射生成对象使用的是setter字段映射。

二、写一个注解来标记

@Target({ElementType.METHOD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
public @interface Request {
    boolean required() default false;
}

三、编写切面

@Aspect
@Component
public class aspectj2 {
    @Pointcut("execution(* com.ams.service.serviceImpl.user.*.*(..))")
    private void pointCut(){
    }
    @Around("pointCut()")
    public Object myAround(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        MethodSignature methodSignature = (MethodSignature) proceedingJoinPoint.getSignature();
        Method method = methodSignature.getMethod();
        Annotation[][] annotations= method.getParameterAnnotations();//获取方法参数上的注解
        Object obj=null;
        Map<String,String> map = new HashMap<>();
        map.put("password","123");
        log4j.getLogger().info(Arrays.toString(proceedingJoinPoint.getArgs()));
        for (int i = 0; i < method.getParameterCount(); i++)
            for (Annotation annotation : annotations[i]) {
                Request request = (Request) annotation;
                if (request.required()) {
                    map.put("username","true");
                    //替换执行参数值
                    proceedingJoinPoint.getArgs()[i] = parse.read(map, method.getParameterTypes()[i]);
                }
                else {
                    map.put("username","false");
                    proceedingJoinPoint.getArgs()[i] = parse.read(map, method.getParameterTypes()[i]);
                }
            }
        obj=proceedingJoinPoint.proceed(proceedingJoinPoint.getArgs());
        return obj;
    }


}

当这个aop环绕通知执行的时候,如果执行方法参数上有@Request注解,那么这个参数就会发生变化,这里为了简单方便我使用的是Map对象作为数据来源,实际上数据来源一般是前端传递过来的字节流或者字符流。

四、测试

//service层的方法
public void t1(@Request(required = true)user user1, @Request user user2,user user3) {
        log4j.getLogger().info(user1);
        log4j.getLogger().info(user2);
        log4j.getLogger().info(user3);
    }
@Test
    public void t8() {
        userService.t1(new user("user1","2342"),new user("user2","2333"),new user("zhang","12345"));
    }

对比发现方法参数前后发生了变化 。当然实现的这个功能非常简陋,实际情况是非常非常复杂。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值