玩转aop,对http业务数据进行装箱拆箱

玩转aop,对http业务数据进行装箱拆箱

一:需求

这里采用通俗的语言描述下需求

前端发送的表单数据,需要将字段 NAME的内容 例如 ”ABCD“,前端没办法将 ABCD 转化为小写的 abcd

但是服务端需要用到小写的 abcd,而且前端回显的时候,需要字段 NAME的abcd 转化为 大写的”ABCD"

思路:

http表单请求来,用aop将特殊字段替换

http回显请求来,用aop将替换后的字段再还原

由于不想入侵业务代码,这里我们写一个注解来进行切入。

二:实现思路

首先你要掌握

  • Java
  • spring
  • springboot
  • 注解等基础知识

1. 写一个注解 里面有一个字段 标明是 装箱操作 还是拆箱操作

2. 写一个切面类 去切我们的注解 切面类中进行判断是装箱还是拆箱 走向不同的逻辑

3. 写一个 接口及实现类 函数包括:拆箱操作具体内容 装箱操作具体内容

4. 测试我们写的方法 写一个接口 用我们的注解

注意:String 等不可变的对象 不能修改其值和引用

三:Java代码

3.1:注解类

package xyz.fudongyang.manager.aspect.annotaion;


import xyz.fudongyang.manager.aspect.PackingTypeEnum;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * @author: vfudongyang
 * @createTime: 2022年02月17日 15:58:00
 * @Description: 对智能消息的包装
 */
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface AlgoMessagePacking {
    PackingTypeEnum packingType();
}

3.2: 切面类

package xyz.fudongyang.manager.aspect.aop;


import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import xyz.fudongyang.manager.aspect.PackingTypeEnum;
import xyz.fudongyang.manager.aspect.algo.IAlgoMessageAdvance;
import xyz.fudongyang.manager.aspect.annotaion.AlgoMessagePacking;
import xyz.fudongyang.manager.aspect.domain.*;

/**
 * @author: vfudongyang
 * @createTime: 2022年02月17日 16:00:00
 * @Description: 对智能消息的包装拦截器
 */
@Component
@Aspect
@Slf4j
public class AlgoMessagePackingAspect {

    @Autowired
    private IAlgoMessageAdvance algoMessageAdvance;

    @Around(value = "@annotation(algoMessagePacking)")
    public Object packingAop(ProceedingJoinPoint pjp, AlgoMessagePacking algoMessagePacking) throws Throwable {

        PackingTypeEnum packingTypeEnum = algoMessagePacking.packingType();

        if (PackingTypeEnum.MAKE.equals(packingTypeEnum)) {
            return make(pjp).proceed();
        }

        if (PackingTypeEnum.UN_MAKE.equals(packingTypeEnum)) {
            return unMake(pjp.proceed());
        }

        throw new IllegalAccessException("智能消息拆解包类型不支持");
    }

    private ProceedingJoinPoint make(ProceedingJoinPoint pjp) {
        Object[] args = pjp.getArgs();
        TaskInfoVersionReq req = (TaskInfoVersionReq)args[0];

        // String 不可变对象是不可以被修改的
        if (args.length==2){
            args[1] = "fudongyang";
        }

        TaskVersionReq version = req.getVersion();

        version.setTemplateJson(algoMessageAdvance.makeMessage(version.getTemplateJson()));

        return pjp;
    }

    private Object unMake(Object proceed) {
        DataResult<TaskResp> resp = (DataResult<TaskResp>)proceed;
        TaskResp data = resp.getData();
        TaskVersionResp version = data.getVersion();

        version.setTemplateJson(algoMessageAdvance.unMakeMessage(version.getTemplateJson()));

        return proceed;
    }
}

3.3: 装箱拆箱具体业务服务类

3.3.1: 接口类
package xyz.fudongyang.manager.aspect.algo;

/**
 * @author: vfudongyang
 * @createTime: 2022年02月17日 15:39:00
 * @Description:
 */
public interface IAlgoMessageAdvance {

    /**
     * 对数据进行修改
     *
     * @param templateJson 请求入参
     * @return java.lang.String
     */
    String makeMessage(String templateJson);

    /**
     * 对数据进行撤销修改
     *
     * @param templateJson 请求出参
     * @return java.lang.String
     */
    String unMakeMessage(String templateJson);
}

3.3.2:实现类
package xyz.fudongyang.manager.aspect.algo.impl;

import com.alibaba.fastjson.JSON;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import xyz.fudongyang.manager.aspect.NodeTypeEnum;
import xyz.fudongyang.manager.aspect.algo.IAlgoMessageAdvance;

import java.util.List;
import java.util.Map;

/**
 * @author: vfudongyang
 * @createTime: 2022年02月17日 15:54:00
 * @Description: 对智能消息的拦截处理
 */
@Service
@Slf4j
public class AlgoMessageAdvance implements IAlgoMessageAdvance {

