消息转换器
在Spring中org.springframework.http.converter.HttpMessageConverter规范中定义了Http请求和响应的消息转换规范, 我们知道SpringMvc可以接收不同的消息形式,也可以将不同的消息形式响应回去(最常见的是json);这些消息所蕴含的"有效信息"是一致的,那么各种不同的消息转换器,都会生成同样的转换结果. 至于各种消息间解析细节的不同,就被屏蔽在不同的HttpMessageConverter实现类中.
SpringMVC中使用FastJson作为转换器
通过SpringMvc中message-converts配置FastJson作为转换器
<!-- 默认的注解映射的支持,org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping -->
<mvc:annotation-driven content-negotiation-manager="contentNegotiationManager">
<mvc:message-converters register-defaults="true">
<!-- 将Jackson2HttpMessageConverter的默认格式化输出为true -->
<!-- 配置Fastjson支持 -->
<bean class="com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter">
<property name="supportedMediaTypes">
<list>
<value>text/html;charset=UTF-8</value>
<value>application/json</value>
</list>
</property>
<property name="features">
<list>
<!-- 输出key时是否使用双引号 -->
<value>QuoteFieldNames</value>
<!-- 是否输出值为null的字段 -->
<!-- <value>WriteMapNullValue</value> -->
<!-- 数值字段如果为null,输出为0,而非null -->
<value>WriteNullNumberAsZero</value>
<!-- List字段如果为null,输出为[],而非null -->
<value>WriteNullListAsEmpty</value>
<!-- 字符类型字段如果为null,输出为"",而非null -->
<value>WriteNullStringAsEmpty</value>
<!-- Boolean字段如果为null,输出为false,而非null -->
<value>WriteNullBooleanAsFalse</value>
<!-- null String不输出 -->
<value>WriteNullStringAsEmpty</value>
<!-- null String也要输出 -->
<!-- <value>WriteMapNullValue</value> -->
<!-- Date的日期转换器 -->
<value>WriteDateUseDateFormat</value>
</list>
</property>
</bean>
</mvc:message-converters>
</mvc:annotation-driven>
<!-- REST中根据URL后缀自动判定Content-Type及相应的View -->
<bean id="contentNegotiationManager" class="org.springframework.web.accept.ContentNegotiationManagerFactoryBean">
<property name="mediaTypes" >
<map>
<entry key="json" value="application/json"/>
</map>
</property>
<!-- 这里是否忽略掉accept header,默认就是false -->
<property name="ignoreAcceptHeader" value="true"/>
<property name="favorPathExtension" value="true"/>
</bean>
Fastjson轻量级属性转换
定义示例对象模型
做fastjson轻量注解配置, 更多配置参考https://github.com/alibaba/fastjson/wiki/JSONField
public class ModelTest implements Serializable{
// 使用ordinal指定字段
@JSONField(ordinal = 1)
private Long id;
@JSONField(ordinal = 2)
private String name;
@JSONField(ordinal = 3)
private Integer age;
// 使用serialize/deserialize指定字段不序列化
@JSONField(deserialize = false, serialize = false)
private String remark;
// 配置date序列化和反序列使用yyyyMMdd日期格式
@JSONField(format="yyyy-MM-dd HH:mm:ss")
private Date crateTime;
// 配置属性序列化使用的名称
@JSONField(name = "updateTime", format="yyyy-MM-dd HH:mm:ss")
private Date modifyTime;
@JSONField(ordinal = 0)
private DeleteEnum deleteEnum;
public enum DeleteEnum {
DISABLE(1, "禁用"),
ENABLE(2, "启用");
private int value;
private String depict;
DeleteEnum(int value, String depict) {
this.value = value;
this.depict = depict;
}
public static DeleteEnum findByValue(int value) {
switch (value) {
case 1:
return DISABLE;
case 2:
return ENABLE;
default:
return null;
}
}
}
// getter and setter
}
定义示例Controller
示例完成序列化数据到前端和提交JSON数据转换成对象模型
@Controller
@RequestMapping(value = "/test")
public class TestWebController {
private static final Logger LOG = LoggerFactory.getLogger(TestWebController.class);
// 序列化对象到视图
@ResponseBody
@RequestMapping(value = {"/bean/data"}, method = {RequestMethod.GET, RequestMethod.POST})
public Object toBody(){
ModelTest modelTest = new ModelTest();
modelTest.setAge(11);
modelTest.setCrateTime(new Date());
modelTest.setModifyTime(new Date());
modelTest.setId(1L);
modelTest.setName("测试Fastjson");
modelTest.setRemark("备注");
modelTest.setDeleteEnum(ModelTest.DeleteEnum.ENABLE);
return ImmutableMap.<String, String>builder()
.put("code", "0")
.put("data", JSON.toJSONString(modelTest)).build();
}
// 解析JSON对象到实体模型
@ResponseBody
@RequestMapping(value = {"/bean/put"}, method = {RequestMethod.GET, RequestMethod.POST})
public Object getBody(@RequestBody ModelTest modelTest){
System.out.println(JSON.toJSONString(modelTest));
return ImmutableMap.<String, String>builder()
.put("code", "0")
.put("data", "ok").build();
}
}
测试对象序列化到前端展示
@Test
public void fastJSONTest01() throws Exception {
MvcResult mvcResult = this.mockMvc.perform(MockMvcRequestBuilders.post("/test/bean/data")
.cookie(new Cookie("token", "F3AF5F1D14F534F677XF3A00E352C")) // 登录授权
.accept(MediaType.parseMediaType("application/json;charset=UTF-8")))
.andExpect(handler().handlerType(TestWebController.class)) // 验证执行的控制器类型
.andExpect(status().isOk()) // 验证执行状态
.andDo(print()) // 打印交互信息
.andReturn();
System.out.println(mvcResult.getResponse().getContentAsString());
}
执行结果:
{
"code": "0",
"data": "{"crateTime":"2016-12-2808: 02: 50","deleteEnum":"ENABLE","updateTime":"2016-12-2808: 02: 50","id":1,"name":"测试Fastjson","age":11}"
}
测试提交数据转换成模型
@Test
public void fastJSONTest02() throws Exception {
ModelTest modelTest = new ModelTest();
modelTest.setAge(11);
modelTest.setCrateTime(new Date());
modelTest.setModifyTime(new Date());
modelTest.setId(1L);
modelTest.setName("测试Fastjson");
modelTest.setRemark("备注");
modelTest.setDeleteEnum(ModelTest.DeleteEnum.ENABLE);
MvcResult mvcResult = this.mockMvc.perform(MockMvcRequestBuilders.post("/test/bean/put")
.content(JSON.toJSONString(modelTest))
.contentType(MediaType.APPLICATION_JSON)
.cookie(new Cookie("token", "F3AF5F1D14F534F677XF3A00E352C")) // 登录授权
.accept(MediaType.parseMediaType("application/json;charset=UTF-8")))
.andExpect(handler().handlerType(TestWebController.class)) // 验证执行的控制器类型
.andExpect(status().isOk()) // 验证执行状态
.andDo(print()) // 打印交互信息
.andReturn();
System.out.println(mvcResult.getResponse().getContentAsString());
}
执行后台打印:
{"crateTime":"2016-12-28 08:04:33","deleteEnum":"ENABLE","updateTime":"2016-12-28 08:04:33","id":1,"name":"测试Fastjson","age":11}
枚举绑定处理
示例中我们看到序列化的枚举为枚举的name(). 如果我们想用枚举的寓意值进行传输过程中的映射时,可以这样做, 透传一个数值, 该数值和枚举在getter()和setter()方法上绑定即可.
修改示例的对象模型
public class ModelTest implements Serializable{
// 使用ordinal指定字段
@JSONField(ordinal = 1)
private Long id;
@JSONField(ordinal = 2)
private String name;
@JSONField(ordinal = 3)
private Integer age;
// 使用serialize/deserialize指定字段不序列化
@JSONField(deserialize = false, serialize = false)
private String remark;
// 配置date序列化和反序列使用yyyyMMdd日期格式
@JSONField(format="yyyy-MM-dd HH:mm:ss")
private Date crateTime;
// 配置属性序列化使用的名称
@JSONField(name = "updateTime", format="yyyy-MM-dd HH:mm:ss")
private Date modifyTime;
@JSONField(ordinal = 0)
private DeleteEnum deleteEnum;
private int enable;
public enum DeleteEnum {
DISABLE(1, "禁用"),
ENABLE(2, "启用");
private int value;
private String depict;
DeleteEnum(int value, String depict) {
this.value = value;
this.depict = depict;
}
public static DeleteEnum findByValue(int value) {
switch (value) {
case 1:
return DISABLE;
case 2:
return ENABLE;
default:
return null;
}
}
}
// 数值绑定枚举
public int getEnable() {
this.deleteEnum = DeleteEnum.findByValue(enable);
return enable;
}
// 数值绑定枚举
public void setEnable(int enable) {
this.enable = enable;
this.deleteEnum = DeleteEnum.findByValue(enable);
}
// 枚举映射数值
public DeleteEnum getDeleteEnum() {
this.enable = this.deleteEnum.value;
return deleteEnum;
}
// 枚举映射数值
public void setDeleteEnum(DeleteEnum deleteEnum) {
this.deleteEnum = deleteEnum;
this.enable = this.deleteEnum.value;
}
}
我们保持示例中Controller类和测试用例的代码不变,执行用例.
-
测试对象序列化到前端展示
执行结果
{
"code": "0",
"data": "{"crateTime":"2016-12-2808: 12: 52","deleteEnum":"ENABLE","enable":2,"updateTime":"2016-12-2808: 12: 52","id":1,"name":"测试Fastjson","age":11}"
}
-
测试提交数据转换成模型
执行后台打印
{"crateTime":"2016-12-28 08:20:17","deleteEnum":"ENABLE","enable":2,"updateTime":"2016-12-28 08:20:17","id":1,"name":"测试Fastjson","age":11}
修改用例模拟的实体对象, 测试数值到枚举的映射.
ModelTest modelTest = new ModelTest();
modelTest.setAge(11);
modelTest.setCrateTime(new Date());
modelTest.setModifyTime(new Date());
modelTest.setId(1L);
modelTest.setName("测试Fastjson");
modelTest.setRemark("备注");
modelTest.setEnable(1);
后台打印输出:
{"crateTime":"2016-12-28 08:21:48","deleteEnum":"DISABLE","enable":1,"updateTime":"2016-12-28 08:21:48","id":1,"name":"测试Fastjson","age":11}
可以看到enable的值自动和枚举类型映射上.
使用FastJson做对象和JSON之间的转换
对象转换成JSON
@Test
public void fastJSONTest03() {
ModelTest modelTest = new ModelTest();
modelTest.setAge(11);
modelTest.setCrateTime(new Date());
modelTest.setModifyTime(new Date());
modelTest.setId(1L);
modelTest.setName("测试Fastjson");
modelTest.setRemark("备注");
modelTest.setEnable(1);
System.out.println(JSON.toJSONString(modelTest));
}
执行结果:
{"crateTime":"2016-12-28 08:30:42","deleteEnum":"DISABLE","enable":1,"updateTime":"2016-12-28 08:30:42","id":1,"name":"测试Fastjson","age":11}
JSON转换成对象
@Test
public void fastJSONTest04() {
String json = "{\n" +
" \"id\": 1,\n" +
" \"deleteEnum\": \"DISABLE\",\n" +
" \"updateTime\": 1482884802549,\n" +
" \"crateTime\": 1482884802549,\n" +
" \"age\": 11,\n" +
" \"name\": \"测试Fastjson\",\n" +
" \"enable\": 1\n" +
"}";
ModelTest modelTest = JSONObject.parseObject(json, ModelTest.class);
System.out.println(modelTest);
System.out.println(modelTest.getName());
}
执行结果:
ModelTest{id=1, name='测试Fastjson', age=11, remark='null', crateTime=Wed Dec 28 08:26:42 CST 2016, modifyTime=Wed Dec 28 08:26:42 CST 2016, deleteEnum=DISABLE, enable=1}
测试Fastjson
示例中直接打印输出对象,是因为复写了toString()方法.
网友评论