在使用mybaits-plus中(官网链接:链接)的时候,有个枚举类的功能的十分常见,因为在实际开发中,少不了约定一些状态码以及特殊含义的数字等,这就与枚举类中的意义相同,fastjson+mybatis-plus可以让实际开发中
一、 定义枚举类
IEnum
接口@EnumValue
标记在数据库存的字段上,下述例子数据存的就是 code字段,即 0,1toString
方法,返回相应的描述,这个在序列化时会替换成这个描述package com.example.demo.user.enumClass;
import com.baomidou.mybatisplus.annotation.EnumValue;
import com.baomidou.mybatisplus.core.enums.IEnum;
/**
* Create by Lingo
*/
//@JSONType(serializeEnumAsJavaBean = true)
public enum GenderEnum implements IEnum {
MALE(1,"男"),
FEMALE(0,"女");
@EnumValue
private final int code;
private final String descp;
GenderEnum(int code, String descp) {
this.code = code;
this.descp = descp;
}
@Override
public String toString() {
return this.descp;
}
@Override
public Integer getValue() {
return code;
}
}
二、 定义实体类
Serializable
接口,以便可以序列化tinyint(1)
,而定义的时候类型是GenderEnum
@JSONField(serialzeFeatures= SerializerFeature.WriteEnumUsingToString)
注解,以便进行局部设置package com.example.demo.user.entity;
import com.alibaba.fastjson.annotation.JSONField;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.example.demo.user.enumClass.GenderEnum;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import java.io.Serializable;
/**
* @author Lingo
* @since 2019-08-06
*/
@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
@ApiModel(value="User对象", description="")
public class User implements Serializable {
private static final long serialVersionUID = 1L;
private String name;
private Integer age;
private String email;
@JSONField(serialzeFeatures= SerializerFeature.WriteEnumUsingToString)
private GenderEnum gender;
// setter/getter方法已经由lombok 在编译时自动生成
}
实体类\Controller\Service都可以使用
Mybatis-plus
的CodeGenerator
来自动生成,此处不再演示,具体请看Mybatis-plus
的官网
三、配置 Mybatis-plus
# application.yml
# 指定扫描枚举类所在包
mybatis-plus:
type-enums-package: com.example.demo.user.enumClass
四 、测试类
Json.toJsonString
的方法才能获取描述(调用枚举类的toString
方法)。当使用Json.toJson()
的时候,则不会替换成描述。原因请看后面package com.example.demo;
import com.alibaba.fastjson.JSON;
import com.example.demo.user.entity.User;
import com.example.demo.user.service.IUserService;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import java.util.List;
@RunWith(SpringRunner.class)
@SpringBootTest
public class DemoApplicationTests {
@Autowired
IUserService userService;
@Test
public void selectList1(){
System.out.println("----------test1--------------");
List userList = userService.lambdaQuery().list();
for (User user : userList) {
System.out.println(JSON.toJSONString(user));
}
}
@Test
public void selectList2(){
System.out.println("----------test2--------------");
List userList = userService.lambdaQuery().list();
for (User user : userList) {
System.out.println(JSON.toJSON(user));
}
}
@Test
public void selectList3() {
System.out.println("----------test3--------------");
List userList = userService.lambdaQuery().list();
for (User user : userList) {
System.out.println(user);
}
}
@Test
public void selectList4() {
System.out.println("----------test4--------------");
List userList = userService.lambdaQuery().list();
userList.forEach(System.out::println);
}
}
结果
----------test1--------------
{"age":24,"email":"[email protected]","gender":"女","name":"Jone"}
{"age":24,"email":"[email protected]","gender":"女","name":"Jack"}
{"age":24,"email":"[email protected]","gender":"男","name":"Tom"}
{"age":24,"email":"[email protected]","gender":"男","name":"Sandy"}
{"age":24,"email":"[email protected]","gender":"女","name":"Billie"}
----------test2--------------
{"gender":"FEMALE","name":"Jone","age":24,"email":"[email protected]"}
{"gender":"FEMALE","name":"Jack","age":24,"email":"[email protected]"}
{"gender":"MALE","name":"Tom","age":24,"email":"[email protected]"}
{"gender":"MALE","name":"Sandy","age":24,"email":"[email protected]"}
{"gender":"FEMALE","name":"Billie","age":24,"email":"[email protected]"}
----------test3--------------
User(name=Jone, age=24, [email protected], gender=女)
User(name=Jack, age=24, [email protected], gender=女)
User(name=Tom, age=24, [email protected], gender=男)
User(name=Sandy, age=24, [email protected], gender=男)
User(name=Billie, age=24, [email protected], gender=女)
----------test4--------------
User(name=Jone, age=24, [email protected], gender=女)
User(name=Jack, age=24, [email protected], gender=女)
User(name=Tom, age=24, [email protected], gender=男)
User(name=Sandy, age=24, [email protected], gender=男)
User(name=Billie, age=24, [email protected], gender=女)
五、 Controller
中返回Json
package com.example.demo.user.controller;
import com.alibaba.fastjson.JSON;
import com.example.demo.user.service.IUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @author Lingo
* @since 2019-08-06
*/
@RestController
@RequestMapping("/user")
public class UserController {
@Autowired
IUserService userService;
@RequestMapping("/list")
public Object list(){
// 至于为什么要先变成JSONString 再组装成 JSON,请看后文
return JSON.toJSON(JSON.toJSONString(userService.lambdaQuery().list()));
}
}
toJsonString
再组装成Json
对象JSON.toJSONString()
在研究toJsonString()
方法的时候,发现fastjson
自己也有一个ObjectSerializer
的对象池,当你在实体类中标记了@JSONField
注解的时候,它就会根据 实体类的类型返回相对应的ObjectSerializer
(序列化器),先看以下代码:
public final void write(Object object) {
if (object == null) {
this.out.writeNull();
} else {
Class> clazz = object.getClass();
ObjectSerializer writer = this.getObjectWriter(clazz); // 1 号代码
try {
writer.write(this, object, (Object)null, (Type)null, 0); // 2号代码
} catch (IOException var5) {
throw new JSONException(var5.getMessage(), var5);
}
}
}
@JSONField
注解时,1 号代码中将会返回 JavaBeanSerializer
,此时2号代码将会调用 javaBeanSerializer
的write 方法,期间,FieldSerializer
会判断这个Field
是不是Enum
,如果是,则取 toString
的值。关键代码如下:if (this.fieldInfo.isEnum) { //here
if (this.writeEnumUsingName) {
serializer.out.writeString(((Enum)propertyValue).name());
return;
}
if (this.writeEnumUsingToString) {
serializer.out.writeString(((Enum)propertyValue).toString());
return;
}
}
@JSONField
注解时,1 号代码中将会返回 ASMSerializer_x_xxx
如(ASMSerializer_1_User
),估计是在项目初始化的期间通过反射产生的,断点调试时此时2号代码会调用Serializable.writeDirect()
方法,由于在代码上这个方法是返回 boolean类型的,且名称也不对,并没有对输出做什么操作,猜测是使用了Aop技术(具体是什么没有做深入研究)。这里会直接将所有的Field
值转成json格式,而fastjson是默认使用Name
属性的,如本例的(MALE/FEMALE
)JSON.toJSON()
if (clazz.isEnum()) {
return ((Enum)javaObject).name();
}
正是这行代码决定了 JSON.toJSON()
返回的是枚举类的Name 属性。