limp-cloud:API接口码表转换功能设计

 

1. 业务场景介绍

功能描述:数据接口如何实现字典表的快速转换

举例:如一张人员表的性别(SEX)字段这样定义 1代表男  2代表女

返回人员接口信息如下

{"SEX":1,"NAME":"张三"}

但是业务需要转换为如下信息(字段1转化为了

{"SEX":"男","NAME":"张三"}

2. 开发实战

这里快速梳理下集成步骤

1)定义相关字典表

规则:1代表男  2代表女 即对应码表编号和码表名称

特别说明:key为性别的规范定义字段如SEX代表性别,也就是key和码表编号 查询 可以确定一条记录

2)Java实体类标明需要转换的字段(人员表举例)

  字段转换标识:字段@JSONField标识 name:显示字段+转换前缀+字典Key

  @JSONField(name="rc3"+ Constant.CODE_TRANS_PRE+"SEX")

rc3需要字典转换,对应转换为码表中SEX性别的字典值

public class UserInfo  extends AbstractModel implements Serializable {
    private String id;

    private String account;

    private String name;


    /**
     * 性别标识-需要码表转换的字段:举例 用@JSONField标识
     * name:显示字段+转换前缀+字典Key
     * 即是:name="rc3"+ Constant.CODE_TRANS_PRE+"SEX"
     */
    @JSONField(name="rc3"+ Constant.CODE_TRANS_PRE+"SEX")
    private Integer rc3;


}

3.码表转换开关

Controller注入核心Servce

 @Autowired
CoreService coreService;

返回Json数据开启码表转换getJson(coreService)

Result.getInstance(...).getJson(coreService);

    @RequestMapping(value = "/loginUserInfo",method= RequestMethod.GET)
    public String loginUserInfo() {
        UserInfo user=ApplicationContext.getLoginUser();
      
        UserInfo userInfo=userInfoService.get(user.getId());
       
        return Result.getInstance(ResultCode.SUCCESS.toString(), ResultMsg.SUCCESS,userInfo,"").getJson(coreService);
    }

4.效果展示

3.源码剖析

设计原则:最小改动、不影响其他接口业务、符合常规码表定义规则

核心技术点:fastJson的JSONField功能、正则字符串替换、Result类的封装

部分代如下

Result返回类


package com.limp.framework.core.bean;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializeConfig;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.alibaba.fastjson.serializer.SimpleDateFormatSerializer;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
//import com.limp.framework.boss.service.CommonService;
import com.limp.framework.core.constant.ExceptionEnum;
import com.limp.framework.core.constant.ResultMsg;
import com.limp.framework.core.service.CoreService;
import com.limp.framework.utils.StrUtils;
import com.limp.framework.utils.TextUtils;
import org.apache.log4j.Logger;

import java.io.Serializable;
import java.sql.Timestamp;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * Created with IntelliJ IDEA.
 * @author: zzh
 * Date: 16-6-12
 * Time: 下午11:55
 * To change this template use File | Settings | File Templates.
 */
public class Result implements Serializable {


    private static Logger log= Logger.getLogger(Result.class);

    /**
     * 字符串
     */
    private static  final String EMPTY_STRING="";
    /**
     * 返回状态码 : 如 200
     */
    private static  final String CODE="code";
    /**
     * 返回提示信息:如 更新成功
     */
    private static  final String MSG="msg";
    /**
     * 返回数据集合:如list对象等
     */
    private static  final String RESULT="result";
    /**
     * 额外参数:如Map个格式的其他数据
     */
    private static  final String EXT="ext";
    /**
     * 返回状态代码
     */
    private String code;
    /**
     * 提示信息
     */
    private String msg;
    /**
     * 返回数据
     */
    private Object data;

    /**
     * 返回结果map
     */
    private Map resultMap;

    /**
     * 格式化数据字符串
     */
    private String formatJsonStr;



