spring是如何加載可用的ViewResolver的?

Spring Web MVC 視圖解析

Spring web MVC 框架同其它web MVC 框架同樣,是請求驅動的(request driven),圍繞中心Servlet設計的。中心Servlet會分配請求到各個Controllers,以及提供其它功能。Spring的DispatcherServlet就是這種中心Servlet,但作的更多。全部MVC框架都提供定位視圖(address views)的機制,Spring提供view resolvers,讓你可以在瀏覽器上渲染models,而不會把你束縛在某一特定的視圖技術上。有2個接口(Interface)對於Spring處理視圖來講是很重要的,一個是ViewResolver,另外一個是View。 ViewResolver提供視圖名稱與實際視圖的映射關係,View接口定位請求準備和請求處理到視圖技術上。Spring規定,Controller中的全部handler方法,必須解析到一個邏輯視圖,能夠是顯式的(經過返回String、View或ModelView)或者是隱式的(基於協商 based on conventions)。在Spring中,視圖由邏輯視圖名稱定位,而後由一個view resolver解析。java

Spring自帶的視圖解析器

Spring自身帶有若干種view resolver,好比:AbstractCachingViewResolver、XmlViewResolver、ResourceBundleViewResolver、UrlBasedViewResolver、InternalResourceViewResolver、VelocityViewResolver、FreeMarkerViewResolver
、ContentNegotiatingViewResolver,你能夠使用1種,或鏈式使用多種。使用方法就是在你的*-Servlet.xml配置文件種加入相關的bean。舉例以下:web

<bean id="jspViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    <property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>
    <property name="prefix" value="/WEB-INF/jsp/"/>
    <property name="suffix" value=".jsp"/>
</bean>
<bean id="excelViewResolver" class="org.springframework.web.servlet.view.XmlViewResolver">
    <property name="order" value="1"/>
    <property name="location" value="/WEB-INF/views.xml"/>
</bean>

J2EE環境下視圖解析器的加載

那麼,問題是,Spring是如何從容器中感知到咱們想要使用哪些ViewResoler的呢? 答案就在於DispatcherServlet類中的initViewResolvers方法。spring

DispatcherServlet.java中有一個私有方法,名爲initViewResolvers,代碼片斷以下,就是用來初始化全部ViewResolvers的。瀏覽器

/**
     * Initialize the ViewResolvers used by this class.
     * <p>If no ViewResolver beans are defined in the BeanFactory for this
     * namespace, we default to InternalResourceViewResolver.
     */
    private void initViewResolvers(ApplicationContext context) {
        this.viewResolvers = null;

        if (this.detectAllViewResolvers) {
            // Find all ViewResolvers in the ApplicationContext, including ancestor contexts.
            Map<String, ViewResolver> matchingBeans =
                    BeanFactoryUtils.beansOfTypeIncludingAncestors(context, ViewResolver.class, true, false);
            if (!matchingBeans.isEmpty()) {
                this.viewResolvers = new ArrayList<ViewResolver>(matchingBeans.values());
                // We keep ViewResolvers in sorted order.
                OrderComparator.sort(this.viewResolvers);
            }
        }
        else {
            try {
                ViewResolver vr = context.getBean(VIEW_RESOLVER_BEAN_NAME, ViewResolver.class);
                this.viewResolvers = Collections.singletonList(vr);
            }
            catch (NoSuchBeanDefinitionException ex) {
                // Ignore, we'll add a default ViewResolver later.
            }
        }

        // Ensure we have at least one ViewResolver, by registering
        // a default ViewResolver if no other resolvers are found.
        if (this.viewResolvers == null) {
            this.viewResolvers = getDefaultStrategies(context, ViewResolver.class);
            if (logger.isDebugEnabled()) {
                logger.debug("No ViewResolvers found in servlet '" + getServletName() + "': using default");
            }
        }
    }

若是detectAllViewResolvers屬性被設置爲true的話,就會觸發DispatcherServlet從ApplicationContext中加載全部基類爲ViewResolver的Beans,而後存入viewResolvers列表。
(initViewResolvers會被確保在WebApplicationContext被初始化好了之後纔會被調用的)框架

相關文章
相關標籤/搜索