玩转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 成功啦~~~~~~~~