使用注解翻译字典值

2019独角兽企业重金招聘Python工程师标准>>> hot3.png

使用注解翻译字典值

惯例,贴码云地址

https://gitee.com/imbobo_bo/angel-bo

本文描述的都可以在码云上找到

需求

在服务端开发,数据库表中有些字段对应的是字典值,在查询的时候要展示字典值,这个时候可能就需要关联字典表查询,或者在前后端开发过程中,由前端页面展示的部分调取字典服务的接口来展示,但这样都有问题,前者是数据库字典变更时要修改SQL,都不合理,那有没有更优雅的方式来完成字典值翻译呢?

思路

现在都使用springboot来开发服务,springboot的注解太好用了,能不能使用切面拦截器的方式来完成字典翻译呢?

@TranslationDict({@DictParam(dictCode = "USER_GENDER_CODE",dictValueFiled = "gender",dictNameFiled = "genderName")})

启用AOP 拦截注解TranslationDict,注解里描述需要翻译的字段,字典CODE,和目标字段(翻译完成后对应的值存储)

实现

新建注解类

/**
 * 翻译字典值注解
 */
@Retention(RUNTIME)
@Target(METHOD)
@Documented
public @interface TranslationDict {

    DictParam[] value();
}

/**
 * 需要翻译的字典值
 *
 * */

@Retention(RUNTIME)
@Target(METHOD)
@Documented
public @interface DictParam {

    /**
     * 字典CODE
     * @return
     */
    String dictCode() default "";

    /**
     * 需要翻译的字段名
     * @return
     */
    String dictValueFiled() default "";


    /**
     * 被翻译的字段名
     * @return
     */
    String dictNameFiled() default "";

}

新建拦截器

@Around("@annotation(translationDict)")
    public Object Translation(final ProceedingJoinPoint pjp, TranslationDict translationDict) throws Throwable {
        Object result = pjp.proceed();
        // 第一步、获取返回值类型
        Class returnType = ((MethodSignature) pjp.getSignature()).getReturnType();

        //首先,取出要翻译字段的字典值
        String returnJsonResult = toJSONString(result);

        DictParam[] dictParams = translationDict.value();
        for (DictParam dictParam : dictParams) {
            log.info("开始翻译字典CODE:{},取值字段:{},目标字段:{}",dictParam.dictCode(),dictParam.dictValueFiled(),dictParam.dictNameFiled());
            //从缓存里取出字典信息
            WebReturn webReturn = (WebReturn) getFromCache(CacheType.DICT_INFO_TRANSLATION, CacheType.DICT_INFO_TRANSLATION.name()+"#"+dictParam.dictCode(), WebReturn.class);

            if(null == webReturn){
                return result;
            }
            List dictInfos = JSONObject.parseArray(webReturn.getData().toString(),DictInfo.class);

            //先把字典值转成map
            for (DictInfo dictInfo : dictInfos) {
                dictInfoMap.put(dictInfo.getDictCode()+"#"+dictInfo.getDictInfoValue(),dictInfo.getDictInfoName());
            }

            Pattern dictPattern= Pattern.compile("\"" + dictParam.dictValueFiled() +".*?,");
            Matcher dictMatcher=dictPattern.matcher(returnJsonResult);
            StringBuffer sb = new StringBuffer();
            while (dictMatcher.find()){

                //取出要翻译字段对应的值
                Matcher dictValueMatcher = dictValuePattern.matcher(dictMatcher.group());
                dictValueMatcher.find();
                //翻译字典
                String dictInfoName = dictInfoMap.get(dictParam.dictCode()+"#"+dictValueMatcher.group());

                String s = dictMatcher.group() + "\"" +  dictParam.dictNameFiled() + "\":\"" + dictInfoName + "\",";
                dictMatcher.appendReplacement(sb, s);
            }
            dictMatcher.appendTail(sb);
            returnJsonResult = sb.toString();
        }
        result = getJsonToResultObject(returnJsonResult,returnType);
        return result;
    }

拦截器主要逻辑:拦截方法,把返回值转成JSON,然后根据注解翻译JSON, 从JSON中取出DictParam中的 dictValueFiled字段的值,然后根据DictParam中的dictCode翻译对一个的字典,然后将翻译好的值插入dictNameFiled这个字段

例子:

返回JSON值为

{userId:1,geneder:1,userName:'zhangsan'}

注解为:

@TranslationDict({@DictParam(dictCode = "USER_GENDER_CODE",dictValueFiled = "gender",dictNameFiled = "genderName")})

拦截器处理时取出gender字段对应的值“1”和字典“USER_GENDER_CODE”翻译为“男性”,然后将男性赋值给genderName字段

{userId:1,geneder:1,genderName:'男性',userName:'zhangsan'}

然后将JSON转对象返回即可,当然,要翻译的javabean必须要有genderName字段

##优化

拦截器优化,翻译字典从缓存里读取。。。

转载于:https://my.oschina.net/angelbo/blog/2875887

你可能感兴趣的:(java,json,数据库)