当一个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<Team> { private static final MediaType EXCEL_TYPE = MediaType.valueOf("application/vnd.ms-excel"); TeamToXlsConverter() { super(EXCEL_TYPE); } @Override protected Team readInternal(final Class<? extends Team> 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()); } } }
上面代码只是帮助我们理解的一个例子,不要用于生产。