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。
 
                    
                     
                    
                 
                    
                
 
                
            
         
         浙公网安备 33010602011771号
浙公网安备 33010602011771号