业务数据-自动翻译工具-第二版

前言

当你做业务内容开发时,数据库数据转化为人类数据,例如:机构id=>机构名称,用户Id=>用户名称。你是否受够了,不同业务的相同转化要写多次,写的抓狂。下面可以看看,我自己写的自动翻译工具,是否符合你的要求。

什么是自动翻译工具

自动翻译工具就是用来解决上述痛点,同时实现一次定义多处使用。通过AOP思想对接口进行拦截,自动触发数据转换和数据组装。只需要定义好翻译者,添加一些注解,剩下的就可以交给自动翻译工具了,电梯:使用场景-简单翻译。

主要思想

自动翻译工具,就是利用Spring AOP思想,对接口进行拦截,针对指定的对象,自动获取数据库数据,再主动调用用户定义的翻译者,获取人类数据,最后在自动填充。

代码结构

代码结构

说明:

  1. 用户自定义各种Translator,然后系统自动加载到TranslatorFactory,通过TranslateFactory提供翻译者。
  2. TranslateAspect是核心内容,通过自定义切面,拦截所有@TransAnnotation的方法。
  3. 也可以直接调用方法进行处理:com.jkf.translate.core.translate.TranslateManager.translate(Object obj, TranslateConfig config)。

开始使用

定义翻译者

继承公共的抽象Translator:AbstractTranslator。


/**
 * @author jiakunfeng
 */
@Component
public class OrgTranslator extends AbstractTranslator<Long, String> {
    @Override
    public String name() {
        return "orgTranslator";
    }

    @Override
    public Map<Long, String> translate(List<Long> result) {
        HashMap<Long, String> resultMap = Maps.newHashMap();
        //模拟查询数据库获取机构id和名称
        for (Long id : result) {
            resultMap.put(id, NameRandom.randomName() + id);
        }
        return resultMap;
    }
}

定义被翻译对象

使用TransObject、@TransSource、@TransTarget注解,标明相关的字段。注意:如果是同一个翻译者,@TransSource、@TransTarget的name属性要一致。

@Data
@NoArgsConstructor
@AllArgsConstructor
/**声明被翻译对象*/
@TransObject
public class KuWoUser implements Serializable {
    /**声明被翻译对象的id来源*/
    @TransSource(name="userTranslator")
    private Long id;
    /**声明被翻译对象的翻译结果填充*/
    @TransTarget(name="userTranslator")
    private String name;

    @TransSource(name="orgTranslator")
    private Long orgId;
    @TransTarget(name="orgTranslator")
    private String orgName;

    public KuWoUser(Long id,Long orgId){
        this.id = id;
        this.orgId = orgId;
    }

}

接口调用

添加注解@TransAnnotation,然后填写相关的参数即可,自动翻译工具会主动接收后续的工作。也可以手动调用方法:com.jkf.translate.core.translate.TranslateManager#translate。注意:默认支持的返回值类型为List,后续可以自定义,详情见“使用场景-自定义返回格式翻译”,可以修改:@TransAnnotation的retType的默认值。

@Service
@Slf4j
public class KuWoUserReadServiceImpl implements KuWoUserReadService{

    @Override
    @TransAnnotation(translators = {"userTranslator"})
    public List<KuWoUser> list() {
        KuWoUser user1 = new KuWoUser(1L,1111L);
        KuWoUser user2 = new KuWoUser(2L,2222L);
        return Lists.newArrayList(user1,user2);
    }

    @Override
    @TransAnnotation(translators = {"userTranslator","orgTranslator"})
    public List<KuWoUser> listByName() {
        KuWoUser user1 = new KuWoUser(1L,1111L);
        KuWoUser user2 = new KuWoUser(2L,2222L);
        return Lists.newArrayList(user1,user2);
    }

    @Override
    @TransAnnotation(translators = {"userTranslator"},retType = "obj")
    public KuWoUser findById() {
        return null;
    }
}

使用场景

简单翻译

简单翻译:根据Dto中的id直接翻译成名字。

  1. 定义翻译者,指定能解决的翻译格式。
/**
 * @author jiakunfeng
 * 根据用户id,返回相对应的用户名称
 */
@Component
public class UserTranslator implements Translator<Long,String> {
    @Override
    public String name() {
        return "userTranslator";
    }

    @Override
    public Map<Long, String> translate(List<Long> idList) {
        //模拟查询数据库获取数据
        return findUserName(idList);
    }

    private Map<Long,String> findUserName(List<Long> idList){
        Map<Long,String> userNameMap = new HashMap<>();
        for (Long id : idList) {
            userNameMap.put(id,"酷我音乐盒"+id);
        }
        return userNameMap;
    }
}
  1. 定义被翻译对象,添加@TransObject、@TransSource、@TransTarget
@Data
@NoArgsConstructor
@AllArgsConstructor
/**声明被翻译对象
这是简单根据id翻译名称。
*/
@TransObject
public class KuWoUser implements Serializable {
    /**声明被翻译对象的id来源*/
    @TransSource(name="userTranslator")
    private Long id;
    /**声明被翻译对象的翻译结果填充*/
    @TransTarget(name="userTranslator")
    private String name;

}.	
  1. 方法调用,添加TransAnnotation
