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. 我相信我们成为怎样的人是我们自己的选择。没有人会来拯救你,你必须要自己拯救自己。
原文地址:https://www.cnblogs.com/caroline/p/2991280.html