使用 Spring MVC 进行开发的时候,如果想返回 json 格式的数据,只需要添加在 controller 的方法上添加 @ResponseBody 注解,Spring 就会自动将 bean 转成 json。
@Controller
@RequestMapping(value = "/test")
public class TestController {
@ResponseBody
@GetMapping("")
public User test() {
return new User("张三", 20);
}
}
请求http://127.0.0.1:8080/test后的返回结果
{
"name": "张三",
"age": 20
}
那序列化过程是如何实现的呢?通过 DEBUG 代码,发现序列化过程如下:

首先调用 ServletInvocableHandlerMethod 里面的 invokeAndHandle 方法,在 invokeAndHandle 方法中会通过 invokeForRequest 方法获取到需要返回的对象 returnValue,然后再调用 this.returnValueHandlers.handleReturnValue 方法来处理返回值。

上面的 handleReturnValue 方法中会先调用 selectHandler 方法,通过遍历 returnValueHandlers List 来判断返回类型是否是支持的类型,从而找到到合适的 HandlerMethodReturnValueHandler 的实现类,

其中 supportsReturnType 方法会判断当前这个返回类型的 controller 方法是否含有 @ResponseBody 注解。

我这里的例子是调用其实现类之一的 RequestResponseBodyMethodProcessor 类的 handleReturnValue 方法,然后再调用 writeWithMessageConverters

然后,根据返回的MediaType类型,选择合适的 HttpMessageConverter 实现类调用其 write 方法来实现序列化。

write 方法又调用了 writeInternal 方法来获取 objectWriter,通过 objectWriter.writeValue 方法 实现序列化。

protected void writeInternal(Object object, @Nullable Type type, HttpOutputMessage outputMessage) throws IOException, HttpMessageNotWritableException {
MediaType contentType = outputMessage.getHeaders().getContentType();
JsonEncoding encoding = this.getJsonEncoding(contentType);
JsonGenerator generator = this.objectMapper.getFactory().createGenerator(outputMessage.getBody(), encoding);
try {
this.writePrefix(generator, object);
Class<?> serializationView = null;
FilterProvider filters = null;
Object value = object;
JavaType javaType = null;
if (object instanceof MappingJacksonValue) {
MappingJacksonValue container = (MappingJacksonValue)object;
value = container.getValue();
serializationView = container.getSerializationView();
filters = container.getFilters();
}
if (type != null && TypeUtils.isAssignable(type, value.getClass())) {
javaType = this.getJavaType(type, (Class)null);
}
ObjectWriter objectWriter;
if (serializationView != null) {
objectWriter = this.objectMapper.writerWithView(serializationView);
} else if (filters != null) {
objectWriter = this.objectMapper.writer(filters);
} else {
objectWriter = this.objectMapper.writer();
}
if (javaType != null && javaType.isContainerType()) {
objectWriter = objectWriter.forType(javaType);
}
SerializationConfig config = objectWriter.getConfig();
if (contentType != null && contentType.isCompatibleWith(MediaType.TEXT_EVENT_STREAM) && config.isEnabled(SerializationFeature.INDENT_OUTPUT)) {
objectWriter = objectWriter.with(this.ssePrettyPrinter);
}
objectWriter.writeValue(generator, value);
this.writeSuffix(generator, object);
generator.flush();
} catch (InvalidDefinitionException var13) {
throw new HttpMessageConversionException("Type definition error: " + var13.getType(), var13);
} catch (JsonProcessingException var14) {
throw new HttpMessageNotWritableException("Could not write JSON: " + var14.getOriginalMessage(), var14);
}
}