Spring MVC 提供了 ViewResolver接口用以通过视图名查找并解析视图。该接口有resolveViewName方法,返回 View 视图。接受 String类型的视图名,以该视图名进行查找。还有 Locale 类型的地区参数, 用于进行国际化。 Spring MVC 的控制器中支持多个ViewResolver, 查找视图时进行遍历查找, 直到找到相应的视图,如果没有找到则报错提示没有查找到相应的视图。默认情况下 SpringMVC 支持以下几种查找与解析的策略。
该方式支持通过返回BeanName来查找 View, 该 View 需要声明为 Spring 容器的 Bean,该解析方式是通过 BeanNameViewResolver 执行的,这种方式要求声明的 Bean 类型为 View接口的实现, 示例代码如下:
// CustomViewController. java文件
@Controller
public class CustomViewController {
@RequestMapping("/beanNameView")
public String beanNameView( Model model) {
// 添加一个 Model 属性
model. addAttribute(" name", "BeanNameView");
// 返回ViewName, 用于查找
return "beanNameViewBean";
}
}
// CustomView. java文件
// 声明为 Bean, BeanName 为beanNameViewBean
@Component("beanNameViewBean")
public class CustomView implements View {
// 返回该 View支持 text/ html类型的ContentType,用于查找到多个 view时选择最优匹配结果
@Override
public String getContentType() {
return MediaType. TEXT_HTML_VALUE;
}
//执行视图的渲染操作,第一个参数是处理器逻辑中 Model处理逻辑产生的 Model 模型数据
@Override
public void render(@ Nullable Map< String, ?> model, HttpServletRequest request,HttpServletResponse response) throws Exception {
// 从 Model 中拿到模型参数
Object name = model. get(" name") ;
//返回页面内容
response. getWriter(). append(" name is" + name);
}
}
访问 localhost:8080/beanNameView, 可以正常使用我们定义的 View 类型的 Bean 去渲染视图。
各种模板引擎都会为自己配置视图解析器,用于实现自己的视图解析。这里以Thymeleaf为例, 简单说明模板引擎视图解析的工作原理。
在项目中引入 spring- boot- starter - thymeleaf 依赖后, Spring Boot的自动配置机制就会生效,自动生成ThymeleafViewResolver到 Spring MVC中, 控制器逻辑可以引用到此视图解析器。默认情况下ThymeleafViewResolver会以 classpath:/ templates/为前缀, 以.html为后缀,把前缀和后缀拼接成视图名后进行资源查找。该属性可以通过 SpringBoot的配置进行修改。
spring. thymeleaf. prefix=视图前缀
spring. thymeleaf. suffix=视图后缀
也可以通过引入其他模板引擎的 starter 依赖来自动产生其特定的视图解析器。关于这种视图解析的例子前面已经介绍很多了, 这里就不再赘述了, 而关于视图解析与自动配置相关的内容将在后面源码解析中详述。
该种解析用于处理各种内部特殊视图, 如前面提到的转发视图和重定向视图, 以及 Servlet容器自带的JSP 视图解析。
该视图解析器为 InternalResourceViewResolver, 其中会判断视图名的前缀类型, 以 forward:或者 redirect:为前缀, 再返回其对应类型的视图。
除了通过视图名自动查找视图外, 还可以通过直接指定视图的方式来跳过通过视图名解析视图的步骤。
在前面 Model 部分提到了 ModelAndView类型,这种类型除了可以接受 String类型的视图名外, 还可以直接接受 View类型的实例作为视图。
同时也可以在@RequestMapping 标记的方法中, 直接返回 View 类型的返回值,此时该返回值也会被直接作为最终视图使用, 示例代码如下:
@RequestMapping("/returnView")
public View returnView( Model model) {
// 添加一个 Model 属性
model. addAttribute(" name", "returnView");
// 直接返回 View类型
return new CustomView();
}