字典翻译在我们应用里是一个很正常普遍的需求。
对于小型项目我们可能在数据库设计层面通常不会进行分库处理,那么对于此类项目,通常字典翻译会通过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"
}
}
}



被折叠的 条评论
为什么被折叠?



