Spring MVC 之 ViewResolver

SpringMVC的视图解析器ViewResolver负责将控制器返回的逻辑视图名称转化为具体视图实现,如JSP、FreeMarker模板等。常见的ViewResolver包括InternalResourceViewResolver(解析JSP)、FreeMarkerViewResolver(解析FreeMarker模板)和ContentNegotiatingViewResolver(根据请求头返回JSON等)。InternalResourceViewResolver通过前缀和后缀匹配逻辑视图,而ContentNegotiatingViewResolver根据Accept头选择视图解析器。

        Spring MVC的视图解析器 ViewResolver 是框架中一个重要的组件,用于将控制器返回的逻辑视图名称解析为具体的视图实现对象,最终呈现给用户的是具体的视图实现,例如 JSP、FreeMarker 模板、Thymeleaf 模板、JSON 等等。本文将介绍 Spring MVC 的视图解析器的作用、类型、以及源码实现。

作用

        在 Spring MVC 中,控制器处理完请求之后需要将生成的模型数据和视图名称返回给 DispatcherServlet,DispatcherServlet 会将模型数据和视图名称交给 ViewResolver 进行解析,ViewResolver 将对应的视图解析出来,并返回给 DispatcherServlet,由 DispatcherServlet 进行渲染,最终将渲染后的结果返回给客户端。因此,ViewResolver 的作用是将控制器返回的逻辑视图名称解析为具体的视图实现对象。

类型

        Spring MVC 中提供了多种 ViewResolver 类型,不同类型的 ViewResolver 会使用不同的解析策略和算法,下面介绍几种常见的 ViewResolver 类型。

InternalResourceViewResolver

        InternalResourceViewResolver 是 Spring MVC 中最常用的视图解析器,它用于解析 JS P或 HTML 等资源文件。该解析器会将逻辑视图名称加上前缀和后缀,例如将逻辑视图名称 “hello” 解析为 “/WEB-INF/views/hello.jsp”。

@Configuration
@EnableWebMvc
@ComponentScan(basePackages = "com.example.controller")
public class AppConfig {

    @Bean
    public InternalResourceViewResolver viewResolver() {
        InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
        viewResolver.setPrefix("/WEB-INF/views/");
        viewResolver.setSuffix(".jsp");
        return viewResolver;
    }
}
复制代码

FreeMarkerViewResolver

        FreeMarkerViewResolver 用于解析FreeMarker 模板,它会将逻辑视图名称加上前缀和后缀,例如将逻辑视图名称 “hello” 解析为 “/WEB-INF/views/hello.ftl”。

@Configuration
@EnableWebMvc
@ComponentScan(basePackages = "com.example.controller")
public class AppConfig {

    @Bean
    public FreeMarkerViewResolver viewResolver() {
        FreeMarkerViewResolver viewResolver = new FreeMarkerViewResolver();
        viewResolver.setPrefix("/WEB-INF/views/");
        viewResolver.setSuffix(".ftl");
        return viewResolver;
    }
}
复制代码

TilesViewResolver

        TilesViewResolver 用于解析 Tiles 布局,它会将逻辑视图名称解析为 Tiles 布局,并返回给 DispatcherServlet 进行渲染。Tiles 是一个基于模板的布局框架,可以将页面分成多个部分,每个部分都是一个独立的模板,最终组合成一个完整的页面。

@Configuration
@EnableWebMvc
@ComponentScan(basePackages = "com.example.controller")
public class AppConfig {

    @Bean
    public TilesConfigurer tilesConfigurer() {
        TilesConfigurer tilesConfigurer = new TilesConfigurer();
        tilesConfigurer.setDefinitions(new String[] { "/WEB-INF/tiles.xml" });
        return tilesConfigurer;
    }

    @Bean
    public TilesViewResolver viewResolver() {
        TilesViewResolver viewResolver = new TilesViewResolver();
        return viewResolver;
    }
}
复制代码