    /**
     * 处理智能消息控件数据结构 category mvelKey字段 源字段值为:algoPush-algoSms
     * 由 mdata 中 messageType 的值(algoPush/algoSms)决定字段值修改为 algoPush/algoSms
     *
     * @param templateJson 请求入参
     */
    @Override
    public String makeMessage(String templateJson) {

        if (StringUtils.isNotEmpty(templateJson)) {
            Map<String, Object> jsonMap = JSON.parseObject(templateJson, Map.class);
            List<Map<String, Object>> nodes = (List<Map<String, Object>>) jsonMap.get("nodeDataArray");
            if (CollectionUtils.isNotEmpty(nodes)){
                for (Map<String, Object> node : nodes) {
                    String category = MapUtils.getString(node, "category");
                    if (NodeTypeEnum.ALGO_MESSAGE.getName().equals(category)){
                        Map<String, Object> mData = (Map<String, Object>) MapUtils.getObject(node, "mdata");
                        String messageType = MapUtils.getString(mData, "messageType");
                        node.put("category",messageType);
                        node.put("mvelKey",messageType);
                    }
                }
            }

            return JSON.toJSONString(jsonMap);
        }else {
            return templateJson;
        }
    }

    @Override
    public String unMakeMessage(String templateJson) {
        if (StringUtils.isNotEmpty(templateJson)) {
            Map<String, Object> jsonMap = JSON.parseObject(templateJson, Map.class);
            List<Map<String, Object>> nodes = (List<Map<String, Object>>) jsonMap.get("nodeDataArray");
            if (CollectionUtils.isNotEmpty(nodes)){
                for (Map<String, Object> node : nodes) {
                    String category = MapUtils.getString(node, "category");
                    if (NodeTypeEnum.ALGO_PUSH.getName().equals(category)
                            || NodeTypeEnum.ALGO_SMS.getName().equals(category) ){
                        node.put("category",NodeTypeEnum.ALGO_MESSAGE.getName());
                        node.put("mvelKey",NodeTypeEnum.ALGO_MESSAGE.getName());
                    }
                }
            }

            return JSON.toJSONString(jsonMap);
        }else {
            return templateJson;
        }
    }
}

3.4: 测试代码

3.4.1:controll类
package xyz.fudongyang.manager.test;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import xyz.fudongyang.manager.aspect.PackingTypeEnum;
import xyz.fudongyang.manager.aspect.annotaion.AlgoMessagePacking;
import xyz.fudongyang.manager.aspect.domain.DataResult;
import xyz.fudongyang.manager.aspect.domain.TaskResp;

/**
 * @author: vfudongyang
 * @createTime: 2022年02月17日 17:22:00
 * @Description:
 */
@RestController
@RequestMapping("/test/aop")
public class Controller {

    @Autowired
    private Test test;

    @RequestMapping("/unmake")
    @AlgoMessagePacking(packingType = PackingTypeEnum.UN_MAKE)
    DataResult<TaskResp> viewEdit(){
        return test.unMake();
    }
}

3.4.2: 测试接口
package xyz.fudongyang.manager.test;

import xyz.fudongyang.manager.aspect.domain.DataResult;
import xyz.fudongyang.manager.aspect.domain.TaskInfoVersionReq;
import xyz.fudongyang.manager.aspect.domain.TaskResp;

/**
 * @author: vfudongyang
 * @createTime: 2022年02月17日 17:13:00
 * @Description:
 */
public interface Test {

    void make(TaskInfoVersionReq req);

    void makeString(TaskInfoVersionReq req,String str);

    DataResult<TaskResp> unMake();
}

3.4.3: 测试接口实现类
package xyz.fudongyang.manager.test;

import com.alibaba.fastjson.JSON;
import org.springframework.stereotype.Service;
import xyz.fudongyang.manager.aspect.PackingTypeEnum;
import xyz.fudongyang.manager.aspect.annotaion.AlgoMessagePacking;
import xyz.fudongyang.manager.aspect.domain.*;

/**
 * @author: vfudongyang
 * @createTime: 2022年02月17日 17:14:00
 * @Description:
 */
@Service
public class TestImpl implements Test{

    @Override
    @AlgoMessagePacking(packingType = PackingTypeEnum.MAKE)
    public void make(TaskInfoVersionReq req) {
        TaskInfoVersionReq req1 = req;
        System.out.println(JSON.toJSONString(req1));
    }

    @Override
    @AlgoMessagePacking(packingType = PackingTypeEnum.MAKE)
    public void makeString(TaskInfoVersionReq req, String str) {
        System.out.println(str);
        System.out.println(JSON.toJSONString(req));
    }

    @Override
    public DataResult<TaskResp> unMake() {
        DataResult<TaskResp> result = new DataResult<>();
        TaskResp taskResp = new TaskResp();
        TaskVersionResp taskVersionResp = new TaskVersionResp();
        taskVersionResp.setTemplateJson(getStr());
        taskResp.setVersion(taskVersionResp);
        result.setData(taskResp);
        return result;
    }


