大家好,我是霸戈,好久没有写代码(文章)了, 闲下来整理了一篇文章,感谢大家的阅读和支持。
写接口时经常碰到要把某个枚举值返回给前端展示,然后前端要把这个枚举值显示成文本。在没有典文本映射功能之前前端就需要把这些枚举值和文本对应起来然后做展示,或者后台直接把枚举值转换成文本然后返回给前端。
如果后端能直接把枚举值的文本自动的设置到返回实体的某个属性上,这样就能解决了枚举值文体的转换问题了,话不多说开整。
实体设计
字典本身并不复杂,所以设计实体也比较简洁:
public class Dict {
private String id;
private String name;
private String value;
private String type;
private String pid;
private String status;
private Integer sort;
private String description;
}
各项属性说明如下:
id : 字典的id
name: 字典的名称,一般用于前端展示
value:字典的值
type:字典的类型
status: 字典的状态
sort: 排序
description: 字典的描述信息
pid: 上级字典id,有些特殊的字典有上下级关系,比如存放城市的时候
上面的字典设计是非常直观的一个字典项对应数据库中的一行,相同的字典项由类型(type)来标识。
字典文本映射
比如下面的响应就是经过字典文本映射的:
{
"code": "SUCCESS",
"success": true,
"message": "操作成功",
"data": {
"id": "1496108440362811394",
"status": "DISABLE",
"statusDesc": "禁用",
...
}
}
status
是一个字典值,statusDesc
是status
的文本表示。
下面来一起看看如何利用Spring
来实现字典文本映射的。
定义字典属性注解
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface DictProperty {
/**
* 字典类型
* @return
*/
String type();
/**
* 字典数据值属性名称
* @return
*/
String value();
}
注解属性说明:
type:对应字典的类型属性
value: 字典数据值属性名称
如何使用?
@Data
public class UserDTO {
private String status;
@DictProperty(type = "user_status", value = "status")
private String statusDesc;
}
在UserDTO
里面的status
属性是字典的值, statusDesc
是字典值的名字。
实现方式
实现可以使用aop
,但我发现SpringMVC
提供了个非常好的切入点:ResponseBodyAdvice
,继承此接口就能对请求的响应做一些小修改。
public interface ResponseBodyAdvice<T> {
boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType);
@Nullable
T beforeBodyWrite(@Nullable T body, MethodParameter returnType, MediaType selectedContentType,
Class<? extends HttpMessageConverter<?>> selectedConverterType,
ServerHttpRequest request, ServerHttpResponse response);
}
supports方法:判断实体类型是否能处理
beforeBodyWrite: 如果
supports
返回ture,就会执行这个方法,这个方法可以修改返回的实体。
大致的实现思路:
在
beforeBodyWrite
方法利用Java反射来读取实体属性的DictPropty
注解解析
DictPropty
注解的type
的值,然后通过字典类型获取到对应的字典读取到对应类型的字典后,将字典的
name
写入到实体的属性上
@Slf4j
@ControllerAdvice
public class DictResponseBodyAdvice implements ResponseBodyAdvice<Object> {
@Autowired
private IDictService dictService;
@Override
public boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType) {
return true;
}
@Override
public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class<? extends HttpMessageConverter<?>> selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {
if(body instanceof Result){
handleBody(((Result) body).getData());
}else if(body instanceof IPage){
handleBody(((IPage) body).getRecords());
}else{
handleBody(body);
}
return body;
}
}
篇幅有限,省略了一些代码,利用 SpringMV
C 提供扩展接口与Java反射
就可以轻松实现字典的文本映射。
后续考虑
上面的代码已经实现了字典文本映射的功能,但还有一些可以优化一下:
读取字典的时候要加缓存,防止数据量过大读取字典的字数过大,拖慢接口的响应速度
可以不通过
ResponseBodyAdvice
也能实现字典映射,只需要传入对象就能实现字典映射功能。...
项目推荐
分享一套家庭理财系统(附源码)
推荐一套开源通用后台管理系统(附源码)
推荐一个酷炫的监控系统
从朋友那里搞了 20 个实战项目,速领!
推荐一个完善的停车管理系统,物联网项目springboot,附源码
推荐一个互联网企业级别的开源支付系统
一款神仙接私活儿软件,吊到不行!
推荐 10 款超实用的企业级开源应用!
开放平台 SDK 设计实践!
“淘宝” 开放平台接口设计思路
Spring中经典的9种设计模式