前两天写业务接口的时候碰到一个实体类映射别名的问题,纠结想了很久,再这里我先简单的描述一下场景。
项目中常常对接第三方接口,由于别人的接口入参和回参都是别人定义的,你对接的过程中需要按照别人定义好的规范去接收,很多时候会和自己内部系统对外提供服务时候有很多字段冲突,先不说首字母大小写的问题,我举个例子,比如人家定义的车牌号字段为 LicenseNO,而我们自己使用命名为carNum等,比如再对接别人的接口还有叫其他名字的都很正常,那么如何管理这些对象间的映射呢,保证对外对内不会因为对象字段不一致出现矛盾呢?
其实方法有很多,但是肯定要考虑最优的一种解决方案,前两天我和同事讨论了一些方案,比如最简单的准备做一层Convertor转换,使用get,set做对象转换,当然首先代码很繁琐,实际维护起来麻烦,越到后面出现其他渠道对接还要重新准备第二套代码转换,随着业务迭代一层两层三层。。。
还有同事提出了在数据库做对象关系映射以及配置中心保存这些对象关系映射,再调用的时候去读数据库或者配置中心,我毫不犹豫的否决了,首先数据库保存会导致数据库开销非常大,物理连接太过频繁,随着业务量增大很容易压垮数据库,只为了做数据转化使用数据库太过于夸张,配置中心原理也是差不多,最后想出了使用map做关系映射,再调用接口的时候使用aop切面拦截统一处理对象转换。把请求参数校验-->接口路由-->参数适配->日志记录等统一在拦截器处理,如下图。
当然做对象适配处理,离不开java反射机制,这两天回顾了java.lang.Class类的api,正好在这里统一整理一下api方法的使用。
Class对象里面的方法:
1:String toString() -->此方法将Class
对象转换为字符串。
我们看下上面针对不同类型的对象使用toString()打印出什么
可以看出来Class
对象表示基本类型时候返回基本类型的名称
2:String toGenericString() -->返回描述此类的字符串,包括有关修饰符和类型参数的信息 -->直接看示例
3:String getName() ->返回由类对象表示的实体类,接口,数组类,原始类型的名称(含包名)
4:String getSimpleName()-->此方法返回源代码中给出的基础类的名称(不含包名)
5:Package getPackage()-->获取对象的包名
6:Field[] getFields() -->此方法返回一个Field对象数组,该对象反映此Class对象表示的类(及其所有超类)或接口(及其所有超类)的所有可访问公共字段
7:Method[] getMethods()-->此方法返回一个Method对象数组,这些对象反映了类或接口的所有可访问的公共方法,以及从此Class对象表示的超类和超级接口继承的方法。
8:Constructor<?>[] getConstructors()-->此方法返回一个Constructor对象数组,这些对象反映此Class对象所表示的类的所有公共构造函数
9: T newInstance()-->此方法创建此Class对象表示的类的新实例。通过具有空参数列表的新表达式创建类。如果尚未初始化,则初始化该类
当然这里还有很多api方法,比如
boolean isAssignableFrom(Class<?> cls)
此方法确定此Class对象表示的类或接口是否与指定的Class参数表示的类或接口相同,或者是超类或超接口。
boolean isInstance(Object obj)
此方法确定指定的Object是否与此Class表示的对象分配兼容。它相当于java中的instance of运算符
boolean isInterface()
此方法确定指定Class对象是否表示接口类型
boolean isPrimitive()
此方法确定指定的Class对象是否表示基本类型。即boolean , byte , char , short , int , long , float和double 。
boolean isArray()
此方法确定指定的Class对象是否表示数组类。
boolean isEnum()
当且仅当此类在源代码中声明为枚举时,此方法才返回true
以上并不是api所有的方法,感兴趣的同学可以没事自己翻阅api文档进行测试,
java.lang.Class的相关api操作虽然很容易看懂和使用,但是实际运用中却很重要,尤其是java的反射机制,虽然大家都了解,多多少少都会使用,但是在实际开发中往往使用很少,使用java反射机制起码在我这里可以做通用接口的参数校验,参数适配等逻辑。
以上就是今日的分享。