    private String getStr(){
        return "{\"nodeDataArray\":[{\n" +
                "                    \"category\":\"algoPush\",\n" +
                "                    \"text\":\"智能消息\",\n" +
                "                    \"url\":\"/molo/img/push.png\",\n" +
                "                    \"enter\":true,\n" +
                "                    \"mvelKey\":\"algoPush\",\n" +
                "                    \"mdata\":{\n" +
                "                     \"sendStrategy\":  1 ,\n" +
                "                        \"isSend\":  1 ,            \n" +
                "                        \"messageType\":   \"algoPush\" ,    \n" +
                "               \"list\":\n" +
                "                        [\n" +
                "    \n" +
                "                    ]\n" +
                "                    },\n" +
                "                    \"key\":-2,\n" +
                "                    \"loc\":\"340 250\",\n" +
                "                    \"describe\":\"vv-北京-参数\"\n" +
                "                }]}";

    }

}

3.4.4: 测试http表单请求
package xyz.fudongyang.manager.test;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.RequestMapping;
import xyz.fudongyang.manager.aspect.domain.TaskInfoVersionReq;
import xyz.fudongyang.manager.aspect.domain.TaskVersionReq;

/**
 * @author: vfudongyang
 * @createTime: 2022年02月17日 17:16:00
 * @Description:
 */
@Component("aopMain")
public class Main implements CommandLineRunner {

    @Autowired
    private Test test;

    @Override
    public void run(String... args) throws Exception {
        TaskInfoVersionReq req =  new TaskInfoVersionReq();
        TaskVersionReq versionReq = new TaskVersionReq();
        versionReq.setTemplateJson(getStr());
        req.setVersion(versionReq);
        test.make(req);
        test.makeString(req,"req-first");
    }


    private String getStr(){
        return "{\"nodeDataArray\":[{\n" +
                "                    \"category\":\"algoPush-algoSms\",\n" +
                "                    \"text\":\"智能消息\",\n" +
                "                    \"url\":\"/molo/img/push.png\",\n" +
                "                    \"enter\":true,\n" +
                "                    \"mvelKey\":\"algoPush-algoSms\",\n" +
                "                    \"mdata\":{\n" +
                "                     \"sendStrategy\":  1 ,\n" +
                "                        \"isSend\":  1 ,            \n" +
                "                        \"messageType\":   \"algoPush\" ,    \n" +
                "               \"list\":\n" +
                "                        [\n" +
                "    \n" +
                "                    ]\n" +
                "                    },\n" +
                "                    \"key\":-2,\n" +
                "                    \"loc\":\"340 250\",\n" +
                "                    \"describe\":\"vv-北京-参数\"\n" +
                "                }]}";

    }
}

四:测试结果

测试目标:

  • http请求时 把 algoPush-algoSms 字符串 替换为 messageType 字符串的内容
  • http返回时 把曾经替换的值再还原回来

测试结果

http请求装箱
在这里插入图片描述

http请求拆箱

在这里插入图片描述

YES 成功啦~~~~~~~~

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
动态代理可以用来实现 AOP(面向切面编程)的功能。下面是一个简单的用动态代理实现 AOP数据进行操作的示例: 1. 创建一个数据源类 DataSource,其中包含了对数据库的增删改查操作。 ```java public interface DataSource { void insert(String data); void delete(String data); void update(String data); String select(); } ``` 2. 创建一个切面类 DataSourceAspect,该类实现了 InvocationHandler 接口,用于拦截 DataSource 类中的方法调用,并在方法前后执行一些操作。 ```java import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; public class DataSourceAspect implements InvocationHandler { private final DataSource dataSource; public DataSourceAspect(DataSource dataSource) { this.dataSource = dataSource; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { before(); Object result = method.invoke(dataSource, args); after(); return result; } private void before() { System.out.println("Before invoking method..."); } private void after() { System.out.println("After invoking method..."); } } ``` 3. 创建一个测试类 Test,用于测试动态代理对数据库操作的影响。 ```java import java.lang.reflect.Proxy; public class Test { public static void main(String[] args) { DataSource dataSource = new DataSourceImpl(); DataSourceAspect aspect = new DataSourceAspect(dataSource); DataSource proxy = (DataSource) Proxy.newProxyInstance( dataSource.getClass().getClassLoader(), dataSource.getClass().getInterfaces(), aspect); proxy.insert("data1"); proxy.select(); proxy.delete("data1"); proxy.update("data2"); } } ``` 运行 Test 类,可以看到在调用 DataSource 类的方法前后,会打印出 "Before invoking method..." 和 "After invoking method..." 的提示信息。 通过动态代理,我们实现了 AOP数据库的增删改查操作,将重复的操作(如日志记录、权限控制等)统一封装在切面类中,使得代码更加简洁和可维护。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值