    /**
     * 返回结果
     * @param code 状态码
     * @param msg  提示信息
     * @param data  结果集合
     * @param param 额外参数
     */
    public Result(String code,String msg,Object data,Object param){
        this.code=code;
        this.msg=msg;
        this.data=data;
        resultMap=new HashMap();
        resultMap.put(CODE,code);
        resultMap.put(MSG,this.msg);
        if(!StrUtils.isBlank(data)){
            resultMap.put(RESULT,this.data);
        }
        if(!StrUtils.isBlank(param)){
            resultMap.put(EXT,param);
        }
        this.resultMap=resultMap;
    }

    /**
     * 正确的返回结果
     * @param data
     */
    public Result(Object data){
        this.msg=msg;
        this.data=data;
        resultMap=new HashMap();
        resultMap.put(CODE,200);
        resultMap.put(MSG,"success");
        if(!StrUtils.isBlank(data)){
            resultMap.put(RESULT,this.data);
        }
        this.resultMap=resultMap;
    }
    /**
     * 返回异常信息
     * @param exceptionEnum
     * @return
     */
    public final static Result getException(ExceptionEnum exceptionEnum) {
        String arr[]= exceptionEnum.getKey().split("_");
        return new Result(arr.length>1?arr[0]:ResultCode.ERROR.toString(),arr.length>1?arr[1]: ResultMsg.ERROR.toString(),exceptionEnum.getValue(),"");
    }

    /**
     *  返回异常信息
     * @param exceptionStr
     * @return
     */
    public final static Result getException(String exceptionStr) {
        return new Result(ResultCode.ERROR.toString(),exceptionStr,"","");
    }


    /**
     * 返回结果格式化
     * @param code 状态值 200成功 500错误
     * @param msg 提示信息
     * @param data 返回数据
     * @param param ext其他参数
     * @return  调用Result.getJson()返回json数据
     */
    public final static Result getInstance(String code,String msg,Object data,Object param) {
        return new Result(code,msg,data,param);
    }

    /**
     * 正确返回结果
     * @return
     */
    public final static Result Success() {
        return new Result(ResultCode.SUCCESS.toString(),ResultMsg.SUCCESS,"","");
    }

    /**
     * 错误返回结果
     * @return
     */
    public final static Result Error() {
        return new Result(ResultCode.ERROR.toString(),ResultMsg.ERROR,"","");
    }

    /**
     * 错误返回结果
     * @param msg 返回信息
     * @return
     */
    public final static Result Error(String msg) {
        return new Result(ResultCode.ERROR.toString(),msg,"","");
    }

    /**
     * FASTjson【obj】转化为【json】
     * @param obj
     * @return
     */
    public static String toJSONString(Object obj) {
        if (StrUtils.isBlank(obj)) {
            return EMPTY_STRING;
        }
        return JSON.toJSONString(obj);
    }
    public final static String transCodeZN(CoreService commonService, Object obj){

        //定义返回JSON字符串
        String returnJson = "";
        SerializeConfig ser = new SerializeConfig();
    /*    *
         * 注意:有些json字符串返回的不是如下时间格式,校验方式:检查该字段是否是Date类型(其他Object类型无效)
      */
        ser.put(Date.class, new SimpleDateFormatSerializer("yyyy-MM-dd  HH:mm:ss"));
        try {

          /*  1、格式化时间
             2、禁止循环
             3、fastjson将bean转成字符串时首字母变小写问题:方案在bean的属性get方法上加注解 @JSONField(name = "RC2") public String getRC2() return RC2;
           */
            returnJson = JSON.toJSONString(obj, ser, SerializerFeature.WriteNullListAsEmpty,
                    SerializerFeature.DisableCircularReferenceDetect);
        } catch (Exception e) {

        }
        //格式化数据字符串使用
        //转码方法
            Long start=System.currentTimeMillis();
            returnJson= commonService.transCodeZN(returnJson);
            Long end=System.currentTimeMillis();
            log.info(TextUtils.format("码表转换解析需要时间为:{0}毫秒",end-start));
        return returnJson;

    }

