22_6 Spring MVC - ViewResolver系列 - ResourceBundleViewResolver

22_6 Spring MVC - ViewResolver系列 - ResourceBundleViewResolver

一、简介

ResourceBundleViewResolver和XmlViewResolver一样,也是继承自AbstractCachingViewResolver,但是它缓存的不是视图。同时它也需要一个配置文件来定义逻辑视图名称和真正的View对象的对应关系,不同的是它需要的是一个属性文件,而且必须放在classpath路径下面。默认情况下这个配置文件是classpath根目录下的views.properties文件,如果不实用默认值的话,则可以通过baseName或baseNames来指定。

二、源码解析

2.1 loadView(String viewName, Locale locale)

重写 loadView方法来创建View对象

	@Override
	protected View loadView(String viewName, Locale locale) throws Exception {
		BeanFactory factory = initFactory(locale);
		try {
			return factory.getBean(viewName, View.class);
		}
		catch (NoSuchBeanDefinitionException ex) {
			// Allow for ViewResolver chaining...
			return null;
		}
	}
  • 在loadView方法中先初始化Spring容器
  • 通过Spring容器获取视图Bean对象

2.2 initFactory(locale)


	/** The default basename if no other basename is supplied */
	public static final String DEFAULT_BASENAME = "views";

	protected synchronized BeanFactory initFactory(Locale locale) throws BeansException {
		// Try to find cached factory for Locale:
		// Have we already encountered that Locale before?
		if (isCache()) {
			BeanFactory cachedFactory = this.localeCache.get(locale);
			if (cachedFactory != null) {
				return cachedFactory;
			}
		}

		// Build list of ResourceBundle references for Locale.
		List<ResourceBundle> bundles = new LinkedList<>();
		for (String basename : this.basenames) {
			ResourceBundle bundle = getBundle(basename, locale);
			bundles.add(bundle);
		}

		// Try to find cached factory for ResourceBundle list:
		// even if Locale was different, same bundles might have been found.
		if (isCache()) {
			BeanFactory cachedFactory = this.bundleCache.get(bundles);
			if (cachedFactory != null) {
				this.localeCache.put(locale, cachedFactory);
				return cachedFactory;
			}
		}

		// Create child ApplicationContext for views.
		GenericWebApplicationContext factory = new GenericWebApplicationContext();
		factory.setParent(getApplicationContext());
		factory.setServletContext(getServletContext());

		// Load bean definitions from resource bundle.
		PropertiesBeanDefinitionReader reader = new PropertiesBeanDefinitionReader(factory);
		reader.setDefaultParentBean(this.defaultParentView);
		for (ResourceBundle bundle : bundles) {
			reader.registerBeanDefinitions(bundle);
		}

		factory.refresh();

		// Cache factory for both Locale and ResourceBundle list.
		if (isCache()) {
			this.localeCache.put(locale, factory);
			this.bundleCache.put(bundles, factory);
		}

		return factory;
	}
  • 可以看到在初始化Spring容器时,通过PropertiesBeanDefinitionReader 对象来读取配置文件
  • 默认情况下,配置文件为classpath根目录下的view.properties

三、使用

3.1 配置ResourceBundleViewResolver的配置文件

ResourceBundleViewResolver是根据properties文件来找对应的视图来解析"逻辑视图"的,该properties文件默认是放在classpath路径下的views.properties文件,当然可以通过basename属性更改。

<bean class="org.springframework.web.servlet.view.ResourceBundleViewResolver">
    <property name="basename" value="spring-views"></property>
    <property name="order" value="1"></property>
</bean>

这时ResourceBundleViewResolver会从classpath路径下的spring-views.properties文件中寻找物理视图。

3.2 编辑配置文件spring-views.properties

login.(class)=org.springframework.web.servlet.view.JstView
login.url=/WEB-INF/jsp/login.jsp

properties文件里面存放的是key-value数据,从文件中可以看出逻辑视图与视图Bean也是以这种方式绑定的。
1、login表示处理器(controller)返回的逻辑视图
2、login.(class)表示视图Bean对应的视图类
3、login.url表示物理视图
注意要将这个“spring-views.properties”文件放到项目的classpath路径下。

3.3 Controller控制器

@RequestMapping(value="/page",method=RequestMethod.GET)
public String getPage(Model model){
  return "login";
}

当处理器(controller)返回”login“时,会在前台显示/WEB-INF/jsp/login.jsp的页面内容。

四、总结

当控制器返回一个名为“login”的视图时,ResourceBundleViewResolver将在“spring-views.properties”文件中查找以“login”起始的键,并返回相对应的视图URL“/WEB-INF/pages/login.jsp”给DispatcherServlet。

posted @ 2020-09-13 15:41  在线打工者  阅读(187)  评论(0编辑  收藏  举报