前言
在现代的 Web 开发中,数据交换格式的多样性要求我们能够灵活地处理各种格式的数据。除了常见的 JSON 和 XML,YAML 作为一种简洁且易于阅读的标记语言,也越来越受到开发者的关注。本文将通过一个完整的示例,展示如何在 Spring MVC 中使用 SnakeYAML 库实现 YAML 数据与 Java 对象之间的转换。
-
项目背景
在之前的教程中,我们已经学习了如何创建自定义的 HTTPMessageConverter。这一次,我们将进一步扩展,实现一个能够处理 YAML 格式数据的 HTTPMessageConverter。通过这个转换器,我们可以轻松地将 YAML 格式的请求体转换为 Java 对象,同时也能将 Java 对象转换为 YAML 格式的响应体。 -
创建控制器
首先,我们需要创建一个控制器来处理与 YAML 数据相关的请求。以下是一个简单的控制器示例:
java复制
@Controller
public class ExampleController {
@RequestMapping(
value = “/newEmployee”,
consumes = “text/yaml”,
produces = MediaType.TEXT_PLAIN_VALUE,
method = RequestMethod.POST)
@ResponseBody
@ResponseStatus(HttpStatus.OK)
public String handleRequest(@RequestBody Employee employee) {
System.out.printf(“In handleRequest method, employee: %s%n”, employee);
String s = String.format("Employee saved: " + employee.getName());
System.out.println(s);
return s;
}@RequestMapping(
value = “/employee”,
produces = “text/yaml”,
method = RequestMethod.GET)
@ResponseBody
@ResponseStatus(HttpStatus.OK)
public Employee handleRequest2(@RequestParam String id) {
// 创建一个测试员工对象
return new Employee(id, “Tina”, “111-111-1111”);
}
}
在上述代码中,handleRequest 方法用于处理 POST 请求,接收 YAML 格式的请求体并将其转换为 Employee 对象。handleRequest2 方法则用于处理 GET 请求,返回一个 Employee 对象,并将其转换为 YAML 格式的响应体。 -
创建 YAML 转换器
接下来,我们需要创建一个自定义的 HTTPMessageConverter,用于处理 YAML 数据的读取和写入。以下是转换器的实现代码:
java复制
public class YamlHttpMessageConverter extends AbstractHttpMessageConverter {
public YamlHttpMessageConverter() {
super(new MediaType(“text”, “yaml”));
}@Override
protected boolean supports(Class<?> clazz) {
return true;
}@Override
protected T readInternal(Class<? extends T> clazz, HttpInputMessage inputMessage)
throws IOException, HttpMessageNotReadableException {
Yaml yaml = new Yaml();
T t = yaml.loadAs(inputMessage.getBody(), clazz);
return t;
}@Override
protected void writeInternal(T t, HttpOutputMessage outputMessage)
throws IOException, HttpMessageNotWritableException {
Yaml yaml = new Yaml();
OutputStreamWriter writer = new OutputStreamWriter(outputMessage.getBody());
yaml.dump(t, writer);
writer.close();
}
}
在 readInternal 方法中,我们使用 SnakeYAML 的 loadAs 方法将 YAML 数据流转换为指定类型的 Java 对象。在 writeInternal 方法中,我们使用 dump 方法将 Java 对象转换为 YAML 格式的数据流。 -
注册转换器
为了让 Spring MVC 使用我们自定义的 YamlHttpMessageConverter,我们需要在配置类中将其注册到消息转换器列表中。以下是配置类的代码:
java复制
@EnableWebMvc
@ComponentScan(“com.logicbig.example”)
public class AppConfig extends WebMvcConfigurerAdapter {
@Override
public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
converters.add(new YamlHttpMessageConverter<>());
}
}
通过 extendMessageConverters 方法,我们将 YamlHttpMessageConverter 添加到 Spring MVC 的消息转换器列表中,使其能够被 Spring MVC 框架自动使用。 -
测试
为了验证我们的实现是否正确,我们可以编写一些 JUnit 测试用例。以下是测试请求和响应的代码示例:
测试请求
java复制
@RunWith(SpringJUnit4ClassRunner.class)
@WebAppConfiguration
@ContextConfiguration(classes = AppConfig.class)
public class ControllerTest {
@Autowired
private WebApplicationContext wac;
private MockMvc mockMvc;@Before
public void setup() {
DefaultMockMvcBuilder builder = MockMvcBuilders.webAppContextSetup(this.wac);
this.mockMvc = builder.build();
}@Test
public void testConsumerController() throws Exception {
MockHttpServletRequestBuilder builder =
MockMvcRequestBuilders.post(“/newEmployee”)
.contentType(“text/yaml”)
.accept(MediaType.TEXT_PLAIN_VALUE)
.content(getNewEmployeeInYaml());
this.mockMvc.perform(builder)
.andExpect(MockMvcResultMatchers.status().isOk())
.andExpect(MockMvcResultMatchers.content().string(“Employee saved: Tina”))
.andDo(MockMvcResultHandlers.print());
}public String getNewEmployeeInYaml() {
return “id: 1\nname: Tina\nphoneNumber: 111-111-1111\n”;
}
}
在上述测试代码中,我们模拟了一个 POST 请求,发送 YAML 格式的请求体,并验证响应状态码和响应内容是否符合预期。
测试响应
java复制
@Test
public void testProducerController() throws Exception {
MockHttpServletRequestBuilder builder =
MockMvcRequestBuilders.get(“/employee”)
.accept(“text/yaml”)
.param(“id”, “1”);
this.mockMvc.perform(builder)
.andExpect(MockMvcResultMatchers.status().isOk())
.andDo(MockMvcResultHandlers.print());
}
在测试响应的代码中,我们模拟了一个 GET 请求,接受 YAML 格式的响应体,并验证响应状态码是否为 200。 -
输出结果
以下是测试运行后的输出结果:
测试请求输出
复制
In handleRequest method, employee: Employee{id=‘1’, name=‘Tina’, phoneNumber=‘111-111-1111’}
Employee saved: Tina
MockHttpServletRequest:
HTTP Method = POST
Request URI = /newEmployee
Parameters = {}
Headers = {Content-Type=[text/yaml], Accept=[text/plain]}
Handler:
Type = com.logicbig.example.ExampleController
Method = public java.lang.String com.logicbig.example.ExampleController.handleRequest(com.logicbig.example.Employee)
Async:
Async started = false
Async result = null
Resolved Exception:
Type = null
ModelAndView:
View name = null
View = null
Model = null
FlashMap:
Attributes = null
MockHttpServletResponse:
Status = 200
Error message = null
Headers = {Content-Type=[text/plain;charset=ISO-8859-1], Content-Length=[20]}
Content type = text/plain;charset=ISO-8859-1
Body = Employee saved: Tina
Forwarded URL = null
Redirected URL = null
Cookies = []
测试响应输出
复制
MockHttpServletRequest:
HTTP Method = GET
Request URI = /employee
Parameters = {id=[1]}
Headers = {Accept=[text/yaml]}
Handler:
Type = com.logicbig.example.ExampleController
Method = public com.logicbig.example.Employee com.logicbig.example.ExampleController.handleRequest2(java.lang.String)
Async:
Async started = false
Async result = null
Resolved Exception:
Type = null
ModelAndView:
View name = null
View = null
Model = null
FlashMap:
Attributes = null
MockHttpServletResponse:
Status = 200
Error message = null
Headers = {Content-Type=[text/yaml]}
Content type = text/yaml
Body = !!com.logicbig.example.Employee {id: ‘1’, name: Tina, phoneNumber: 111-111-1111}
Forwarded URL = null
Redirected URL = null
Cookies = []
从输出结果可以看出,我们的 YAML 数据与 Java 对象之间的转换功能已经正常工作。 -
总结
通过本文的介绍,我们学习了如何在 Spring MVC 中使用 SnakeYAML 库实现 YAML 数据与 Java 对象之间的转换。通过自定义的 YamlHttpMessageConverter,我们可以轻松地处理 YAML 格式的请求和响应。同时,通过编写 JUnit 测试用例,我们验证了实现的正确性。希望本文能够帮助你在项目中更好地处理 YAML 数据。 -
示例项目依赖
以下是本项目所使用的依赖和相关技术:
spring-webmvc 4.3.8.RELEASE: Spring Web MVC。
spring-test 4.3.8.RELEASE: Spring TestContext Framework。
javax.servlet-api 3.0.1: Java Servlet API。
junit 4.12: JUnit 是一个用于 Java 的单元测试框架。
snakeyaml