– Introduction: This article tries to customize message converter in a fast and clear way, with you to understand how to convert messages to the required format in SpringBoot


1. Application scenarios

At present, the mainstream scenario is that the front end calls the HTTP interface exposed by the back end for access, and most of the parameters are passed in JSON format. The back end does not go through the attempt parser, but directly returns the response to the front end.

@requestbody is used to extract the parameters in the RequestBody as required and wrap them into the required format. ResponseBody, mainly extracts the parameters in the ResponseBody as required and returns them to the front end after packaging. HttpMessageConverter = HttpMessageConverter = HttpMessageConverter = HttpMessageConverter

With the format of the application/json request, for instance with application/json format returned, will use MappingJacksonHttpMessageConverter by default

So what if you want to return in XMl format, or even define your own format to receive and return?

We just need to define a new HttpMessageConverter. Several points need to be declared:

1. What type of data (Class) will be converted

2. What types of content-type are supported

3. Read the request code

4. Write the code for response

The code:

@ Service / / 1. Implementation AbstractHttpMessageConverter public class ResponseToXlsConverter extends AbstractHttpMessageConverter<AjaxResponse> { private static final MediaType EXCEL_TYPE = MediaType.valueOf("application/vnd.ms-excel"); public ResponseToXlsConverter() { //2. Statements in support of the content-type Type super (EXCEL_TYPE, MediaType. APPLICATION_JSON); } @override protected Boolean supports(Class<? > clazz) { return (AjaxResponse.class == clazz); } @requestBody can encapsulate the contents of the request body. Override protected AjaxResponse readInternal(Class<? extends AjaxResponse> clazz, HttpInputMessage inputMessage) throws IOException, HttpMessageNotReadableException {System. Out. Println (" readInternal effect "); if (clazz == AjaxResponse.class) { String s = StreamUtils.copyToString(inputMessage.getBody(), StandardCharsets.UTF_8); return AjaxResponse.success(s, "heihei"); } return null; } // select * from ResponseBody; @override protected void writeInternal(AjaxResponse AjaxResponse, HttpOutputMessage outputMessage) throws IOException, HttpMessageNotWritableException {System. Out. Println (" writeInternal effect "); final Workbook workbook = new HSSFWorkbook(); final Sheet sheet = workbook.createSheet(); final Row row = sheet.createRow(0); row.createCell(0).setCellValue(ajaxResponse.getMessage()); row.createCell(1).setCellValue(ajaxResponse.getData().toString()); workbook.write(outputMessage.getBody()); }}Copy the code

Add this converter to Converters,

public class MyWebMvcConfigurer implements WebMvcConfigurer { @Autowired CustomHandlerInterceptor customHandlerInterceptor; @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(customHandlerInterceptor).addPathPatterns("/*"); } @Override public void extendMessageConverters(List<HttpMessageConverter<? >> converters) {// Add the first ResponseToXlsConverter(0, new ResponseToXlsConverter()); }}Copy the code

Take a look at my Controller: I’m trying to parse json parameters into an AjaxResponse, which I can also parse if it’s Application/Vnd.ms-Excel because my Converter supports two types of formats.

@GetMapping(value = "/article/{id}")
public AjaxResponse article(@PathVariable Long id, @RequestBody AjaxResponse se) {
    log.info("-->{}", se);
    return AjaxResponse.success("hehe,nimade");
}
Copy the code

Debug Check the cause

1. Go to the custom Converter and compare the Supports method and canRead method

Support must be true, let’s look at canRead, mediaType is the content-Type in the front end request header, and our supportsMediaTypes supports two, including JSON, which will succeed.

3. Check the contents of the request body, which immediately enters our own readInternal method. Request methods without the request body, such as form-data, cannot be parsed. Our readInternal returns an AjaxResponse to the Controller.

4, actually request parsing MappingJacksonHttpMessageConverter also can do it, but we will own the first statement in a List, so in their own first.

4. The response process is exactly the same

change

1. If there are multiple hits, the first one will be used first, so our Add (0, Converter) will put its own first.

The content-type of the request is produced by the request header, but when responding, you can specify the type you want to return by using @requestMapping produces in controller, which affects the mediaType in debug. So for example, if you want to return String, you can specify that, instead of using your own converter.