2021年6月29日星期二

基于SpringBoot 、AOP与自定义注解转义字典值

本文为解决项目中字典值的转义问题,通过注解获取结果集转为JSON字符串,再通过正则查找附加字段,完成字典值的转义。

  一直以来,前端展示字典一般以中文展示为主,若在表中存字典值中文,当字典表更改字典值对应的中文,会造成数据不一致,为此设置冗余字段并非最优方案,若由前端自己写死转义,不够灵活,若在业务代码转义,臃肿也不够通用,从网络上了解到注解、AOP是一种不错的解决方案,主要有两种方式:

  1、通过注解获取结果集转为JSON字符串,通过正则查找附加字段;

  2、通过获取结果集中相关字段上注解,此种方法有两个需要解决的问题,父类继承字段、嵌合对象难以解决获取对应注解字段问题,解决起来均比较麻烦;

  因此本文采用第一种方法,能有效规避第二种方法相关问题,做到逻辑相对简单,引入缓存提高效率。

一、新建注解

  标注方法上使用

1 @Retention(RetentionPolicy.RUNTIME)2 @Target(ElementType.METHOD)3 @Documented4 public @interface TranslationDict {5  FieldParam[] value();6 }

  注解参数:FieldParam

 1 @Retention(RetentionPolicy.RUNTIME) 2 @Target({ElementType.FIELD}) 3 @Documented 4 public @interface FieldParam { 5  6  /** 7   * 字段类型 默认字典  8   * Constant.FIELDTYPE_DICT 为自定义常量 9   * @return10  */11  int type() default Constant.FIELDTYPE_DICT;12 13  /**14   * 字典dictType15   * @return16  */17  String dictType() default "";18 19  /**20   * 要翻译的字段 目标字段为翻译的字段+Str21   * @return22  */23  String targetField() default "";24 25  /**26   * 要翻译的字段值类型27   * @return28  */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 4 public class TranslateFieldAspect { 5  6  /** 7   * 翻译字典值 8   * @param joinPoint 9   * @return 10   * @throws Throwable 11  */ 12  @Around("@annotation(com.vfangtuan.vft.common.annotation.TranslationDict)") 13  public 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) joinPoint.getSignature()).getReturnType(); 21  22   //首先,取出要翻译字段的字典值 23   String returnJsonResult = JSONObject.toJSONString(result); 24   //开始解析(翻译字段注解参数指定的字段) 25   Method method = ((MethodSignature) joinPoint.getSignature()).getMethod(); 26   //获取注解上参数 27   TranslationDict annotation = method.getAnnotation(TranslationDict.class); 28   FieldParam[] fieldParams = annotation.value(); 29   //遍历 30   for (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    //转义字段 37    this.translateDict(fieldParam,dictPattern,dictMatcher,sb); 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); 47   return result; 48  } 49   /** 50   * 字典值转义为中文 51   * @param fieldParam 52   * @param fieldPattern 53   * @param fieldMatcher 54   * @param sb 55  */ 56  private void translateDict(FieldParam fieldParam, Pattern fieldPattern, Matcher fieldMatcher, StringBuffer sb) { 57   //从缓存中一次性取值 58   Map<String, String> dictNames = DictData.getDictNames(fieldParam.dictType()); 59   while (fieldMatcher.find()){ 60  61    //取出要翻译字段对应的值 62    Matcher dictValueMatcher = fieldPattern.matcher(fieldMatcher.group()); 63    dictValueMatcher.find(); 64    String group = dictValueMatcher.group(); 65    //""sex":1", ""sex":"1"",""sex":null" 66    //属性无值 67    if (group.split(":").length <= 1) continue; 68    String dictName = ""; 69  70    //获取字典值 71    String dictValue = group.split(":")[1].replace("\"", ""); 72    //属性值非为空 为空赋值空串 73    if (StringUtils.isNotBlank(dictValue) && !dictValue.toLowerCase().equals("null")){ 74     //多值 75     if (dictValue.split(",").length > 1){ 76      for (String s : dictValue.split(",")) { 77       //fieldParam.dictType() + "_" + s 根据自己字典表设置的规则去查询 78       dictName += dictNames.get(fieldParam.dictType() + "_" + s) + "/"; 79      } 80     }else { 81      dictName = dictNames.get(fieldParam.dictType() + "_" + dictValue); 82     } 83    } 84  85    String s = "\"" + fieldParam.targetField() + "Str" + "\":\"" + dictName + "\"," + fieldMatcher.group(); 86    log.debug("拼接后字符串:{}",s); 87    fieldMatcher.appendReplacement(sb, s); 88   } 89  } 90   /** 91   * 获取对应的正则式 92   * @param fieldParam 93   * @return 94  */ 95  private Pattern getPattern(FieldParam fieldParam) { 96   Pattern fieldPattern;//属性整型 字符型 97   if (fieldParam.targetFieldValueClazz().equals(Integer.class) ){ 98    fieldPattern= Pattern.compile("\""+fieldParam.targetField() +"\":(\\d+)?"); 99   }else {100    fieldPattern= Pattern.compile("\""+fieldParam.targetField() +"\":\"([0-9a-zA-Z_,]+)?\"");101   }102   return fieldPattern;103  }104 }

四、测试

  测试类

 1 @Slf4j 2 @RestController 3 @RequestMapping("/demo") 4 @Api(tags="demo") 5 public class DemoController { 6  7  8  /** 9   * 测试注解字典10   * @return11  */12  @TranslationDict({@FieldParam(dictType = "CUSTOMER_SEX", targetField = "sex"),13    @FieldParam(dictType = "CUSTOMER_......

原文转载:http://www.shaoqun.com/a/836064.html

跨境电商:https://www.ikjzd.com/

acca是什么:https://www.ikjzd.com/w/1370

adore:https://www.ikjzd.com/w/2202

王惟:https://www.ikjzd.com/w/1744


本文为解决项目中字典值的转义问题,通过注解获取结果集转为JSON字符串,再通过正则查找附加字段,完成字典值的转义。  一直以来,前端展示字典一般以中文展示为主,若在表中存字典值中文,当字典表更改字典值对应的中文,会造成数据不一致,为此设置冗余字段并非最优方案,若由前端自己写死转义,不够灵活,若在业务代码转义,臃肿也不够通用,从网络上了解到注解、AOP是一种不错的解决方案,主要有两种方式:  1、通
巴克莱银行:https://www.ikjzd.com/w/2775
宁波放大招!2019年中国跨境电商高峰论坛亮点颇多!:https://www.ikjzd.com/articles/97189
物流小知识!教你查询最新出口美国的豁免清单产品:https://www.ikjzd.com/articles/97190
海外版聚划算来袭?跨境商品测评返佣平台上线了!:https://www.ikjzd.com/articles/97191
商用餐厨在亚马逊欧洲日本的特色选品/合规要求/采购痛点:https://www.ikjzd.com/articles/97192
村长把小娥压在玉米地 又粗又大的机巴好爽:http://lady.shaoqun.com/m/a/247046.html
几个学长一起要我厕所 学长你的好大我不敢:http://lady.shaoqun.com/m/a/247930.html
口述我与同事的出轨经历细节 他的承诺像烟花一样转瞬即逝:http://www.30bags.com/m/a/250528.html
90%的人在床上都会犯的性错误:http://lady.shaoqun.com/a/391589.html
福田区公共体育场馆7月1日免费开放指南:http://www.30bags.com/a/462515.html
深圳福田区游泳馆有哪些:http://www.30bags.com/a/462516.html
2021年的Prime Day会员日表现如何?:https://www.ikjzd.com/articles/146195

没有评论:

发表评论