本文共 15185 字,大约阅读时间需要 50 分钟。
简介
开发中会经常遇到这样的场景:比如在成绩表有一个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中.
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 type val是对应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 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@Servicepublic 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
fhs framework qq群:976278956
转载地址:http://dhwni.baihongyu.com/