AliasInterceptor拦截器是Struts2默认拦截器中的第二个拦截器。它的作用是:给参数起一个别名,可用于在action链中以不同的名字共享同一个参数,也可用于把http请求参数以不同的名字映射到action里。也许你现在还有点疑惑,我们后面会给个例子程序。
配置
<action name="Student" class="Action.StudentAction">
<param name="aliases">#{'t_id':'s_id'}</param>
<result>
/Student/StudentAddSuccess.jsp
</result>
</action>
你只要关注<param name="aliases">#{'t_id':'s_id'}</param>。这就是设置别名共享同一个参数值。t_id为原名,s_id为别名。
下面以实现在action链中以不同的名字共享同一个参数为例
struts.xml:
<action name="Student" class="Action.StudentAction">
<param name="aliases">#{'t_id':'s_id'}</param>
<result>
/Student/StudentAddSuccess.jsp
</result>
</action>
<action name="Teacher" class="Action.TeacherAction">
<result type="chain">Student</result>
</action>
public class StudentAction extends ActionSupport{
private int s_id;
public int getS_id() {
return s_id;
}
public void setS_id(int sId) {
s_id = sId;
}
public String Add(){
return SUCCESS;
}
public String Delete(){
return SUCCESS;
}
public String execute()
{
System.out.println(s_id);
return SUCCESS;
}
}
public class TeacherAction extends ActionSupport {
private int t_id;
public int getT_id() {
return t_id;
}
public void setT_id(int tId) {
t_id = tId;
}
public String execute()
{
return SUCCESS;
}
}
/Student/StudentAddSuccess.jsp:
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>
<%@taglib uri="/struts-tags" prefix="s" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<base href="<%=basePath%>">
</head>
<body>
Student Add Success!! <br>
<s:property value="s_id"/>
<s:debug></s:debug>
</body>
</html>
url:http://localhost:8080/structs2-HelloWorld01/Teacher.action?t_id=21
结果:控制台输出21,页面也是21,在值栈中同时存在t_id和s_id。这就是别名的作用,共享同一个参数值。
源码分析:
com.opensymphony.xwork2.interceptor.AliasInterceptor:
@Override public String intercept(ActionInvocation invocation) throws Exception {
ActionConfig config = invocation.getProxy().getConfig();
ActionContext ac = invocation.getInvocationContext();
Object action = invocation.getAction();
// get the action's parameters
final Map<String, String> parameters = config.getParams();
if (parameters.containsKey(aliasesKey)) {
String aliasExpression = parameters.get(aliasesKey);
ValueStack stack = ac.getValueStack();
Object obj = stack.findValue(aliasExpression);
if (obj != null && obj instanceof Map) {
//get secure stack
ValueStack newStack = valueStackFactory.createValueStack(stack);
boolean clearableStack = newStack instanceof ClearableValueStack;
if (clearableStack) {
//if the stack's context can be cleared, do that to prevent OGNL
//from having access to objects in the stack, see XW-641
((ClearableValueStack)newStack).clearContextValues();
Map<String, Object> context = newStack.getContext();
ReflectionContextState.setCreatingNullObjects(context, true);
ReflectionContextState.setDenyMethodExecution(context, true);
ReflectionContextState.setReportingConversionErrors(context, true);
//keep locale from original context
context.put(ActionContext.LOCALE, stack.getContext().get(ActionContext.LOCALE));
}
// override
Map aliases = (Map) obj;
for (Object o : aliases.entrySet()) {
Map.Entry entry = (Map.Entry) o;
String name = entry.getKey().toString();
String alias = (String) entry.getValue();
Object value = stack.findValue(name);
if (null == value) {
// workaround
Map<String, Object> contextParameters = ActionContext.getContext().getParameters();
if (null != contextParameters) {
value = contextParameters.get(name);
}
}
if (null != value) {
try {
newStack.setValue(alias, value);
} catch (RuntimeException e) {
if (devMode) {
String developerNotification = LocalizedTextUtil.findText(ParametersInterceptor.class, "devmode.notification", ActionContext.getContext().getLocale(), "Developer Notification:\n{0}", new Object[]{
"Unexpected Exception caught setting '" + entry.getKey() + "' on '" + action.getClass() + ": " + e.getMessage()
});
LOG.error(developerNotification);
if (action instanceof ValidationAware) {
((ValidationAware) action).addActionMessage(developerNotification);
}
}
}
}
}
if (clearableStack && (stack.getContext() != null) && (newStack.getContext() != null))
stack.getContext().put(ActionContext.CONVERSION_ERRORS, newStack.getContext().get(ActionContext.CONVERSION_ERRORS));
} else {
if (LOG.isDebugEnabled()) {
LOG.debug("invalid alias expression:" + aliasesKey);
}
}
}
return invocation.invoke();
}
拦截器有一个参数:aliasesKey,可通过在struts.xml中定义该拦截器时指定其值,默认值是aliases,表示一个别名的map。param标签的name属性值应该和拦截器参数aliasesKey的值一样,这样拦截器才知道你是否指定了action的别名map。
1:得到struts.xml中action的paramters。
2:看是否包含了aliasesKey,如果包含了,那么说明存在一个别名map。
3:迭代这个map中的每项,将该项的别名和值也写入值栈中。