问题:
目前的项目是前后端耦合在一块的,后台框架提供数据字典,以及字典翻译的功能,不过只能在thymeleaf中通过el表达式来使用,在基于uni-app框架开发app时,无法使用表达式来获取字典值,只能通过重复的请求来获取,这显然是不可能的。重复,繁琐。
解决方案:
后台通过切面在提供数据APP接口返回数据之前对返回的数据进行字典翻译翻译完成之后再将数据返回给APP端。
思路
1.依据框架提供的原始接口,翻译字典需要提供字典类型和字典值。
2.可以通过注解修饰方法和字段,来传递字典类型和字典值
。
3.除了字典值和字典类型以外,还需要获取目标方法的返回值对象的全路径映射。因为需要翻译的对象是未知的,所以需要通过类加载器来动态获取。另外还需要知道返回值对象是集合类型还是对象类型
4.在切面中通过反射获取目标方法中的注解回来获取到字典类型、字典值、需要翻译对象的全路径、返回值类型
5.通过类加载器获取翻译对象的字节码对象
6.在切面中通过切入点对象执行目标方法,获取到目标方法的返回值
7.通过fastjson将返回值转换成JSON字符串,在将JSON字符串指定转换为刚才通过类加载器加载的对象,得到未经过翻译的对象
8.如果对象为集合类型,则遍历翻译,如果为对象类型,直接翻译即可
9.翻译首先获取字典类型和字典值,通过反射获取,然后调用框架原始接口,得到翻译后的字典标签。最后赋值给未经过翻译的对象
10.将翻译完成后的对象返回给前台
具体实施
1.1 此步骤对应思路 1-3
自定义两个注解:@DictTranslate、@DictField。
@DictTranslate注解修饰方法,注解需要提供的属性:
targetObj:指定返回值对象的全路径,如果是集合类型,则指定集合元素对象的全路径。必填
returnType:指定返回值对象的类型,默认为集合类型
@DictField注解修饰目标对象中的字段,注解需要提供的属性:
value:指定该字段对应的字典类型。
自定义切面:DictTranslateAspect。
1.2 此步骤对应思路4-6
切面配置织入点为被注解@DictTranslate修饰的方法。
在切面方法中通过切入点对象获取方法上的注解以及注解值——返回值对象全路径、返回值类型。将全路径传给类加载器获取到字节码对象。
执行表方法获取到返回值——未经过翻译的对象。
1.3 此步骤对应思路7
使用fastjson将返回值通过toJSONString转换方法成JSON字符串,然后在将JSON字符串通过parseArray或者parseObject方法指定转换为我们需要的对象,指定接收的字节码对象为上一步通过类加载器加载的字节码对象。
若为集合类型时:
若为对象类型时:
1.4 此步骤对应思路8-10
如果为集合类型,则遍历集合获取到集合中每一个元素的字节码对象。然后反射获取被注解@DictField修饰的字段的值——即字典值,以及注解上的字典类型。
获取到字典类型和字典值之后调用原始集合查询字典值对应的字典标签。然后利用反射给原来对象赋值,这里我想过使用get、set方法拼接的方式,不改变原来字段的访问权限,但是会报错,提示我,反射执行方法的对象没有实例化,具体不知道什么原因。然后我索性直接将访问权限设置为共有,然后赋值完成之后再改为私有。
以上操作执行完之后直接返回即可。
如果为对象类型,只是少了一个遍历操作,其他与集合类型的代码基本一致。如下: