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。