java实现应用系统中字典统一翻译组件

字典翻译在我们应用里是一个很正常普遍的需求。

对于小型项目我们可能在数据库设计层面通常不会进行分库处理,那么对于此类项目,通常字典翻译会通过sql语句的子查询来处理,如果业务系统中存在较多的字段为code值时,我们需要编写大量的子查询用于code->name 的代码。在代码层面上造成代码的冗余,在查询数据体量较大的情况并且编写sql人员的能力的不足导致查询性能问题。

对于中大型项目我们可能数据库设计层面进行分库处理,在业务应用层面会通过使用微服务对其业务分割化(尤其现在微服务学习使用成本较低,有成熟的开源应用框架供我们使用-springcloud,dubbo)。那么对于字典这一所属公共服务,通常和业务库进行分库处理,那么使用sql语句进行代码翻译的途径也就无法使用,我们通常会将字典翻译暴露出内部公共api接口,通过内部调用(springcloud使用feign)对字段进行翻译,会造成代码的大量冗余(需要对进行翻译的对象进行迭代获取需要翻译的数据聚合一起调用接口返回数据,再迭代进行字段翻译)。会导致系统的不稳定性,业务系统存在大量的请求到公共服务,导致压力剧增。一旦公共服务挂掉会导致对外业务服务不可用(通过服务降级和增加公共服务集群数据可一定缓解压力)

DTC(Dictionaries Transformation Controller):通过简单配置(注解方式),非嵌入式代码(不想用时可直接关闭),无感知(对于使用者只需要编写一句调用方法即可)对javaBean对向进行字典翻译(满足嵌套复杂结构,支持字典本地-redis缓存)

如何使用DTC组件(spring Starter项目)

 定义基础配置和测试环境配置():

##定义测试数据库地
spring:
  #mysql数据库连接池配置
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://******:3306/***?useUnicode=true&useSSL=false&characterEncoding=UTF-8&allowMultiQueries=true
    username:***
    password:****
    filters: stat
    maxActive: 20
    initialSize: 1
    maxWait: 60000
    minIdle: 1
    timeBetweenEvictionRunsMillis: 60000
    minEvictableIdleTimeMillis: 300000
    validationQuery: select 'x'
    testWhileIdle: true
    testOnBorrow: false
    testOnReturn: false
    poolPreparedStatements: true
    maxOpenPreparedStatements: 20
    logSlowSql: false
#redis
redis:
  #redis机器ip
  hostname: 127.0.0.1
  #redis端口
  port: 6379
  #redis密码
  password:
  #redis超时时间(毫秒),如果不设置,取默认值2000
  timeout: 10000
  #最大空闲数
  maxIdle: 300
  #连接池的最大数据库连接数。设为0表示无限制,如果是jedis 2.4以后用redis.maxTotal
  #maxActive=600
  #控制一个pool可分配多少个jedis实例,用来替换上面的redis.maxActive,如果是jedis 2.4以后用该属性
  maxTotal: 10
  #最大建立连接等待时间。如果超过此时间将接到异常。设为-1表示无限制。
  maxWaitMillis: 1000
  #连接的最小空闲时间 默认1800000毫秒(30分钟)
  minEvictableIdleTimeMillis: 300000
  #每次释放连接的最大数目,默认3
  numTestsPerEvictionRun: 2
  #逐出扫描的时间间隔(毫秒) 如果为负数,则不运行逐出线程, 默认-1
  timeBetweenEvictionRunsMillis: 30000
  #是否在从池中取出连接前进行检验,如果检验失败,则从池中去除连接并尝试取出另一个
  testOnBorrow: true
  #在空闲时检查有效性, 默认false
  testWhileIdle: true
dtc:
  ###是否使用dtc 字典转换插件 默认为ture
  enabled: true
  cache:
    ### 缓存类型 支持redis与本地 这里使用redis
    type: redis
    ##后续会添加是否启用自动更新,即数据库中字典的变更会影响本地环境变更

定义查询sql,获取自身系统字典数据

package com.fc.dtcDemo.config;

