您的位置:首页 > 编程语言 > Java开发

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

2013-03-31 09:04 423 查看
官网对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代码:

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


结果:

-4,-1,95,-1,-5,
{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的请求全路径},

/**
* <p> Clones the ActionConfig and its children, replacing various
* properties with the values of the wildcard-matched strings. </p>
*
* @param path The requested path
* @param orig The original ActionConfig
* @param vars A Map of wildcard-matched strings
* @return A cloned ActionConfig with appropriate properties replaced with
*         wildcard-matched values
*/
@Override public ActionConfig convert(String path, ActionConfig orig,
Map<String, String> vars) {

String className = convertParam(orig.getClassName(), vars);转换类名
String methodName = convertParam(orig.getMethodName(), vars);转换方法名
String pkgName = convertParam(orig.getPackageName(), vars);转换包名
替换参数
Map<String,String> params = replaceParameters(orig.getParams(), vars);
替换result配置
Map<String,ResultConfig> results = new LinkedHashMap<String,ResultConfig>();
for (String name : orig.getResults().keySet()) {
ResultConfig result = orig.getResults().get(name);
name = convertParam(name, vars);
ResultConfig r = new ResultConfig.Builder(name, convertParam(result.getClassName(), vars))
.addParams(replaceParameters(result.getParams(), vars))
.build();
results.put(name, r);
}

List<ExceptionMappingConfig> exs = new ArrayList<ExceptionMappingConfig>();
for (ExceptionMappingConfig ex : orig.getExceptionMappings()) {
String name = convertParam(ex.getName(), vars);
String exClassName = convertParam(ex.getExceptionClassName(), vars);
String exResult = convertParam(ex.getResult(), vars);
Map<String,String> exParams = replaceParameters(ex.getParams(), vars);
ExceptionMappingConfig e = new ExceptionMappingConfig.Builder(name, exClassName, exResult).addParams(exParams).build();
exs.add(e);
}
重新的构造针当前action的配置:config
return new ActionConfig.Builder(pkgName, orig.getName(), className)
.methodName(methodName)
.addParams(params)
.addResultConfigs(results)
.addInterceptors(orig.getInterceptors())
.addExceptionMappings(exs)
.location(orig.getLocation())
.build();
}


下面我们学习下convertParam方法:

/**
* <p> Inserts into a value wildcard-matched strings where specified
* with the {x} syntax.  If a wildcard-matched value isn't found, the
* replacement token is turned into an empty string.
* </p>
*
* @param val  The value to convert
* @param vars A Map of wildcard-matched strings
* @return The new value
*/
protected String convertParam(String val, Map<String, String> vars) {
if (val == null) {
return null;
}

int len = val.length();
StringBuilder ret = new StringBuilder();
char c;
String varVal;
for (int x=0; x<len; x++) {
c = val.charAt(x);
if (x < len - 2 &&
c == '{' && '}' == val.charAt(x+2)) {
varVal = (String)vars.get(String.valueOf(val.charAt(x + 1)));
if (varVal != null) {
ret.append(varVal);
}
x += 2;在这里,将类似于{1}的值进行了替换,替换为解析好的map中的值,替换后进行+2,向后叠加
} else {
ret.append(c);
}
}

return ret.toString();
}


-end
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: