MessageConverterByteArrayHttpMessageConverterAbstractJackson2HttpMessageConverter 의 request response cycle에서의 역할xml MessageConverter추가하기xStream에서 ConversionError 이슈 — No converter available
MessageConverter

- Spring MVC에서는
HttpMessageConverter
interface를 이용하여 Http request 와 response를 변환시켜줌. 예를 들어 java object 가 json(by using the Jackson Library)으로 변환되거나 xml( jackson xml extension)으로 변환되는 부분을 실행해줌
public interface GenericHttpMessageConverter<T> extends HttpMessageConverter<T> { boolean canRead(Type type, @Nullable Class<?> contextClass, @Nullable MediaType mediaType); T read(Type type, @Nullable Class<?> contextClass, HttpInputMessage inputMessage) throws IOException, HttpMessageNotReadableException; boolean canWrite(@Nullable Type type, Class<?> clazz, @Nullable MediaType mediaType); void write(T t, @Nullable Type type, @Nullable MediaType contentType, HttpOutputMessage outputMessage) throws IOException, HttpMessageNotWritableException; }
- 하나의 MessageConverter가 읽는것과 쓰는 것을 다 함. Content negotiation을 해서 header에 전달하는 accept, Content-type을 보고 해당 MessageConverter가 동작할 지 말지를 결정하는 것
ByteArrayHttpMessageConverter
@PostMapping("/upload") public ApiResponse<AssetUploadResponse> uploadFile(@RequestParam String path, @RequestBody byte[] data) { assetService.upload(path, data); return ApiResponse.ok(List.of(new AssetUploadResponse(path))); }
curl http://localhost:8080/assets/upload\?path\=testfolder1/testfolder2/ohho.pdf --request POST --data-binary "@test.pdf" -H "Content-Type:application/octet-stream" -i
- 위와 같은 상황에서
@RequestBody byte[]
의 타입으로 변환할 때, content negotation을 진행하여, 데이터가 바이트 배열이면ByteArrayHttpMessageConverter
가 동작하여 message convert를 진행하게 됨
- Content-Type을 임의로 다른 값을 넣어서 POST 날려봤는데도
ByteArrayHttpMessageConverter
클래스가 동작함
AbstractJackson2HttpMessageConverter 의 request response cycle에서의 역할
@RequestBody에서는 setter가 필요없다? → @RequestBody(
json
→ object
)에서는 내부적으로 objectMapper.readValue를 이용하기 때문에 default 생성자가 필요함. setter는 필요없음@PostMapping("/test") public CreateOrderRequest test(@RequestBody CreateOrderRequest createOrderRequest){ System.out.println(createOrderRequest.getName() + " " + createOrderRequest.getEmail()); return createOrderRequest; }
- request
- DispatcherServlet — doDispatch( )
- AbstractHandlerMethodAdapter — handle( ) . . . . (내부 호출 스택 . . )
- AbstractJackson2HttpMessageConverter — read( ) 메서드 호출
- JSON데이터를 objectMapper를 이용하여 Java Object로 매핑 (deserialize)
- AbstractJackson2HttpMessageConverter — writeInternal( ) 메서드 호출
- objectMapper에서 serialize할 클래스의 getter를 이용함 (serialize)
- response
xml MessageConverter추가하기
- WebMvcConfigurer 클래스를 extend 하며
extendMessageConverters()
함수를 오버라이드 하면 됨
@Override public void extendMessageConverters(List<HttpMessageConverter<?>> converters) { MarshallingHttpMessageConverter messageConverter = new MarshallingHttpMessageConverter(); XStreamMarshaller xStreamMarshaller = new XStreamMarshaller(); messageConverter.setMarshaller(xStreamMarshaller); messageConverter.setUnmarshaller(xStreamMarshaller); converters.add(0, messageConverter); // 이 부분은 json object mapper에서 serializer의 내용을 추가하는 부분임 var javaTimeModule = new JavaTimeModule(); javaTimeModule.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(DateTimeFormatter.ISO_DATE_TIME)); var modules = Jackson2ObjectMapperBuilder.json().modules(javaTimeModule); converters.add(1, new MappingJackson2HttpMessageConverter(modules.build())); }
xStream에서 ConversionError 이슈 — No converter available
- List.of 로 생성한 ImmutableCollections 클래스와 Arrays.asList(..) 으로 생성한 List에 대해 conversion이 지원이 잘 안됨 → Fails on Java 16 for java.util.Arrays$ArrayList and java.util.Collections$EmptyList