全部学科
NodeJS全栈
nodejs
Python全栈
python
小程序首页
📅 2026-05-18 10 分钟 ✍️ juanwangdev

响应数据转换与渲染

SpringMVC支持多种响应方式,包括JSON/XML数据响应和视图渲染,通过HandlerMethodReturnValueHandler统一处理。

返回值处理器架构

核心接口

Java
public interface HandlerMethodReturnValueHandler {
    boolean supportsReturnType(MethodParameter returnType);

    void handleReturnValue(Object returnValue, MethodParameter returnType,
            ModelAndViewContainer mavContainer, NativeWebRequest webRequest);
}

返回值处理器链

Java
// RequestMappingHandlerAdapter初始化返回值处理器
private List<HandlerMethodReturnValueHandler> getDefaultReturnValueHandlers() {
    List<HandlerMethodReturnValueHandler> handlers = new ArrayList<>();

    // ModelAndView相关
    handlers.add(new ModelAndViewMethodReturnValueHandler());
    handlers.add(new ViewMethodReturnValueHandler());

    // 响应体相关
    handlers.add(new ResponseBodyMethodReturnValueHandler());

    // 视图名称
    handlers.add(new ViewNameMethodReturnValueHandler());

    // 其他类型
    handlers.add(new HttpEntityMethodProcessor());
    handlers.add(new RequestResponseBodyMethodProcessor());

    return handlers;
}

HttpMessageConverter机制

核心接口

Java
public interface HttpMessageConverter<T> {
    boolean canRead(Class<?> clazz, @Nullable MediaType mediaType);
    boolean canWrite(Class<?> clazz, @Nullable MediaType mediaType);
    List<MediaType> getSupportedMediaTypes();
    T read(Class<? extends T> clazz, HttpInputMessage inputMessage);
    void write(T t, @Nullable MediaType contentType, HttpOutputMessage outputMessage);
}

内置转换器

转换器支持类型MediaType
StringHttpMessageConverterStringtext/plain
MappingJackson2HttpMessageConverterObjectapplication/json
ByteArrayHttpMessageConverterbyte[]application/octet-stream
FormHttpMessageConverterMultiValueMapapplication/x-www-form-urlencoded

@ResponseBody处理流程

RequestResponseBodyMethodProcessor

Java
public class RequestResponseBodyMethodProcessor
        extends AbstractMessageConverterMethodProcessor {

    public void handleReturnValue(Object returnValue, MethodParameter returnType,
            ModelAndViewContainer mavContainer, NativeWebRequest webRequest) {

        mavContainer.setRequestHandled(true);

        // 使用MessageConverter写入响应
        writeWithMessageConverters(returnValue, returnType, inputMessage, outputMessage);
    }

    protected <T> void writeWithMessageConverters(T value, MethodParameter returnType,
            ServletServerHttpRequest inputMessage, ServletServerHttpResponse outputMessage) {

        // 获取内容类型
        MediaType contentType = outputMessage.getHeaders().getContentType();

        // 遍历MessageConverter找到支持的转换器
        for (HttpMessageConverter<?> converter : this.messageConverters) {
            if (converter.canWrite(valueClass, contentType)) {
                ((HttpMessageConverter<Object>) converter)
                    .write(value, contentType, outputMessage);
                return;
            }
        }
    }
}

JSON序列化配置

Java
@Configuration
public class WebConfig implements WebMvcConfigurer {
    @Override
    public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
        MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
        ObjectMapper objectMapper = new ObjectMapper();

        // 日期格式化
        objectMapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));

        // 忽略空值
        objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);

        // 驼峰转下划线
        objectMapper.setPropertyNamingStrategy(PropertyNamingStrategies.SNAKE_CASE);

        converter.setObjectMapper(objectMapper);
        converters.add(converter);
    }
}

ResponseEntity处理

HttpEntityMethodProcessor

Java
public class HttpEntityMethodProcessor
        extends AbstractMessageConverterMethodProcessor {

    public void handleReturnValue(Object returnValue, MethodParameter returnType,
            ModelAndViewContainer mavContainer, NativeWebRequest webRequest) {

        HttpEntity<?> httpEntity = (HttpEntity<?>) returnValue;

        // 设置响应头
        HttpHeaders headers = httpEntity.getHeaders();
        outputMessage.getHeaders().putAll(headers);

        // 写入响应体
        writeWithMessageConverters(httpEntity.getBody(), returnType, outputMessage);
    }
}

使用示例

