您好,登錄后才能下訂單哦!
ViewResolver很簡單,通過名稱(name),獲取View視圖的。
View視圖 其實就是對應MVC中的"V"
1.ViewResolver 結構圖
2.BeanNameViewResolver
通過把返回的邏輯視圖名稱去匹配定義好的視圖bean對象。
@Test public void testBeanNameViewResolver() throws ServletException { StaticWebApplicationContext wac = new StaticWebApplicationContext(); wac.setServletContext(new MockServletContext()); MutablePropertyValues pvs1 = new MutablePropertyValues(); pvs1.addPropertyValue(new PropertyValue("url", "/example1.jsp")); wac.registerSingleton("example1", InternalResourceView.class, pvs1); BeanNameViewResolver vr = new BeanNameViewResolver(); vr.setApplicationContext(wac); wac.refresh(); View view = vr.resolveViewName("example1", Locale.getDefault()); assertEquals("Correct view class", InternalResourceView.class, view.getClass()); assertEquals("Correct URL", "/example1.jsp", ((InternalResourceView) view).getUrl()); }
3.XmlViewResolver
XmlViewResolver這個視圖解析器跟 BeanNameViewResolver 有點類似,也是通過把返回的邏輯視圖名稱去匹配定義好的視圖 bean 對象。
3.1 配置XML
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN" "http://www.springframework.org/dtd/spring-beans-2.0.dtd"> <beans> <bean id="example1" class="org.springframework.web.servlet.view.ViewResolverTests$TestView"> <property name="url"><value>/example1.jsp</value></property> <property name="attributesMap"> <map> <entry key="test1"><value>testvalue1</value></entry> <entry key="test2"><ref bean="testBean"/></entry> </map> </property> <property name="location"><value>test</value></property> </bean> </beans>
3.2 測試用例
@Test public void testXmlViewResolver() throws Exception { StaticWebApplicationContext wac = new StaticWebApplicationContext(); wac.registerSingleton("testBean", TestBean.class); wac.setServletContext(new MockServletContext()); wac.refresh(); TestBean testBean = (TestBean) wac.getBean("testBean"); XmlViewResolver vr = new XmlViewResolver(); vr.setLocation(new ClassPathResource("org/springframework/web/servlet/view/views.xml")); vr.setApplicationContext(wac); View view1 = vr.resolveViewName("example1", Locale.getDefault()); assertTrue("Correct view class", TestView.class.equals(view1.getClass())); assertTrue("Correct URL", "/example1.jsp".equals(((InternalResourceView) view1).getUrl()));BeanNameViewResolver VS XmlViewResolver
1. BeanNameViewResolver 要求視圖 bean 對象都定義在 Spring 的 application context 中,而 XmlViewResolver 是在指定的配置文件中尋找視圖 bean 對象,
2. XmlViewResolver是 AbstractCachingViewResolver的子類,支持緩存;
BeanNameViewResolver 不會進行視圖緩存。
4. ResourceBundleViewResolver
和 XmlViewResolver 一樣它也需要有一個配置文件來定義邏輯視圖名稱和真正的 View 對象的對應關系,不同的是 ResourceBundleViewResolver 的配置文件是一個屬性文件,而且必須是放在 classpath 路徑下面的,默認情況下這個配置文件是在 classpath 根目錄下的 views.properties 文件,如果不使用默認值的話,則可以通過屬性 baseName 或 baseNames 來指定。
4.1 配置文件testviews_fr.properties
debugView.(class)= org.springframework.web.servlet.view.InternalResourceView debugView.url=jsp/debug/deboug.jsp debugView.contentType=text/xml;charset=ISO-8859-1
4.2 測試用例
public class ResourceBundleViewResolverTests extends TestCase { /** Comes from this package */ private static String PROPS_FILE = "org.springframework.web.servlet.view.testviews"; private ResourceBundleViewResolver rb; private StaticWebApplicationContext wac; protected void setUp() throws Exception { rb = new ResourceBundleViewResolver(); rb.setBasename(PROPS_FILE); rb.setCache(getCache()); rb.setDefaultParentView("testParent"); wac = new StaticWebApplicationContext(); wac.setServletContext(new MockServletContext()); wac.refresh(); // This will be propagated to views, so we need it. rb.setApplicationContext(wac); } public void testDebugViewFrench() throws Exception { View v = rb.resolveViewName("debugView", Locale.FRENCH); assertTrue("French debugView must be of type InternalResourceView", v instanceof InternalResourceView); InternalResourceView jv = (InternalResourceView) v; assertTrue("French debugView must have correct URL", "jsp/debug/deboug.jsp".equals(jv.getUrl())); assertTrue( "Correct overridden (XML) content type, not '" + jv.getContentType() + "'", jv.getContentType().equals("text/xml;charset=ISO-8859-1")); } }
在ResourceBundleViewResolver第一次進行視圖解析的時候會先new一個BeanFactory對象,然后把properties文件中定義好的屬性按照它自身的規則生成一個個的bean對象注冊到該BeanFactory中,之后會把該BeanFactory對象保存起來,所以ResourceBundleViewResolver緩存的是BeanFactory,而不是直接的緩存從BeanFactory中取出的視圖bean。然后會從bean工廠中取出名稱為邏輯視圖名稱的視圖bean進行返回。接下來就講講Spring通過properties文件生成bean的規則。它會把properties文件中定義的屬性名稱按最后一個點“.”進行分割,把點前面的內容當做是bean名稱,點后面的內容當做是bean的屬性。這其中有幾個特別的屬性,Spring把它們用小括號包起來了,這些特殊的屬性一般是對應的attribute,但不是bean對象所有的attribute都可以這樣用。其中(class)是一個,除了(class)之外,還有(scope)、(parent)、(abstract)、(lazy-init)。而除了這些特殊的屬性之外的其他屬性,Spring會把它們當做bean對象的一般屬性進行處理,就是bean對象對應的property。所以根據上面的屬性配置文件將生成如下兩個bean對象:
from http://elim.iteye.com/blog/1770554
5.UrlBasedViewResolver
它是對ViewResolver的一種簡單實現,而且繼承了AbstractCachingViewResolver,主要就是提供的一種拼接URL的方式來解析視圖,它可以讓我們通過prefix屬性指定一個指定的前綴,通過suffix屬性指定一個指定的后綴,然后把返回的邏輯視圖名稱加上指定的前綴和后綴就是指定的視圖URL了。
5.2 重要屬性
public class UrlBasedViewResolver extends AbstractCachingViewResolver implements Ordered { /** * Prefix for special view names that specify a redirect URL (usually * to a controller after a form has been submitted and processed). * Such view names will not be resolved in the configured default * way but rather be treated as special shortcut. */ public static final String REDIRECT_URL_PREFIX = "redirect:"; /** * Prefix for special view names that specify a forward URL (usually * to a controller after a form has been submitted and processed). * Such view names will not be resolved in the configured default * way but rather be treated as special shortcut. */ public static final String FORWARD_URL_PREFIX = "forward:"; //Set the view class that should be used to create views. private Class viewClass; // Set the prefix that gets prepended to view names when building a URL. private String prefix = ""; //the suffix that gets appended to view names when building a URL. private String suffix = ""; //view names; such that 'my*', '*Report' and '*Repo*' private String[] viewNames = null; //content type for all views. private String contentType; //UrlBasedViewResolver 的 redirectContextRelative 的默認值為 true, //這意味著,只要重定向的資源以/開頭,那么 spring 會幫你添加 contextPath private boolean redirectContextRelative = true; //whether redirects should stay compatible with HTTP 1.0 clients private boolean redirectHttp10Compatible = true; //the name of the RequestContext attribute for all views private String requestContextAttribute; private int order = Integer.MAX_VALUE; /** Map of static attributes, keyed by attribute name (String) */ private final Map<String, Object> staticAttributes = new HashMap<String, Object>(); ... }
5.3 createView方法
public static final String REDIRECT_URL_PREFIX = "redirect:"; protected View createView(String viewName, Locale locale) throws Exception { // If this resolver is not supposed to handle the given view, // return null to pass on to the next resolver in the chain. if (!canHandle(viewName, locale)) { return null; } // Check for special "redirect:" prefix. if (viewName.startsWith(REDIRECT_URL_PREFIX)) { String redirectUrl = viewName.substring(REDIRECT_URL_PREFIX.length()); return new RedirectView(redirectUrl, isRedirectContextRelative(), isRedirectHttp10Compatible()); } // Check for special "forward:" prefix. if (viewName.startsWith(FORWARD_URL_PREFIX)) { String forwardUrl = viewName.substring(FORWARD_URL_PREFIX.length()); return new InternalResourceView(forwardUrl); } // Else fall back to superclass implementation: calling loadView. return super.createView(viewName, locale); }
URLBasedViewResolver發現返回的視圖名稱包含”redirect:”前綴,于是把返回的視圖名稱前綴”redirect:”去掉,取后面的test.do組成一個RedirectView,RedirectView中將把請求返回的模型屬性組合成查詢參數的形式組合到redirect的URL后面,然后調用HttpServletResponse對象的sendRedirect方法進行重定向。同樣URLBasedViewResolver還支持forword:前綴,對于視圖名稱中包含forword:前綴的視圖名稱將會被封裝成一個InternalResourceView對象,然后在服務器端利用RequestDispatcher的forword方式跳轉到指定的地址。使用UrlBasedViewResolver的時候必須指定屬性viewClass,表示解析成哪種視圖,一般使用較多的就是InternalResourceView,利用它來展現jsp,但是當我們使用JSTL的時候我們必須使用JstlView。
5.4 一段UrlBasedViewResolver的定義
<bean class="org.springframework.web.servlet.view.UrlBasedViewResolver"> <property name="prefix" value="/WEB-INF/" /> <property name="suffix" value=".jsp" /> <property name="viewClass" value="org.springframework.web.servlet.view.InternalResourceView"/> </bean>
6.InternalResourceViewResolver 內部資源視圖解析器
InternalResourceViewResolver會把返回的視圖名稱都解析為InternalResourceView對象,InternalResourceView會把Controller處理器方法返回的模型屬性都存放到對應的request屬性中,然后通過RequestDispatcher在服務器端把請求forword重定向到目標URL。
6.1最熟悉的一段配置
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix" value="/WEB-INF/"/> <property name="suffix" value=".jsp"></property> </bean>
總結
ViewResolver解決的事情很單一
通過配置,根據不同策略,找出匹配的JSP(也可以是其他)。
適當添加緩存處理
根據策略不同,返回不同的VIEW,降低耦合度。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。