• Struts2使用通配符完成方法和action的调用


    官网对struts2通配符使用的介绍:

    Wildcard Mappings

    <action name="*_*" class="com.netshuai.action.{1}Action" method="{2}">
    <result name="success">/{2}_{1}Success.jsp</result>
    </action>

    如上所示,所有文件都采用统一的命名规范,第一个*为分类名称,第二个*为操作名,{1}和{2}分别代表第一个和第二个*的替换值,所有action实现类都命名为分类名称+Action。
    如分类名称为User,操作名为add,则访问的action名为User_add.action,action实现类名为UserAction,返回页面的名为add_UserSuccess.jsp 
    另:{0}代表显示所有通配符内容,如<result name="success">/{2}_{1}Success.jsp</result>改为<resultname="success">/{0}Success.jsp</result>,则返回的名为User_addSuccess.jsp

    下面我们来介绍struts2的通配符方面的实现的内部原理

    AbstractMatcher类是主要的匹配和计算通配符的类,下面我们来学习他的match方法

     /**
         * <p> Matches the path against the compiled wildcard patterns. </p>
         *
         * @param potentialMatch The portion of the request URI for selecting a config.
         * @return The action config if matched, else null
         */
        public E match(String potentialMatch) {
            E config = null;
            所有已经编译好的通配符的list,即已经将表达式的字符串转换为整形数组
            if (compiledPatterns.size() > 0) {
                if (log.isDebugEnabled()) {
                    log.debug("Attempting to match '" + potentialMatch
                        + "' to a wildcard pattern, "+ compiledPatterns.size()
                        + " available");
                }
                在这里,我们的match方法中传递的map(vars)终于派上了用场,它是用来存储匹配成功的字符,
                Map<String,String> vars = new LinkedHashMap<String,String>();
                for (Mapping<E> m : compiledPatterns) {
                    if (wildcard.match(vars, potentialMatch, m.getPattern())) {
                        if (log.isDebugEnabled()) {
                            log.debug("Value matches pattern '"
                                + m.getOriginalPattern() + "'");
                        }
    
                        config =
                            convert(potentialMatch, m.getTarget(), vars);
                        break;
                    }
                }
            }
    
            return config;
        }

    下面我们来关注下convert方法:我们关注它的子类,ActionConfigMatcher

    在进行convert方法的时候,传递了一个map,下面我们通过一个模拟WildCardMatcher类的方法,给我们看下,这个map

    到底是什么:

    运行这段模拟的java代码:

     1 public static void main(String[] args) throws URISyntaxException {
     2         WildcardHelper w = new WildcardHelper();
     3         int[] a = w.compilePattern("*_*");
     4         for (int i = 0; i < a.length; i++) {
     5             int j = a[i];
     6             System.out.print(j + ",");
     7         }
     8         Map<String,String> vars = new LinkedHashMap<String,String>();
     9         //User_add.action,页面请求的action,请求通过struts2的处理后,他会把后缀action给截取掉
    10         //所以,我们模拟的时候,将action给去掉
    11         w.match(vars, "User_add", a);
    12         System.out.println();
    13         System.out.println(vars);
    14     }

    结果:

    1 -4,-1,95,-1,-5,
    2 {0=User_add, 1=User, 2=add}

    现在终于知道了这个map的作用了,这个map存放的值是为了在取如下配置中的

    <action name="*_*" class="com.netshuai.action.{1}Action" method="{2}">
      <result name="success">/{2}_{1}Success.jsp</result>
    </action>

    {1}和{2}中的值,另外,struts2对这个{下标}的这个下标的最大值进行了限定,最大的值为9,请看下面的官网的介绍

    In the action mapping and action results, the wildcard-matched values can be accessed with the token {N} where N is a number from 1 to 9 indicating which wildcard-matched value to substitute. The whole request URI can be accessed with the {0} token.{0代表struts2的请求全路径},

     1  /**
     2      * <p> Clones the ActionConfig and its children, replacing various
     3      * properties with the values of the wildcard-matched strings. </p>
     4      *
     5      * @param path The requested path
     6      * @param orig The original ActionConfig
     7      * @param vars A Map of wildcard-matched strings
     8      * @return A cloned ActionConfig with appropriate properties replaced with
     9      *         wildcard-matched values
    10      */
    11     @Override public ActionConfig convert(String path, ActionConfig orig,
    12         Map<String, String> vars) {
    13         
    14         String className = convertParam(orig.getClassName(), vars);转换类名
    15         String methodName = convertParam(orig.getMethodName(), vars);转换方法名
    16         String pkgName = convertParam(orig.getPackageName(), vars);转换包名
    17         替换参数
    18         Map<String,String> params = replaceParameters(orig.getParams(), vars);
    19         替换result配置
    20         Map<String,ResultConfig> results = new LinkedHashMap<String,ResultConfig>();
    21         for (String name : orig.getResults().keySet()) {
    22             ResultConfig result = orig.getResults().get(name);
    23             name = convertParam(name, vars);
    24             ResultConfig r = new ResultConfig.Builder(name, convertParam(result.getClassName(), vars))
    25                     .addParams(replaceParameters(result.getParams(), vars))
    26                     .build();
    27             results.put(name, r);
    28         }
    29         
    30         List<ExceptionMappingConfig> exs = new ArrayList<ExceptionMappingConfig>();
    31         for (ExceptionMappingConfig ex : orig.getExceptionMappings()) {
    32             String name = convertParam(ex.getName(), vars);
    33             String exClassName = convertParam(ex.getExceptionClassName(), vars);
    34             String exResult = convertParam(ex.getResult(), vars);
    35             Map<String,String> exParams = replaceParameters(ex.getParams(), vars);
    36             ExceptionMappingConfig e = new ExceptionMappingConfig.Builder(name, exClassName, exResult).addParams(exParams).build();
    37             exs.add(e);
    38         }
    39         重新的构造针当前action的配置:config
    40         return new ActionConfig.Builder(pkgName, orig.getName(), className)
    41                 .methodName(methodName)
    42                 .addParams(params)
    43                 .addResultConfigs(results)
    44                 .addInterceptors(orig.getInterceptors())
    45                 .addExceptionMappings(exs)
    46                 .location(orig.getLocation())
    47                 .build();
    48     }

     下面我们学习下convertParam方法:

     1  /**
     2      * <p> Inserts into a value wildcard-matched strings where specified
     3      * with the {x} syntax.  If a wildcard-matched value isn't found, the
     4      * replacement token is turned into an empty string. 
     5      * </p>
     6      *
     7      * @param val  The value to convert
     8      * @param vars A Map of wildcard-matched strings
     9      * @return The new value
    10      */
    11     protected String convertParam(String val, Map<String, String> vars) {
    12         if (val == null) {
    13             return null;
    14         } 
    15         
    16         int len = val.length();
    17         StringBuilder ret = new StringBuilder();
    18         char c;
    19         String varVal;
    20         for (int x=0; x<len; x++) {
    21             c = val.charAt(x);
    22             if (x < len - 2 && 
    23                     c == '{' && '}' == val.charAt(x+2)) {
    24                 varVal = (String)vars.get(String.valueOf(val.charAt(x + 1)));
    25                 if (varVal != null) {
    26                     ret.append(varVal);
    27                 } 
    28                 x += 2;在这里,将类似于{1}的值进行了替换,替换为解析好的map中的值,替换后进行+2,向后叠加
    29             } else {
    30                 ret.append(c);
    31             }
    32         }
    33         
    34         return ret.toString();
    35     }

    -end

    I believe that we are who we choose to be. Nobody‘s going to come and save you, you‘ve got to save yourself. 我相信我们成为怎样的人是我们自己的选择。没有人会来拯救你,你必须要自己拯救自己。
  • 相关阅读:
    datetime模块
    python正则表达式练习题
    Python入门——turtle库的使用
    Python入门——Python程序语法元素
    Python入门——eval() 函数
    Python入门——实例1_温度转换
    Python入门——编程方式
    Python入门——程序的基本编写方法
    Python入门——编译和解释
    SQL中isnull、ifnull和nullif函数用法
  • 原文地址:https://www.cnblogs.com/caroline/p/2991280.html
Copyright © 2020-2023  润新知