zoukankan      html  css  js  c++  java
  • spring mvc velocity多视图

    1、ViewResolver
    UrlBasedViewResolver 这个东西是根据url 进行路由的。网上搜了

    1、order 排序,同名出现各种问题

    2、XmlViewResolver,BeanNameViewResolver,ResourceBundleViewResolver  这个

    根据配置文件去找不同的view 乱码。。。莫名,而且配置的起来比较麻烦,好处么,就是一个配置文件基本搞定所有页面位置

    乱码据说WebApplicationContext 中可以设置某弄过

    3、自己写个ViewResolver ,这个比较推荐,也比较靠谱,网上找了2个,觉得还是集成AbstractCachingViewResolver

    比较靠谱,下面是拷贝来的

    package com.cnynld.web.tpl;
    
    import java.util.Iterator;
    import java.util.Locale;
    import java.util.Map;
    
    import org.springframework.core.Ordered;
    import org.springframework.util.StringUtils;
    import org.springframework.web.servlet.View;
    import org.springframework.web.servlet.ViewResolver;
    import org.springframework.web.servlet.view.AbstractCachingViewResolver;
    
    
    /**
     * @author loswing
     * spring mvc 多view 兼容的 通过后缀来过滤
     * FIXME 也可以通过 集成  ViewResolver 不过 AbstractCachingViewResolver是所有resolver的根更靠谱点
     */
    public class SpringMvcExtendViewResolver extends AbstractCachingViewResolver  implements Ordered{ 
       
        private int order = Integer.MIN_VALUE;  
        
        public int getOrder() {  
            return order;  
        }  
      
        public void setOrder(int order) {  
            this.order = order;  
        }  
          
        private Map<String, ViewResolver> resolvers;  
          
        public void setResolvers(Map<String, ViewResolver> resolvers) {  
            this.resolvers = resolvers;  
        }  
        private String getViewResolverKey(String fileExtension){  
            Iterator<String> keyIt = resolvers.keySet().iterator();  
            while (keyIt.hasNext()) {  
                String viewResolverKey = (String) keyIt.next();  
                String[] arr = viewResolverKey.split(",");  
                for (String subKey : arr) {  
                    if(subKey.equals(fileExtension)) return viewResolverKey;  
                }  
            }  
            return null;  
        }  
          
        @Override  
        protected View loadView(String viewName, Locale locale) throws Exception {  
            String fileExtension = StringUtils.getFilenameExtension(viewName);  
            if (fileExtension == null) {  
                return null;  
            }  
            String viewResolverKey = getViewResolverKey(fileExtension);  
            ViewResolver resolver = resolvers.get(viewResolverKey);  
              
            return resolver == null ? null : resolver.resolveViewName(viewName,locale);  
      
        }   
    
    }
    View Code
         <!--
          把下面配置拷贝到spring-mvc.xml中就可以了。
          在需要地方返货 以 vm 为后缀的页面就ok
         -->
        
        <!-- 自定义多视图解析器,根据请求后缀调用相应的视图解析器 -->  
       <bean id="LdMultipleViewResolver" class="com.cnynld.web.tpl.SpringMvcExtendViewResolver" p:order="0">   
            <property name="resolvers">   
                <map>
                   <entry key="vm">
                           <bean  class="org.springframework.web.servlet.view.velocity.VelocityViewResolver">  
                            <property name="cache" value="true"/>  
                            <property name="prefix" value=""/> 
                            <property name="suffix" value="" />  
                            <property name="contentType" value="text/html;charset=UTF-8" />
                        </bean> 
                   </entry> 
                </map>   
            </property>   
        </bean>  
        
         <bean id="velocityConfig" class="org.springframework.web.servlet.view.velocity.VelocityConfigurer">  
            <property name="resourceLoaderPath" value="classpath:/tpl"/>  
            <!-- <property name="configLocation" value="/WEB-INF/velocity.properties"/> --> <!-- 用下面这个吧 -->
            <property name="velocityProperties">  
              <props>  
                <prop key="input.encoding">UTF-8</prop>  
                <prop key="output.encoding">UTF-8</prop>  
                <prop key="contentType">text/html;charset=UTF-8</prop>  
            
                <prop key="file.resource.loader.cache">false</prop>  
                <prop key="file.resource.loader.modificationCheckInterval">1</prop>  
                <prop key="velocimacro.library.autoreload">true</prop>  
            
               <!--  <prop key="velocimacro.library">macro.vm</prop>   -->
            
                    <prop key="runtime.log.logsystem.class">org.apache.velocity.runtime.log.SimpleLog4JLogSystem</prop>  
                    <prop key="runtime.log">com.sa</prop>  
                    <prop key="runtime.log.error.stacktrace">true</prop>  
                    <prop key="runtime.log.warn.stacktrace">true</prop>  
                    <prop key="runtime.log.info.stacktrace">false</prop>  
                    <prop key="runtime.log.invalid.reference">true</prop>  
               </props>  
            </property>  
        </bean>  
    View Code

    下面记录点为了解决这个问题找的笔记

    0、spring mvc 莫名
    0.1Controller 的一些

    //所有Controller 都靠这个开始一切,
    public interface Controller {  
           ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception;  
    }  
    WebContentGenerator Controller的基本属性,设置浏览器相关的解析
    AbstractController 所有Controller的根,如果要继承,注意 Override这个 handleRequestInternal,不要去弄handleRequest
    返回null 就不会触发视图的解析(各种Resolver)
    //spring 的注入的的各种
    BaseCommandController //Validator、 属性绑定 等等各种的入口,是conroller 类解析的逻辑所在,其他下面都是业务流
    AbstractCommandController 我理解为将request 解析类,可以帮助你解决request到object各种问题
    setCommandClass 要转换的对象
    setCommandName 命令对象的名称
    //form相关的control ,理解为Override 这个后handleRequestInternal,根据个人爱好写了好多if else
    AbstractFormController   理解为处理form提交的各个过程
    formBackingObject 显示的时候form绑定的数据
    referenceData 一些其他显示要用的数据,
    //各种FormController 我是都没有用过(bpmn 2.0 看下这个吧)
    SimpleFormController,CancellableFormController ,AbstractWizardFormController流程化的 form 提交具体可以其看class的properties
    只要request 含名字为:_cancel  CancellableFormController的 onCancel就会触发如url?xx=1&_cancel=wc
    //FIXME 理解上有问题,spring mvc 多视图引擎的中 prefix, suffix  就在这里产生的
    AbstractUrlViewController ,UrlFilenameViewController
    url匹配按照url最长匹配优先,
    /long/long 
     /long/**/abc  
     /long/** 
     /**
    如请求为“/long/long” 将匹配第一个“/long/long”,但请求“/long/acd” 
    则将匹配 “/long/**”,如请求“/long/aa/abc”则匹配“/long/**/abc”,如请求“/abc”则将匹配“/**” 
    MultiActionController 这个是mvc的核心吧,基本所有Resolver都来自这里 //FIXME 这里的Delegate 不是太明白
    public (ModelAndView | Map | String | void) actionName(HttpServletRequest request, HttpServletResponse response,
            [,HttpSession session] [,AnyObject]);
    1、返回值:即模型和视图部分;
    
     ModelAndView:模型和视图部分 interface Controller 的标准
    
     Map:只返回模型数据,逻辑视图名会根据RequestToViewNameTranslator实现类来计算,稍候讨论;
    
     String:只返回逻辑视图名;
    
     void:表示该功能方法直接写出response响应(如果其他返回值类型(如Map)返回null则和void进行相同的处理);
           这个就是handleRequest 返回null造成viewresolver 不操作,你可以用response 返回各种莫名的东西,如文件流
    
    2、actionName:功能方法名字;由methodNameResolver根据请求信息解析功能方法名,通过反射调用;
    
    3、形参列表:顺序固定,“[]”表示可选,我们来看看几个示例吧:
    
    //表示到新增页面
    
     public ModelAndView toAdd(HttpServletRequest request, HttpServletResponse response);
    
    //表示新增表单提交,在最后可以带着命令对象
    
     public ModelAndView add(HttpServletRequest request, HttpServletResponse response, UserModel user);
    
    //列表,但只返回模型数据,视图名会通过RequestToViewNameTranslator实现来计算
    
     public Map list(HttpServletRequest request, HttpServletResponse response);
    
    //文件下载,返回值类型为void,表示该功能方法直接写响应
    
     public void fileDownload(HttpServletRequest request, HttpServletResponse response)
    
    //第三个参数可以是session
    
     public ModelAndView sessionWith(HttpServletRequest request, HttpServletResponse response, HttpSession session);
    
    //如果第三个参数是session,那么第四个可以是命令对象,顺序必须是如下顺序
    
     public void sessionAndCommandWith(HttpServletRequest request, HttpServletResponse response, HttpSession session, UserModel user)
    
    4、异常处理方法,MultiActionController提供了简单的异常处理,即在请求的功能处理过程中遇到异常会交给异常处理方法进行处理,式如下所示:
    
     public ModelAndView anyMeaningfulName(HttpServletRequest request, HttpServletResponse response, ExceptionClass exception)
    
     MultiActionController会使用最接近的异常类型来匹配对应的异常处理方法,示例如下所示:
    
      
    
    //处理PayException
    
     public ModelAndView processPayException(HttpServletRequest request, HttpServletResponse response, PayException ex)
    
    //处理Exception
    
     public ModelAndView processException(HttpServletRequest request, HttpServletResponse response,  Exception ex)
    0.x 配置的一些莫名
    prefix, suffix 这个东西 这个在返回的时候有用 视图路径=prefix+逻辑视图名+suffix

     1、ViewResolver
    UrlBasedViewResolver 这个东西是根据url 进行路由的。

    <bean  
       class="org.springframework.web.servlet.view.UrlBasedViewResolver">  
       <property name="prefix" value="/WEB-INF/" />  <!--安全考虑把模板放到url 访问不到的地方-->
       <property name="suffix" value=".jsp" />  <!--所有后缀为.jsp 用下面这个class来过滤 url-->
       <property name="viewClass" value="org.springframework.web.servlet.view.InternalResourceView"/>  <!--如果不用这个,进行一次内部处理request是访问不到/WEB-INF/-->
    </bean>

    1.1 url 视图的分发

    InternalResourceViewResolver 是UrlBasedViewResolver的imp 而且会根据Controller类来找对应对象,并且根据请求将
    对象啊各种放到HttpServletRequest中然后分发对应的视图上去
    eg:url:/hello/test.do

    //路由配置

    @Controller
    @RequestMapping(value="/hello")
    public class HelloController {
        @RequestMapping(value = "/test1", method = RequestMethod.GET) 
        public ModelAndView getUser() { 
            ModelAndView mv = new ModelAndView();  
            mv.addObject("name", " test1 Hello World!!!");  
            mv.setViewName("/hello");      
        }
             @RequestMapping(value = "/test2")
         public String test3(HttpServletRequest request, ModelMap map) {
            map.put("name", "test2 hello world");
                return "/hello";
        }    
    }

    <!--spring-mvc 配置-->

    <bean id="JSPViewResolver"class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="viewClass" value="org.springframework.web.servlet.view.JstlView" /><!--如何解析视图-->
        <property name="contentType" value="text/html" /><!--客户端生成的页面类型-->
        <property name="prefix" value="/WEB-INF/" /><!--模板放在哪里-->
        <property name="suffix" value=".jsp" /><!--模板是啥结尾的-->
        <!--多视图的时候有用,效率问题,如果没有InternalResourceViewResolver会返回个null然后停滞,造成其他Resolver不执行,所以order要大,建议用ResourceBundleViewResolver-->
        <property name="order" value="10"></property>
    </bean>

    //在/WEB-INF/ 建个文件 hello.jsp
    hello ${message}

    //访问
    http://localhost:8080/hello/test1.do
    http://localhost:8080/hello/test2.do

    2、XmlViewResolver根据配置文件分发页面,这个是我以前最恨的,每次svn都冲突,搞头昏
    但是后来觉得这个实际更好用,代码里模板面嵌入模板路径,最后的结果是更加混乱(不过继续推荐ResourceBundleViewResolver)

        <!--spring-mvc-->
        <bean class="org.springframework.web.servlet.view.XmlViewResolver">  
           <property name="location" value="/WEB-INF/views.xml"/>  <!--配置文件在哪里-->
           <property name="order" value="1"/>  
        </bean>
        //views.xml
        <?xml version="1.0" encoding="UTF-8"?>  
        <beans xmlns="http://www.springframework.org/schema/beans"  
            xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
            xsi:schemaLocation="http://www.springframework.org/schema/beans  
             http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">  
            <bean id="myxml" class="org.springframework.web.servlet.view.InternalResourceView">  
               <property name="url" value="/hello.jsp"/>  <!--可以交给美工自己去弄-->
            </bean>  
        </beans>  
    //路由,上面路由添加
    @RequestMapping("/xml")  
    public String testXmlViewResolver() {  
       return "myxml";  //这样模板就交给前台配置,后台人员只要告诉前台基本
    } 

     3、ResourceBundleViewResolver和xml很像,不过他的配置文件必须是放在classpath路径下面
    默认为views.properties 如果不使用默认值的话,则可以通过属性baseName或baseNames来指定。baseName只是指定一个基名称,
    Spring会在指定的classpath根目录下寻找以指定的baseName开始的属性文件进行View解析,如指定的baseName是base,
    那么base.properties、baseabc.properties等等以base开始的属性文件都会被Spring当做ResourceBundleViewResolver解析视图的资源文件。

    <bean class="org.springframework.web.servlet.view.ResourceBundleViewResolver">  
     <property name="basename" value="views"></property> <!--所有以views开头的文件都会被解析,建议一个模块一个views_moduleX.properties--> 
      <property name="order"value="0"></property>  <!--如果你还配置了其他Resolver这个是非常必要的-->
     </bean> 
    //views.properties 
    resourceBundle.(class)=org.springframework.web.servlet.view.InternalResourceView  
    resourceBundle.url=/hello.jsp  
    //views_hello.properties
    hello.(class)=org.springframework.web.servlet.view.InternalResourceView  
    hello.url=/hello.jsp
    //code 
             @RequestMapping(value = "/test3")
         public String test3(HttpServletRequest request, ModelMap map) {
            map.put("name", "test3 hello world");
                return "hello";
        }

    参考:
    http://haohaoxuexi.iteye.com/blog/1770554 说明白了view的解析(其他博文也建议看下)
    https://github.com/sxyx2008/maven-framework-project/ 很好的spring mvc 的demo
    http://www.ibm.com/developerworks/cn/java/j-lo-springview/ 视图和视图解析器的相关概念 这个写的一般不过是中文的
    http://blog.csdn.net/chichengit/article/details/12098111 写的比较全的,文中大量ctrl+c了其代码和文字
    http://martinwuje.iteye.com/blog/1872952 velocity自己搞

  • 相关阅读:
    Python学习摘要201802
    机器学习-梯度下降参数调优小结
    用尽洪荒之力学习Flask源码
    Flask类的属性和方法大全
    Flask第三方工具组件介绍
    Flask自带的常用组件介绍
    Centos下部署Flask
    Python Tips阅读摘要
    web程序设计关于我们
    软工实践总结
  • 原文地址:https://www.cnblogs.com/loswing/p/3824664.html
Copyright © 2011-2022 走看看