基于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 aop15this.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小时内删除。
发表评论