基于SpringBoot、AOP与⾃定义注解转义字典值
  ⼀直以来,前端展⽰字典⼀般以中⽂展⽰为主,若在表中存字典值中⽂,当字典表更改字典值对应的中⽂,会造成数据不⼀致,为此设置冗余字段并⾮最优⽅案,若由前端⾃⼰写死转义,不够灵活,若在业务代码转义,臃肿也不够通⽤,从⽹络上了解到注解、AOP是⼀种不错的解决⽅案,主要有两种⽅式:
  1、通过注解获取结果集转为JSON字符串,通过正则查附加字段;
  2、通过获取结果集中相关字段上注解,此种⽅法有两个需要解决的问题,⽗类继承字段、嵌合对象难以解决获取对应注解字段问题,解决起来均⽐较⿇烦;
  因此本⽂采⽤第⼀种⽅法,能有效规避第⼆种⽅法相关问题,做到逻辑相对简单,引⼊缓存提⾼效率。
⼀、新建注解
  标注⽅法上使⽤
1 @Retention(RetentionPolicy.RUNTIME)
2 @Target(ElementType.METHOD)
3 @Documented
4public @interface TranslationDict {
5    FieldParam[] value();
6 }
  注解参数:FieldParam
1 @Retention(RetentionPolicy.RUNTIME)
2 @Target({ElementType.FIELD})
3 @Documented
4public @interface FieldParam {
5
6/**
7    * 字段类型默认字典
8    * Constant.FIELDTYPE_DICT 为⾃定义常量
9    * @return
10*/
11int type() default Constant.FIELDTYPE_DICT;
12
13/**
14    * 字典dictType
15    * @return
16*/
17    String dictType() default "";
18
19/**
20    * 要翻译的字段⽬标字段为翻译的字段+Str
21    * @return
22*/
23    String targetField() default "";
24
25/**
26    * 要翻译的字段值类型
27    * @return
28*/
29    Class targetFieldValueClazz() default String.class;
30
31 }
⼆、注解的使⽤
  在需要转义⽅法体上添加注解,在注解上指定需要转义的字段,不声明则使⽤默认值。
@TranslationDict({@FieldParam(dictType = "CUSTOMER_SEX", targetField = "sex"),
@FieldParam(dictType = "CUSTOMER_STATUS", targetField = "status", targetFieldValueClazz = Integer.class)})
三、新建切⾯
  切⾯核⼼在于将结果集转为JSON字符串,通过正则查询需要转义的字段,进⾏拼接替换,以增加属性。