@Service
@Slf4j
public class KuWoUserReadServiceImpl implements KuWoUserReadService{

    @Override
    @TransAnnotation(translators = {"userTranslator"})
    public List<KuWoUser> list() {
        return null;
    }

    @Override
    @TransAnnotation(translators = {"userTranslator"})
    public KuWoUser findById() {
        return null;
    }
}

说明:

  1. 自定义Translator时,name至关重要,必须保证不重复,重复会有异常提示,同时后续使用该翻译者的所有注解(@TransSource,@TransTarget)都必须相同。

批次翻译

批次翻译:Dto中用多个相同的变量,但是用的都是一个翻译器。例如:User中的创建人和更新人的名字。只需要修改步骤1。

/**Music对象中的创建人名字和更新人名字都是查询User库就可以翻译,这种现象就是批量翻译,即一个Dto存在多个字段需要用同一个翻译者进行翻译,因此通过group进行区分,请注意group的唯一性(同一个translator必须唯一)*/
@Data
@TransObject
public class Music implements Serializable {
    private Long id;
    @TransSource(name = "userTranslator",group = "creator")
    private Long creatorId;
    @TransTarget(name = "userTranslator",group = "creator")
    private String creatorName;
    @TransSource(name = "userTranslator",group = "operator")
    private Long operatorId;
    @TransTarget(name = "userTranslator",group = "operator")
    private String operatorName;

    public Music(Long id,Long creatorId,Long operatorId){
        this.id = id;
        this.creatorId = creatorId;
        this.operatorId = operatorId;
    }
}

剩余的步骤跟简单调用相同。主要是Dto的注解需要特殊处理。

继承翻译

父类声明了相关的翻译,那么子类继承后,不需要再次声明。

@Data
@TransObject
public class BaseUser implements Serializable {
    @TransSource(name="userTranslator")
    private Long id;
    @TransTarget(name="userTranslator")
    private String name;

    public BaseUser(Long id){
        this.id = id;
    }
}

@Data
public class QQUser extends BaseUser {

    public QQUser(Long id) {
        super(id);
    }
}

QQUser不需要相关的声明,使用的时候按照上述补步骤即可。

多内容翻译

Dto中存在多个需要翻译的字段,例如:存在机构名称、操作人名称需要翻译。只需要修改第2、3步骤即可。

  1. 不同字段添加不同的翻译者
@Data
@NoArgsConstructor
@AllArgsConstructor
/**声明被翻译对象*/
@TransObject
public class KuWoUser implements Serializable {
    /**声明被翻译对象的id来源*/
    @TransSource(name="userTranslator")
    private Long id;
    /**声明被翻译对象的翻译结果填充*/
    @TransTarget(name="userTranslator")
    private String name;

    @TransSource(name="orgTranslator")
    private Long orgId;
    @TransTarget(name="orgTranslator")
    private String orgName;

}
  1. 修改方法调用中翻译者,添加多个翻译者。
	@Override
    @TransAnnotation(translators = {"userTranslator","orgTranslator"})
    public List<KuWoUser> listByName() {
        KuWoUser user1 = new KuWoUser(1L,1111L);
        KuWoUser user2 = new KuWoUser(2L,2222L);
        return Lists.newArrayList(user1,user2);
    }

自定义返回格式翻译

自定义格式翻译:现在的返回值格式,只支持:List、Map(Key)、Map(Value)、Set、Array、单一Object(直接有@TransObject注解),如果想添加更多格式,例如:Response(包装返回值)、Paging(分页)等。只需要添加格式转化者和修改步骤3。

添加转换者

/**
 * 接口的返回值是Paging包装,进行拆包转List
 */
@Component
public class PagingReturnConverter extends AbstractReturnConverter {
    @Override
    public String name() {
        return "paging";
    }

    @Override
    public List<Object> covertReturn(Object ret) {
        Paging<Object> retPage = (Paging<Object>) ret;
        if (retPage.empty()) {
            return Lists.newArrayList();
        }
        return retPage.getData();
    }
}

添加retType

修改接口调用,@TransAnnotation的retType=“paging”

	@Override
    @TransAnnotation(translators = {"userTranslator"},retType = "paging")
    public Paging<KuGoUser> paging() {
        KuGoUser user1 = new KuGoUser(1L, 30,"浙江");
        KuGoUser user2 = new KuGoUser(2L, 31,"杭州");
        return new Paging<>(Lists.newArrayList(user1,user2),2L);
    }

注意事项

  1. AOP拦截的方法的返回值中的集合元素的Class文件必须相同,例如List的所有元素都是同一个Class,严禁:List:List.add(String),List.add(Integer)这种形式的集合。
  2. @TransAnnoation(translators={“XXX”})、@TransTarget(name=“XXX”)、@TransSource(name=“XXX”)、Translator的name()的字符串必须相同。

代码

先提供源码的zip文件,后续会放在git上。
下载地址:https://download.csdn.net/download/u010652576/15687040

说明

后续会补充自动翻译工具的由来和Spring AOP的相关内容。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值