当一个HTTP请求到达时是一个InputStream,通过HttpMessageConverter转换为java对象,从而进行参数接收。 当对一个HTTP请求进行响应时,我们首先输出的是一个java对象,然后由HttpMessageConverter转换为OutputStream输出。
当我们在Spring Boot应用中集成了jackson的类库之后,如下的一些HttpMessageConverter将会被加载:
实现类功能说明StringHttpMessageConverter将请求信息转为字符串FormHttpMessageConverter将表单数据读取到MultiValueMap中XmlAwareFormHttpMessageConverter扩展与FormHttpMessageConverter,如果部分表单属性是XML数据,可用该转换器进行读取ResourceHttpMessageConverter读写org.springframework.core.io.Resource对象BufferedImageHttpMessageConverter读写BufferedImage对象ByteArrayHttpMessageConverter读写二进制数据SourceHttpMessageConverter读写java.xml.transform.Source类型的对象MarshallingHttpMessageConverter通过Spring的org.springframework,xml.Marshaller和Unmarshaller读写XML消息Jaxb2RootElementHttpMessageConverter通过JAXB2读写XML消息,将请求消息转换为标注的XmlRootElement和XmlType连接的类中MappingJacksonHttpMessageConverter利用Jackson开源包的ObjectMapper读写JSON数据RssChannelHttpMessageConverter读写RSS种子消息AtomFeedHttpMessageConverter和RssChannelHttpMessageConverter能够读写RSS种子消息根据HTTP协议的Accept和Content-Type属性,以及参数数据类型来判别使用哪一种HttpMessageConverter。当使用RequestBody或ResponseBody时,再结合前端发送的Accept数据类型,会自动判定优先使用MappingJacksonHttpMessageConverter作为数据转换器。
不仅JSON可以表达对象数据类型,XML也可以。如果我们希望使用XML格式该怎么告知Spring呢,那就要使用到produces属性了。
@GetMapping(value ="/demo",produces = MediaType.APPLICATION_XML_VALUE)
这里我们明确的告知了返回的数据类型是xml,就会使用Jaxb2RootElementHttpMessageConverter作为默认的数据转换器。当然实现XML数据响应比JSON还会更复杂一些,还需要结合@XmlRootElement、@XmlElement等注解实体类来使用。
自定义HttpMessageConverter其实绝大多数的数据格式都不需要我们自定义HttpMessageConverter,都有第三方类库可以帮助我们实现(包括下文代码中的Excel格式)。但有的时候,有些数据的输出格式并没有类似于Jackson这种类库帮助我们处理,需要我们自定义数据格式。
步骤:
- 实现AbstractHttpMessageConverter接口
- 指定该转换器是针对哪种数据格式的?如上文代码中的"application/vnd.ms-excel"
- 指定该转换器针对那些对象数据类型?如上文代码中的supports函数
- 使用writeInternal对数据进行输出处理,上例中是输出为Excel格式。
@Service
public class TeamToXlsConverter extends AbstractHttpMessageConverter {
private static final MediaType EXCEL_TYPE = MediaType.valueOf("application/vnd.ms-excel");
TeamToXlsConverter() {
super(EXCEL_TYPE);
}
@Override
protected Team readInternal(final Class clazz, final HttpInputMessage inputMessage) throws IOException, HttpMessageNotReadableException {
return null;
}
@Override
protected boolean supports(final Class clazz) {
return (Team.class == clazz);
}
@Override
protected void writeInternal(final Team team, final HttpOutputMessage outputMessage) throws IOException, HttpMessageNotWritableException {
try (final Workbook workbook = new HSSFWorkbook()) {
final Sheet sheet = workbook.createSheet();
int rowNo = 0;
for (final TeamMember member : team.getMembers()) {
final Row row = sheet.createRow(rowNo++);
row.createCell(0)
.setCellValue(member.getName());
}
workbook.write(outputMessage.getBody());
}
}
}
上面代码只是帮助我们理解的一个例子,不要用于生产。