Java
@GetMapping("/users/{id}")
public ResponseEntity<User> getUser(@PathVariable Long id) {
    User user = userService.getById(id);
    if (user == null) {
        return ResponseEntity.notFound().build();
    }
    return ResponseEntity.ok()
            .header("X-Custom-Header", "value")
            .cacheControl(CacheControl.maxAge(3600))
            .body(user);
}

视图渲染机制

ViewResolver接口

Java
public interface ViewResolver {
    @Nullable
    View resolveViewName(String viewName, Locale locale) throws Exception;
}

View接口

Java
public interface View {
    void render(@Nullable Map<String, ?> model,
            HttpServletRequest request, HttpServletResponse response);
}

内部资源视图解析器

Java
@Configuration
public class WebConfig implements WebMvcConfigurer {
    @Override
    public void configureViewResolvers(ViewResolverRegistry registry) {
        registry.jsp("/WEB-INF/views/", ".jsp");
    }
}

ContentNegotiatingViewResolver

Java
// 根据请求内容类型选择View
public class ContentNegotiatingViewResolver extends WebMvcConfigurerAdapter {
    public View resolveViewName(String viewName, Locale locale) {
        // 获取请求的MediaType
        List<MediaType> requestedMediaTypes = getMediaTypes(request);

        // 查找所有候选View
        List<View> candidateViews = getCandidateViews(viewName, locale);

        // 选择最佳匹配的View
        for (View view : candidateViews) {
            for (MediaType mediaType : requestedMediaTypes) {
                if (view.getContentType().includes(mediaType)) {
                    return view;
                }
            }
        }
        return null;
    }
}

视图渲染流程

Java
// DispatcherServlet
private void processDispatchResult(HttpServletRequest request,
        HttpServletResponse response, HandlerExecutionChain handler,
        ModelAndView mv, Exception exception) {

    // 1. 处理异常情况
    if (exception != null) {
        mv = processHandlerException(request, response, handler, exception);
    }

    // 2. 渲染视图
    if (mv != null && !mv.wasCleared()) {
        render(mv, request, response);
    }
}

protected void render(ModelAndView mv, HttpServletRequest request,
        HttpServletResponse response) {
    // 解析View
    View view = resolveViewName(mv.getViewName(), mv.getModelInternal(), locale);

    // 渲染
    view.render(mv.getModelInternal(), request, response);
}

Thymeleaf集成

Java
@Configuration
public class ThymeleafConfig {
    @Bean
    public SpringResourceTemplateResolver templateResolver() {
        SpringResourceTemplateResolver resolver = new SpringResourceTemplateResolver();
        resolver.setPrefix("classpath:/templates/");
        resolver.setSuffix(".html");
        resolver.setTemplateMode(TemplateMode.HTML);
        return resolver;
    }

    @Bean
    public SpringTemplateEngine templateEngine() {
        SpringTemplateEngine engine = new SpringTemplateEngine();
        engine.setTemplateResolver(templateResolver());
        engine.setEnableSpringELCompiler(true);
        return engine;
    }

    @Bean
    public ThymeleafViewResolver viewResolver() {
        ThymeleafViewResolver resolver = new ThymeleafViewResolver();
        resolver.setTemplateEngine(templateEngine());
        resolver.setCharacterEncoding("UTF-8");
        return resolver;
    }
}

响应处理流程图

text
Handler方法返回值
        ↓
HandlerMethodReturnValueHandlerComposite
        ↓
    支持@ResponseBody?
    ↓ Yes            ↓ No
ResponseBodyMethodProcessor  ViewNameMethodReturnValueHandler
        ↓                        ↓
HttpMessageConverter        ViewResolver
        ↓                        ↓
JSON/XML序列化              View.render()
        ↓                        ↓
写入响应体                   模板渲染
        ↓                        ↓
        └──────── 响应 ─────────┘

返回值处理器统一处理各种响应类型,HttpMessageConverter负责数据序列化,ViewResolver负责视图解析。

要点总结

  1. HandlerMethodReturnValueHandler统一处理返回值
  2. HttpMessageConverter负责JSON/XML等数据格式转换
  3. @ResponseBody直接返回数据,不经过视图解析
  4. ViewResolver解析视图名称为具体View实现
  5. ContentNegotiatingViewResolver支持内容协商多视图

jwdev/articles/SPRINGMVC/专家/MVC核心源码执行流程/MVC核心源码执行流程\响应数据转换与渲染.md

📝 发现内容有误?点击此处直接编辑

← 上一篇 HandlerMapping机制
下一篇 → 异常处理机制
想查看更多题目和详细解析?
小程序提供完整的题库、模拟考试和详细解析
马上就来

长按或扫描二维码,立即体验

扫码体验小程序
马上就来
使用微信扫描二维码
立即体验完整题库