1 @Aspect
2 @Component
3 @Slf4j
4public class TranslateFieldAspect {
5
6/**
7    * 翻译字典值
8    * @param joinPoint
9    * @return
10    * @throws Throwable
11*/
12    @Around("@annotation(com.vfangtuan.vftmon.annotation.TranslationDict)")
13public Object aroundMethodDict(ProceedingJoinPoint joinPoint) throws Throwable {
14//接收到请求时间
15        Long startTime = System.currentTimeMillis();
16//注意,如果调⽤joinPoint.proceed()⽅法,则修改的参数值不会⽣效,必须调⽤joinPoint.proceed(Object[] args) 17        Object result = joinPoint.proceed();
18
19// 第⼀步、获取返回值类型
20        Class returnType = ((MethodSignature) Signature()).getReturnType();
21
22//⾸先,取出要翻译字段的字典值
23        String returnJsonResult = JSONString(result);
24//开始解析(翻译字段注解参数指定的字段)
25        Method method = ((MethodSignature) Signature()).getMethod();
26//获取注解上参数
27        TranslationDict annotation = Annotation(TranslationDict.class);
28        FieldParam[] fieldParams = annotation.value();
29//遍历
30for (FieldParam fieldParam : fieldParams) {
31            log.info("开始翻译字典CODE:{},取值字段:{},取值字段值类型:{}.",
32                    fieldParam.dictType(),fieldParam.targetField(),fieldParam.targetFieldValueClazz());
33            Pattern dictPattern = getPattern(fieldParam);
34            Matcher dictMatcher=dictPattern.matcher(returnJsonResult);
35            StringBuffer sb = new StringBuffer();
36//转义字段
38            dictMatcher.appendTail(sb);
39            returnJsonResult = sb.toString();
40        }
41
42        result = JSONObject.parseObject(returnJsonResult,returnType);
43//如果这⾥不返回result,则⽬标对象实际返回值会被置为null
44//处理完请求时间
45        Long endTime = System.currentTimeMillis();
46        log.info("The request takes {}ms",endTime-startTime);
47return result;
48    }
49  /**
50    * 字典值转义为中⽂
51    * @param fieldParam
52    * @param fieldPattern
53    * @param fieldMatcher
54    * @param sb
55*/
56private void translateDict(FieldParam fieldParam, Pattern fieldPattern, Matcher fieldMatcher, StringBuffer sb) { 57//从缓存中⼀次性取值
58        Map<String, String> dictNames = DictNames(fieldParam.dictType());
59while (fieldMatcher.find()){
60
61//取出要翻译字段对应的值
62            Matcher dictValueMatcher = fieldPattern.up());
63            dictValueMatcher.find();
64            String group = up();
65//""sex":1", ""sex":"1"",""sex":null"
66//属性⽆值
67if (group.split(":").length <= 1) continue;
68            String dictName = "";
69
70//获取字典值
71            String dictValue = group.split(":")[1].replace("\"", "");
72//属性值⾮为空为空赋值空串
73if (StringUtils.isNotBlank(dictValue) && !LowerCase().equals("null")){
74//多值
75if (dictValue.split(",").length > 1){
76for (String s : dictValue.split(",")) {
77//fieldParam.dictType() + "_" + s 根据⾃⼰字典表设置的规则去查询
78                        dictName += (fieldParam.dictType() + "_" + s) + "/";
79                    }
80                }else {
81                    dictName = (fieldParam.dictType() + "_" + dictValue);
82                }
83            }
84
85            String s =  "\"" +  fieldParam.targetField() + "Str" + "\":\"" + dictName + "\"," + up();
86            log.debug("拼接后字符串:{}",s);
87            fieldMatcher.appendReplacement(sb, s);
88        }
89    }
90  /**
91    * 获取对应的正则式
92    * @param fieldParam
93    * @return
94*/
95private Pattern getPattern(FieldParam fieldParam) {
96        Pattern fieldPattern;//属性整型字符型
97if (fieldParam.targetFieldValueClazz().equals(Integer.class) ){
98            fieldPattern= Patternpile("\""+fieldParam.targetField() +"\":(\\d+)?");
99        }else {
100            fieldPattern= Patternpile("\""+fieldParam.targetField() +"\":\"([0-9a-zA-Z_,]+)?\"");
101        }
102return fieldPattern;
103    }
104 }
四、测试
  测试类
1 @Slf4j
2 @RestController
3 @RequestMapping("/demo")
4 @Api(tags="demo")
5public class DemoController {
6
7
8/**
9    * 测试注解字典
10    * @return
11*/
12    @TranslationDict({@FieldParam(dictType = "CUSTOMER_SEX", targetField = "sex"),
13            @FieldParam(dictType = "CUSTOMER_STATUS", targetField = "status", targetFieldValueClazz = Integer.class)})
14    @GetMapping("/test")
15    @ApiOperation(value = "测试字典转义")
16public ResultVo test1() {
17//接收到请求时间
18        Long startTime = System.currentTimeMillis();
19        List result = Result();
20//处理完请求时间
21        Long endTime = System.currentTimeMillis();
22        log.info("The request takes {}ms",endTime-startTime);
23return new ResultVo().success(result);
24    }
25
26private List getResult() {
27        List demos = new ArrayList<>();
28        Demo demo = new Demo("张三","1,2",1);
29        Demo demo2= new Demo("李四","2,1",2);
30        demos.add(demo);
31        demos.add(demo2);
32
33for (int i = 0; i < 5; i++) {
34            demos.add(new Demo("张三"+i,"1",1) );
35        }
36return demos;
37    }
实体对象
1 @Data
2public class Demo {
3
4private String name;
5
6private String sex;
7
8private Integer status;
9
10public Demo() {
11    }
12
13public Demo(String name, String sex, Integer status) {
14this.name = name;
springboot aop
15this.sex = sex;
16this.status = status;
17    }
18
19public Demo(String name) {
20this.name = name;
21    }
22
23public Demo(String name, String sex) {
24this.name = name;
25this.sex = sex;
26    }
27
28 }
测试效果
{
"code": 0,
"message": "success",
"data": [
{
"statusStr": "报备",
"sex": "1,2",
"name": "张三",
"sexStr": "男/⼥/",
"status": 1
},
{
"statusStr": "到访",
"sex": "2,1",
"name": "李四",
"sexStr": "⼥/男/",
"status": 2
},
{
"statusStr": "报备",
"sex": "1",
"name": "张三0",
"sexStr": "男",
"status": 1
},...
]
}
到此本⽂结束,如您有更好的解决⽅案,还请留⾔告知,⾮常感谢。
参考资料:blog.csdn/qq_44754081/article/details/106142458     blog.csdn/Better_Mei/article/details/103901273
     my.oschina/angelbo/blog/2875887

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。