ContentNegotiatingViewResolver

        ContentNegotiatingViewResolver 是一个复合视图解析器,它可以根据请求的 Accept 头信息来判断客户端需要的数据类型,并选择对应的视图解析器进行解析。例如客户端请求的 Accept 头信息为 “application/json”,则选择使用 MappingJackson2JsonView 解析器将模型数据渲染成 JSON 格式返回给客户端。

@Configuration
@EnableWebMvc
@ComponentScan(basePackages = "com.example.controller")
public class AppConfig {

    @Bean
    public ContentNegotiatingViewResolver viewResolver() {
        ContentNegotiatingViewResolver viewResolver = new ContentNegotiatingViewResolver();
        List<ViewResolver> viewResolvers = new ArrayList<>();
        viewResolvers.add(jsonViewResolver());
        viewResolver.setViewResolvers(viewResolvers);
        return viewResolver;
    }

    @Bean
    public MappingJackson2JsonViewResolver jsonViewResolver() {
        MappingJackson2JsonViewResolver jsonViewResolver = new MappingJackson2JsonViewResolver();
        return jsonViewResolver;
    }
}

复制代码

源码实现

        Spring MVC 中的视图解析器是通过 ViewResolver 接口来实现的,该接口定义了两个方法:

public interface ViewResolver {
    View resolveViewName(String viewName, Locale locale) throws Exception;
    String REDIRECT_URL_PREFIX = "redirect:";
    String FORWARD_URL_PREFIX = "forward:";
}
复制代码

        其中,resolveViewName 方法接收一个逻辑视图名称和一个 Locale 对象作为参数,返回一个 View 对象。如果找不到对应的 View 对象,则返回 null。

对于 InternalResourceViewResolver 而言,它的 resolveViewName 方法实现如下:

@Override
public View resolveViewName(String viewName, Locale locale) throws Exception {
    String prefix = getPrefix();
    String suffix = getSuffix();
    if (viewName.startsWith(REDIRECT_URL_PREFIX)) {
        String redirectUrl = viewName.substring(REDIRECT_URL_PREFIX.length());
        RedirectView redirectView = new RedirectView(redirectUrl, isRedirectContextRelative(), isRedirectHttp10Compatible());
        String[] hosts = StringUtils.toStringArray(getRedirectHosts());
        if (hosts.length > 0) {
            redirectView.setHosts(hosts);
        }
        return redirectView;
    }
    if (viewName.startsWith(FORWARD_URL_PREFIX)) {
        String forwardUrl = viewName.substring(FORWARD_URL_PREFIX.length());
        InternalResourceView forwardView = new InternalResourceView(forwardUrl);
        forwardView.setApplicationContext(getApplicationContext());
        forwardView.setServletContext(getServletContext());
        forwardView.setAttributesMap(getAttributesMap());
        return forwardView;
    }
    if (!viewName.startsWith(prefix) && !viewName.endsWith(suffix)) {
        viewName = prefix + viewName + suffix;
    }
    return buildView(viewName);
}
复制代码

        在上面的代码中 首先判断逻辑视图名称是否以 redirect: 或 forward: 开头,如果是就返回 RedirectView 或 InternalResourceView 对象。

        如果不是,则根据 prefix 和 suffix 属性将逻辑视图名称转换为物理视图名称。

总结

        Spring MVC 的视图解析器 ViewResolver 是一个重要的组件,它将控制器返回的逻辑视图名称解析为具体的视图实现对象,最终呈现给用户的是具体的视图实现。

        Spring MVC提供了多种 ViewResolver 类型,不同类型的ViewResolver会使用不同的解析策略和算法,例如 InternalResourceViewResolver 用于解析JSP或HTML等资源文件,FreeMarkerViewResolver 用于解析 FreeMarker 模板,TilesViewResolver 用于解析 Tiles 布局,ContentNegotiatingViewResolver 则是一个复合视图解析器,可以根据请求的 Accept 头信息来选择对应的视图解析器进行解析。

        ViewResolver 的源码实现遵循了 ViewResolver 接口的规范,即将逻辑视图名称解析为具体的视图实现对象。

 

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值