Dragon
真诚欢迎您的来访,留言,投稿!欢迎(Ctrl+D)收藏并经常访问本站 --- 3uyx.com
  • 真诚欢迎您的来访,留言,投稿!欢迎(Ctrl+D)收藏并经常访问本站 --- 3uyx.com
adminAdmin  2024-07-05 11:36 沃付网络 隐藏边栏 |   抢沙发  6 
文章评分 0 次,平均分 0.0

在 SpringBoot 中,默认枚举的响应和请求都是以枚举名称为对应值,如果我们需要自定枚举的响应值和请求值,就需要单独处理,本次我们就来聊聊一些比较简单快捷方便的处理方式。

响应值

总所周知,SpringBoot内置的 HTTP 响应结构序列化是使用的 Jackson,所以我们只需要在对应的枚举字段上加上@JsonValue 即可,例如:

@AllArgsConstructor  
@Getter  
public enum ApprovalStatus {WAIT(1, " 未审核 "),  
    SUCCESS(2, " 审核成功 "),  
    FAIL(3, " 审核失败 ");  
 
    @JsonValue  
    private final Integer index;  
    private final String desc;  
 
}

这样,在响应结构体中就会直接返回枚举中的 index 字段的值。

请求值

按照响应值的思路,之前看网上说只要加 @JsonValue,SpringBoot 在收到请求体的时候也会自动映射枚举值中的字段来进行匹配注入,但是实际传输的index 会以枚举定义的序列来递增查找匹配注入,这就和我们实际需求结果的不符。

例如不加处理,我们请求 status 的值为1,我们得到的枚举为:

SUCCESS(2, " 审核成功 ")

由此可以看出,这显然不符合我们的业务逻辑,所以我们需要自定义 JSON 反序列化来实现匹配注入,首先我们需要定义一个公共的枚举接口(此处继承了 MybatisPlus 的IEnum接口实现数据库枚举注入):

/**  
 * 公共基础枚举  
 * @author Licoy  
 * */
public interface BaseEnum<T extends Serializable> extends IEnum<T> {}

接着我们需要实现 JsonDeserializer 接口,这里我们使用动态的获取上下文需要注入的枚举类型,所以我们还需要实现 ContextualDeserializer 接口:

/**  
 * 请求枚举 JSON 反序列化  
 * @author Licoy  
 * */
@NoArgsConstructor  
@AllArgsConstructor  
public class RequestEnumJsonDeserialize extends JsonDeserializer<BaseEnum<?>> implements ContextualDeserializer {  
 
    private JavaType type;  
 
    @Override  
    public BaseEnum<?> deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException {if (this.type == null || !this.type.isEnumType()) {return null;}  
        ObjectCodec oc = p.getCodec();  
        JsonNode node = oc.readTree(p);  
 
        if (node == null) {return null;}  
        if (!(node instanceof IntNode)) {return null;}  
        Object[] enumConstants = this.type.getRawClass().getEnumConstants();  
        for (Object e : enumConstants) {if (e instanceof BaseEnum) {BaseEnum<?> ie = (BaseEnum<?>) e;  
                if (ie.getValue().equals(node.asInt())) {return ie;}  
            }  
        }  
        return null;  
    }  
 
    @Override  
    public JsonDeserializer<?> createContextual(DeserializationContext ctxt, BeanProperty property) {JavaType type = ctxt.getContextualType() != null  
 ? ctxt.getContextualType()  
                : property.getMember().getType();  
        return new RequestEnumJsonDeserialize(type);  
    }  
}

到这里,我们就可以在实现 BaseEnum 接口的枚举上注入自定义字段值的枚举,不过在此之前我们需要在对应的枚举上加上使用反序列注解:

@JsonDeserialize(using = RequestEnumJsonDeserialize.class)
如果项目中枚举定义有很多,每个枚举类都去添加 @JsonDeserialize 未免有些麻烦,所以我们直接将此写到 BaseEnum 上,只要实现此接口的都可以实现自定义字段的枚举注入:
/**  
 * 公共基础枚举  
 * @author Licoy  
 * */
@JsonDeserialize(using = RequestEnumJsonDeserialize.class)  
public interface BaseEnum<T extends Serializable> extends IEnum<T> {}

声明:本文为原创文章,版权归所有,欢迎分享本文,转载请保留出处!

admin
Admin 关注:0    粉丝:0
这个人很懒,什么都没写

发表评论

扫一扫二维码分享
×