简介 开发中会经常遇到这样的场景:比如在成绩表有一个student_id,如果我要查看成绩列表需要学生的名称,一般写法就是使用join,现在大部分ORM框架对于表关联支持并不是很友好,所以很多时候我们都要自己写SQL去实现。
翻译服务即:通过id,将对应的title/name 字段翻译出,装载到VO中用于前端展示的技术.
1 FHS 提供的翻译服务如何使用? a定义翻译数据源.
@Service
@DataSource("base_business")
@AutoTrans(namespace = BaseTransConstant.ORG, fields = "name", useRedis = true, defaultAlias = "org")
public class UcenterMsOrganizationServiceImpl extends BaseServiceImpl implements UcenterMsOrganizationService {
通过以上定义,我们就能知道,组织机构的表,对外开放组织机构名称这个字段给其他的业务使用.
b标记业务pojo orgid字段使用此翻译数据源.
/**
* 所属机构
*/
@NotNull(message = "所属机构字段不可为null", groups = {Update.class, Delete.class})
@Length(message = "所属机构字段的长度最大为32", groups = {Add.class, Update.class}, max = 32)
@Column(name = "organization_id")
@Trans(type = TransType.AUTO_TRANS,key = BaseTransConstant.ORG )
private String organizationId;
c调用transService的trans相关方法即可.
public V d2v(D d) {
try {
if (d == null) {
return null;
}
V vo = voClass.newInstance();
BeanUtils.copyProperties(d, vo);
transService.transOne(vo);
return vo;
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
return null;
} public List dos2vos(List dos) {
List vos = ListUtils.copyListToList(dos, this.getVOClass());
transService.transMore(vos);
return vos;
}
c VO中需要有getTransMap 方法返回一个map,翻译服务会吧翻译的结果放到此map中.
【fhs-framework springboot mybatis 解决表关联查询问题的关键方案-翻译服务】d 翻译后的结果示例:
{
"between": {},
"createTime": "2019-03-25 00:00:00",
"createUser": "1",
"dataPermissin": {},
"dataPermissions": "{\"parkIds\":\"0d601eb23f0e11e99571d02788407b5e\"}",
"groupCode": null,
"inFilter": {},
"isDelete": null,
"isEnable": 1,
"methods": null,
"organizationId": "001",
"pkey": 1,
"remark": "12123",
"roleId": 1,
"roleName": "1231",
"state": null,
"transMap": {
"orgName": "机构",
"isEnableName": "启用",
"createUserUserName": "admin22"
},
"updateTime": "2019-03-29 00:00:00",
"updateUser": "62b5870c510c4e9da3f72460001c42fa"
},
2翻译服务实现
A 定义注解 自动翻译注解,把一个service当做数据源的注解,用于service实现类之上,比如上面的ORGservice
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.TYPE})
public @interface AutoTrans
{
/**
*命名空间
* @return
*/
String namespace();
/**
* 字段集合
* @return
*/
String[] fields();
/**
* 是否使用缓存翻译
* @return默认为true 如果是false的话
*/
boolean useCache() default true;
/**
* 是否使用redis存放缓存
* @return 默认false
*/
boolean useRedis() default false;
/**
* 默认的别名
* @return
*/
String defaultAlias() default "";
}
字段翻译注解,定义这个字段使用哪个翻译,比如fhs提供了auto(自动翻译),和wordbook(字典)
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.FIELD })
public @interface Trans {/**
* 获取翻译类型,比如 wordbook 是字典
* @return 类型
*/
String type();
/**
* 字段 比如要翻译男女 上面的type写wordbook 此key写sex即可
* @return
*/
String key() default "";
}
翻译类型集合,用于标记到 pojo上,代表我使用了哪些类型的翻译.
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.TYPE})
public @interface TransTypes
{
/**
* 获取需要翻译的类型
* @return
*/
String[] types();
}
B 定义翻译服务类 主要负责根据翻译的类型决定调用哪个ITransTypeService的实现类去翻译某些字段.
@Service("transService")
public class TransService {
/**
* key typeval是对应type的service
*/
private static Map transTypeServiceMap = new HashMap();
/**
* 注册一个trans服务
*
* @param type类型
* @param transTypeService 对应的trans接口实现
*/
public static void registerTransType(String type, ITransTypeService transTypeService) {
transTypeServiceMap.put(type, transTypeService);
}/**
* 翻译一个字段
*
* @param obj 需要翻译的对象
*/
public void transOne(VO obj) {
if (obj == null) {
return;
}
ClassInfo info = ClassManager.getClassInfoByName(obj.getClass());
String[] transTypes = info.getTransTypes();
if (transTypes == null) {
return;
}
List transFieldList = null;
for (String type : transTypes) {
transFieldList = info.getTransField(type);
if (transFieldList == null || transFieldList.size() == 0) {
continue;
}
transTypeServiceMap.get(type).transOne(obj, transFieldList);
}
}/**
* 翻译多个 字段
*
* @param objList 需要翻译的对象集合
* @param objList 需要翻译的字段集合
*/
public void transMore(List extends VO> objList) {
if (objList == null || objList.size() == 0) {
return;
}
Object object = objList.get(0);
ClassInfo info = ClassManager.getClassInfoByName(object.getClass());
String[] transTypes = info.getTransTypes();
if (transTypes == null) {
return;
}
List transFieldList = null;
for (String type : transTypes) {
transFieldList = info.getTransField(type);
if (transFieldList == null || transFieldList.size() == 0) {
continue;
}
transTypeServiceMap.get(type).transMore(objList, transFieldList);
}
}}
D 自动翻译实现
springboot启动成功后,扫描service包,被autotrans注解标记的service,解析autotrans的内容,然后把数据库中数据缓存到内存和redis中,当业务需要翻译的时候,根据id把缓存的数据拿出来,放到transmap中.
/**
* 本接类使用需要配合Autotrans 注解和autoTransAble的实现类
*
* @Description: 自动翻译服务
* @Author: Wanglei
* @Date: Created in 10:14 2019/10/15
*/
@Data
@Service
public class AutoTransService implements ITransTypeService, InitializingBean, ApplicationListener {public static final Logger LOGGER = LoggerFactory.getLogger(AutoTransService.class);
/**
* service的包路径
*/
@Value("${fhs.autotrans.package:com.*.*.service.impl}")
private String[] packageNames;
/**
* 翻译数据缓存map
*/
private Map> cacheMap = new HashMap<>();
/**
* 缓存 默认时间:半个小时
*/
@CreateCache(expire = 1800, name = "trans:cache:", cacheType = CacheType.REMOTE)
private Cache> transCache;
/**
* 基础服务
*/
private Map baseServiceMap = new HashMap<>();
/**
* 配置
*/
private Map transSettMap = new HashMap<>();
/**
* 如果直接去表里查询,放到这个cache中
*/
private ThreadLocal
全部源码地址 https://gitee.com/fhs-opensource/fhs-framework/tree/v2.x/fhs_extends/fhs_trans
开源项目地址:https://gitee.com/fhs-opensource/fhs-framework
fhs framework qq群:976278956
推荐阅读