import com.fc.dtc.bean.DictionaryBean;
import com.fc.dtc.cache.DictionaryJDBCActuator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;

import java.util.List;

@Configuration
public class DemoConfigure {

    @Bean
    public DictionaryJDBCActuator dictionaryJDBCActuator(){

        return new DictionaryJDBCActuator() {
            //
            @Override
            public List<DictionaryBean> execute(JdbcTemplate jdbcTemplate) {

                String sql = "select  type,name,code,item_order as item_order from dictionary where status =1";

                Object[] param = new Object[0];

                return jdbcTemplate.query(sql,param, new BeanPropertyRowMapper<>(DictionaryBean.class));

            }
        };
    }

}

 

package com.fc.dtcDemo.bean;

import com.fc.dtc.annotation.Translate;
import com.fc.dtc.annotation.TranslateProperty;
import lombok.Getter;
import lombok.Setter;

import java.io.Serializable;
import java.util.List;
import java.util.Map;


/**
 * 测试返回结果集Demo
 * @author fangyuan
 *
 */
/*
 *使用 @ApiModel 该对象转成json后的引用名称
 */
@Translate
@Getter
@Setter
public class TestVo  implements Serializable {
	/**
	 * 
	 */
	private static final long serialVersionUID = -8527981053862121515L;

	
	@TranslateProperty(encode=true,type="sex")
	private String sex;

	private String sex_mc;

	@TranslateProperty(encode=false,type="car")
	private String car_mc;

	private String car;

	@TranslateProperty(translate=TestVo1.class)
	private TestVo1 test1;
	
	@TranslateProperty(translate=TestVo1.class)
	private List<TestVo1> test1s;
	
	@TranslateProperty(translate=TestVo1.class)
	private Map<String, TestVo1> mapTestVo1;

	
}
package com.fc.dtcDemo.bean;

import com.fc.dtc.annotation.Translate;
import com.fc.dtc.annotation.TranslateProperty;
import lombok.Getter;
import lombok.Setter;

import java.io.Serializable;


/**
 * 测试返回结果集Demo
 * @author fangyuan
 *
 */
@Translate
@Getter
@Setter
public class TestVo1 implements Serializable {
	
	/**
	 * 
	 */
	private static final long serialVersionUID = -8527981053862121515L;

	@TranslateProperty(encode=true,type="phone")
	private String phone;

	private String phone_mc;

	@TranslateProperty(encode=false,type="clothes")
	private String clothes_mc;

	private String clothes;

}
        TestVo tv = new TestVo();

        tv.setSex("1");
        tv.setCar_mc("奔驰");

        TestVo1 tv1 = new TestVo1();

        tv1.setPhone("0");
        tv1.setClothes_mc("阿迪达斯");
        tv.setTest1(tv1);

        Map<String, TestVo1> m1 = new HashMap<>();

        m1.put("test", tv1);
        tv.setMapTestVo1(m1);

        List<TestVo1> tv1s = new ArrayList<>();
        tv1s.add(tv1);
        tv.setTest1s(tv1s);

        tv = dataTransformationUtils.transformationData(tv, TestVo.class, TestVo.class);

最终返回的测试结果:

{
    "sex": "1",
    "sex_mc": "男",
    "car_mc": "奔驰",
    "car": "0",
    "test1": {
        "phone": "0",
        "phone_mc": "华为",
        "clothes_mc": "阿迪达斯",
        "clothes": "2"
    },
    "test1s": [
        {
            "phone": "0",
            "phone_mc": "华为",
            "clothes_mc": "阿迪达斯",
            "clothes": "2"
        }
    ],
    "mapTestVo1": {
        "test": {
            "phone": "0",
            "phone_mc": "华为",
            "clothes_mc": "阿迪达斯",
            "clothes": "2"
        }
    }
}

源码github地址:https://github.com/fangyuan94/DTC

demo github地址:https://github.com/fangyuan94/dtcDemo

上一篇: 深入了解kafka机制
下一篇: springboot自定义Actuator
F_Hello_World
博客等级 码龄11年 38粉丝 58原创
评论 3
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值