    /**
     *第一个参数为转码service
     * 格式JSON数据( resultMap的json格式数据)
     * @return 转换后的json字符串
     */
   public String getJson(CoreService... commonServices) {
//    public String getJson() {
        if (StrUtils.isBlank(this.resultMap)) {
            return null;
        }
        //定义返回JSON字符串
        String returnJson = "";
        SerializeConfig ser = new SerializeConfig();
        ser.put(Date.class, new SimpleDateFormatSerializer("yyyy-MM-dd  HH:mm:ss"));
        try {
            /*
            1、格式化时间
             2、禁止循环
             3、fastjson将bean转成字符串时首字母变小写问题:方案在bean的属性get方法上加注解 @JSONField(name = "RC2") public String getRC2() return RC2;
             */
            returnJson = JSON.toJSONString(this.resultMap, ser, SerializerFeature.WriteNullListAsEmpty,
                    SerializerFeature.DisableCircularReferenceDetect);
        } catch (Exception e) {
            log.error("-----JSON转换异常【实体类Timestamp类型请定义为Date类型接收】-----");

            Gson gson2 = new GsonBuilder().setDateFormat("yyyy-MM-dd HH:mm:ss").enableComplexMapKeySerialization()
                    .registerTypeAdapter(Timestamp.class, new TimestampTypeAdapter()).create();
            log.error(e);
            returnJson= gson2.toJson(this.resultMap);
            this.formatJsonStr = returnJson;
            return returnJson;
        }
        //格式化数据字符串使用
        this.formatJsonStr=returnJson;
        //转码方法
        if (commonServices.length>0) {
            Long start=System.currentTimeMillis();
            log.debug(TextUtils.format("-----码表转换开始-----"));
            log.debug(returnJson);
            returnJson= commonServices[0].transCodeZN(returnJson);
            Long end=System.currentTimeMillis();
            log.debug(TextUtils.format("-----码表转换结束-----"));

            log.debug(TextUtils.format("码表转换解析需要时间为:{0}毫秒", end - start));
        }
        return returnJson;
    }
    public String getCode() {
        return code;
    }

    public void setCode(String code) {
        this.code = code;
    }

    public String getMsg() {
        return msg;
    }

    public void setMsg(String msg) {
        this.msg = msg;
    }

    public Object getData() {
        return data;
    }

    public void setData(Object data) {
        this.data = data;
    }

    public Map getResultMap() {
        return resultMap;
    }

    public void setResultMap(Map resultMap) {
        this.resultMap = resultMap;
    }

}

字典表转换类

package com.limp.framework.boss.service.impl;

import com.limp.framework.boss.domain.DicCode;
import com.limp.framework.boss.domain.PageLog;
import com.limp.framework.boss.mapper.oracle.PageLogMapper;
import com.limp.framework.boss.service.CacheService;
import com.limp.framework.boss.service.CommonService;
import com.limp.framework.boss.service.SysService;
import com.limp.framework.core.bean.Pager;
import com.limp.framework.core.constant.Constant;
import com.limp.framework.utils.StrUtils;
import com.limp.framework.utils.TextUtils;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;

/**
 * @Description: 通用类实现方法
 * @Author: zzh
 * @Modified By:
 * @Date: 2018/10/17 16:54
 */
@Service
public class CommonServiceImpl implements CommonService {

    private static Logger log= Logger.getLogger(CommonServiceImpl.class);

    @Resource
    private PageLogMapper pageLogMapper;

    @Resource
    private CacheService cacheService;
    /**
     *字典码表
     */
    @Autowired
    private SysService dictCodesService;

    @Override
    public void insertPageLog(PageLog pageLog) {
        try{
            if (StrUtils.isBlank(pageLog.getId())) {
                pageLog.setId(StrUtils.randomUUID());
            }
            if (StrUtils.isBlank(pageLog.getState())) {
                pageLog.setState(Constant.STATE_EFFECTIVE);
            }
            if (StrUtils.isBlank(pageLog.getIdt())) {
                pageLog.setIdt(new Date());
            }
            pageLogMapper.insert(pageLog);
        }catch (Exception e){
            log.debug("/****日志记录异常************/");
            e.printStackTrace();
        }

    }


