自定义Spring 视图和视图解析器

视图通常就是 JSP、Velocity 、FreeMark等。Spring 默认提供了多种视图解析器,比如,我们可以使用最常用解析器 InternalResourceViewResolver 来查找 JSP 视图(与之相对应的视图类为 InternalResourceView)。通常,一个视图解析器只能查找一个或多个特定类型的视图,我们就可以通过扩展 Spring 来自定义自己所需的视图解析器。目前,视图解析器都需要实现接口 org.springframework.web.servlet.ViewResolver, 它包含方法 resolveViewName,该方法会通过视图名查找并返回 Spring 视图对象。


Spring 常用视图解析器:

1、XmlViewResolver             接口 ViewResolver 的实现,从 XML 配置文件中查找视图实现(默认 XML 配置文件为 /WEB-INF/views.xml).

2、ResourceBundleViewResolver         接口 ViewResolver 的实现,用于从 properties 文件中查找视图。

3、UrlBasedViewResolver           接口 ViewResolver 的实现,用于根据请求的 URL 路径返回相应的视图,该视图需为抽象类 AbstractUrlBasedView 的实现。

4、InternalResourceViewResolver             UrlBasedViewResolver 的子类,通常用于查找 JSP(类 InternalResourceView)和 JSTL(类 JstlView,InternalResourceView 的子类)等视图。

5、VelocityViewResolver /FreeMarkerViewResolver             UrlBasedViewResolver 的子类,分别用于支持 Velocity(类 VelocityView)和 FreeMark 视图(类 FreeMarkerView)。

6、ContentNegotiatingViewResolver                接口 ViewResolver 的实现,用于根据请求文件的后缀名或请求的 header 中的 accept 字段查找视图。



自定义视图:

public class GenericFileView extends AbstractUrlBasedView { 

 // 默认内容类型
 private final static String CONTENT_TYPE = "text/plain"; 

 //http response conent 
 private String responseContent; 

 public GenericFileView() { 
     super(); 
     setContentType(CONTENT_TYPE); 
 } 

 @Override 
 public void setContentType(String contentType) { 
     super.setContentType(contentType); 
 } 

 @Override 
 protected void renderMergedOutputModel(Map<String, Object> model, 
       HttpServletRequest request, HttpServletResponse response) 
       throws Exception { 
     // 设置 content type 
     response.setContentType(getContentType()); 
     // 写入 response 内容
     response.getWriter().write(this.responseContent); 
     response.getWriter().close(); 
 } 

 /** 
 * 设置 http response content 
 * @param responseContent 
 */ 
 public void setResponseContent(String responseContent) { 
     this.responseContent = responseContent; 
 } 

 }
本例中的视图类继承了抽象类 AbstractUrlBasedView,因此,我们的自定义通用视图类并不需太多修改,就是设置文件内容类型和将响应的内容设置到请求响应对象中。


自定义的视图解析器:

所有的视图解析器都需要实现接口 org.springframework.web.servlet.ViewResolver,但同视图的实现一样,Spring 还提供了一个抽象类,我们同样可以通过实现抽象类来节省开发工作。其中,通常一个项目中会有多个视图解析器,那么就需要我们设定各个解析器被调用的优先级,尤其是和 InternalResourceViewResolver 混用的情况下,必须要定义正确的调用优先级,则实现接口 org.springframework.core.Ordered,该接口用于设置视图解析器的调用优先级

视图解析器的核心方法是 loadView:

@Override 
    protected View loadView(String viewName, Locale locale) throws Exception { 
        if (location == null) { 
            throw new Exception( 
                    "No location specified for GenericFileViewResolver."); 
        } 
        String requestedFilePath = location + viewName; 
        Resource resource = null; 
       
        try { 
            logger.finest(requestedFilePath); 
            resource = getApplicationContext().getResource(requestedFilePath); 
           
        } catch (Exception e) { 
            // 返回 null, 以便被下一个 resolver 处理
            logger.finest("No file found for file: " + requestedFilePath); 
            return null; 
        } 
        logger.fine("Requested file found: " + requestedFilePath + ", 
                    viewName:" + viewName); 
        // 根据视图名,获取相应的 view 对象
        GenericFileView view = this.getApplicationContext().getBean(this.viewName, 
                GenericFileView.class); 
        view.setUrl(requestedFilePath); 
        // 写入 view 内容
        view.setResponseContent(inputStreamTOString(resource.getInputStream(), 
                "UTF-8")); 
        return view; 
 }
需要注意的是,在找不到请求文件的时候,需要返回 null,这样 Spring 容器中所注册的其他低优先级的视图解析器才能被调用。

视图解析:

public class JeeDevViewResolver implements ViewResolver  {
    
    private static Log logger = LogFactory.getLog(JeeDevViewResolver.class);

    public View resolveViewName(String viewName, Locale locale) throws Exception {
       for(Map.Entry<Set<String>, ViewResolver> map : viewResolverMap.entrySet()){
           Set<String> suffixs = map.getKey();
           for(String suffix : suffixs){
               if (viewName.endsWith(suffix)){
                   ViewResolver viewResolver = map.getValue();
                   if(null != viewResolver){
                       if (logger.isDebugEnabled()) {
                            logger.debug("found viewResolver '" + viewResolver + "' for viewName '" + viewName+ "'");
                        }
                       return viewResolver.resolveViewName(viewName, locale);
                   }
               }
           }
       }
       
       if(defaultViewResolver != null){
           return defaultViewResolver.resolveViewName(viewName, locale);
       }
       // to allow for ViewResolver chaining
       return null;
    }
    
    
    private Map<Set<String>,ViewResolver> viewResolverMap = new HashMap<Set<String>,ViewResolver>();
    
    private ViewResolver defaultViewResolver = null;

    public Map<Set<String>, ViewResolver> getViewResolverMap() {
        return viewResolverMap;
    }

    public void setViewResolverMap(Map<Set<String>, ViewResolver> viewResolverMap) {
        this.viewResolverMap = viewResolverMap;
    }

    public ViewResolver getDefaultViewResolver() {
        return defaultViewResolver;
    }

    public void setDefaultViewResolver(ViewResolver defaultViewResolver) {
        this.defaultViewResolver = defaultViewResolver;
    }
}

视图映射配置dispather-servlet.xml

假如自定义的 视图解析器NameViewResolver

<bean id="viewResolver" class="com.jeedev.common.web.springmvc.view.JeeDevViewResolver">
        <property name="defaultViewResolver" ref="beanNameViewResolver"/>
        <property name="viewResolverMap">
            <map>
                <entry>
                    <key>
                        <set>
                            <value>.jsp</value>
                        </set>
                    </key>
                    <ref bean="jspViewResolver"/>
                </entry>
                <entry>
                    <key>
                        <set>
                            <value>.vm</value>
                            <value>.htm</value>
                        </set>
                    </key>
                    <ref bean="velocityViewResolver"/>
                </entry>
                <entry>
                    <key><value>.ftl</value></key>
                    <ref bean="freeMarkerViewResolver"/>
                </entry>
                <entry>
                    <key><value>.ziding</value></key>
                    <ref bean="NameViewResolver"/>
                </entry>
            </map>
        </property>
    </bean>

同时注册

<bean id="NameResolver" class="org.springframework.web.servlet.view.NameViewResolver">
        <property name="prefix" value="/WEB-INF/ziding/"/>
        <!--<property name="suffix" value=".ziding"/>-->
    </bean>



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值