    @Override
    public String transCodeZN(String jsonStr) {
        //lp_code_  }或者]结尾【定义需要替换CODE的正则匹配规则】
        final  String pattern= Constant.CODE_TRANS_PRE+"(.*?)[,|\\}|\\]]";

        //key 的集合 (唯一;去重)
        List listUnKsy=new ArrayList();

        //需要转化的码表 key 和value对应集合
        List<Map<String,String>> listMapMath=new ArrayList<Map<String,String>>();

        //匹配List得到的Group分组
        List<String> groups= StrUtils.getRegGroupList(jsonStr, pattern);
        Long start=System.currentTimeMillis();
        log.debug(TextUtils.format("-----获取key-value值-----"));
        for(String group:groups){
//            String []groupArr=group.split(":");
            //需要转换Key:value
            String codeMath=group.replaceAll("\'|\"", "");
            if(codeMath.indexOf(Constant.CODE_SUF)>-1){
//                String pre=groupArr[0].substring(0,groupArr[0].indexOf(Constant.CODE_SUF)+1);
//                String codeMath=pre+groupArr[1].replaceAll("\'|\"", "");
                //如果该value值已经获取相应的码值,则不再进行查询
                if(!StrUtils.isBlank(codeMath)&&!listUnKsy.contains(codeMath)){
                    listUnKsy.add(codeMath);
                    Map<String,String> code=new HashMap<String,String>();
                    String value=getCacheCodeValue(codeMath);//commonService.getCacheCodeValue(codeMath);
                    //只有value不为空,才进行转化
                    if(!StrUtils.isBlank(value)){
                        code.put("key",Constant.CODE_TRANS_PRE+group);
                        code.put("value", value);
                        code.put("pre",group.indexOf("\"")>-1?"\"":"\'" );
                        listMapMath.add(code);
                    }

                }
            }
        }
        Long end=System.currentTimeMillis();
        log.debug(TextUtils.format("----->获取key-value值需要时间{0}[key-value]-----",(end-start)));

        //循环转换字典表
        for(Map<String,String> mapF:listMapMath){
            //获取需要转换的key
            final String reg=mapF.get("key");
//          final String reg="('"+mapF.get("key")+"':|\""+mapF.get("key")+"\":|"+mapF.get("key")+":)";
//           String reg=":"+key+"|:'"+key+"'|:\""+key+"\"";
            //转换后的信息 ":"男"  注意,转后的应该带上引号,是描述信息
            final String replaceVal=mapF.get("pre")+":"+mapF.get("pre")+mapF.get("value")+mapF.get("pre");
            try {
                jsonStr=jsonStr.replaceAll(reg,replaceVal);
            }catch (Exception e){
                log.error("-->正则转化异常");
                e.printStackTrace();
            }
        }
//        jsonStr=jsonStr.replaceAll(Constant.CODE_TRANS_PRE+"(.*?)#","");
        return jsonStr;
    }

    @Override
    public String getCacheCodeValue(String key) {
        log.debug(TextUtils.format("-->getCacheCodeValue方法调用;Key值:{0}",key));
        String val= cacheService.get(key);
        if(StrUtils.isBlank(val)){
            log.debug(TextUtils.format("-->无此key({0})值得缓存,开始添加到缓存池<--",key));
            DicCode dicCodes=new DicCode();
            String dictKey[]=key.split(Constant.CODE_SUF);
            dicCodes.setDictKey(dictKey[0]);
            dicCodes.setDictValue(dictKey[1]);
            Pager<DicCode> list=dictCodesService.getDicPageList(dicCodes,new Pager(1,1));
            for(DicCode codes:list
                    .getDataList()){
                cacheService.set(key,codes.getDictName());
                log.debug(TextUtils.format("添加缓存数据 set key:{0} value:{1}",
                        key, codes.getDictName()));

            }
            val=cacheService.get(key);
            log.debug("reload cache key----> "+val);
        }
        return val;
    }
}

主要是这两个类,其它的有需要深入了解 的可以下方留言

在保证正常业务的流程下,码表转化该方法还是比较方便的,有其它方法也欢迎留言

发布了240 篇原创文章 · 获赞 176 · 访问量 38万+

猜你喜欢

转载自blog.csdn.net/zzhuan_1/article/details/105399316