struts2默认拦截器之alias
?
? ? ? ? ? ? 在struts2的struts-default.xml中定义了一个name为alias拦截器,实现类是com.opensymphony.xwork2.interceptor.AliasInterceptor,它的作用是给参数起一个别名,可用于在action链中以不同的名字共享同一个参数,也可用于把http请求参数以不同的名字映射到action里。拦截器有一个参数:aliasesKey,可通过在struts.xml中定义该拦截器时指定其值,默认值是aliases,表示一个别名的map。
? ? ? ? ? ? 以下以实现在action链中username参数共享name参数为例:
?
<package name="test_Alias" extends="struts-default" namespace="/alias"> <action name="name" method="_name"> <result name="success" type="chain">username</result> </action> <action name="username" method="_username"> <param name="aliases">#{'name':'username'}</param> <result name="success">/jsp/alias/index.jsp</result> </action> </package>
?
? ? ? ? ?名称为username的action中有param标签,其中name属性值应该和alias拦截器参数aliasesKey的值一样,而param标签的值是一个定义map对象的OGNL表达式。
? ? ? ? ?com.opensymphony.xwork2.interceptor.AliasInterceptor的intercept方法代码如下
?
?
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 //获取action配置中的参数(就是param标签) final Map<String, String> parameters = config.getParams(); //查看参数列表中是否有aliasesKey对应的参数,如果没有,直接执行action if (parameters.containsKey(aliasesKey)) { //获取出aliasesKey值参数对象的值。 String aliasExpression = parameters.get(aliasesKey); ValueStack stack = ac.getValueStack(); //利用OGNL表达式,获取参数值对应的对象 Object obj = stack.findValue(aliasExpression); //如果获取到的对象为空,或者不是Map对象,将直接执行action 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; //遍历Map中的数据 for (Object o : aliases.entrySet()) { Map.Entry entry = (Map.Entry) o; String name = entry.getKey().toString(); String alias = (String) entry.getValue(); //从值栈中获取name(原参数名)对应的值 Object value = stack.findValue(name); if (null == value) { // workaround Map<String, Object> contextParameters = ActionContext.getContext().getParameters(); //如果获取到的值为null,则从request中获取参数值 if (null != contextParameters) { value = contextParameters.get(name); } } if (null != value) { try { //将值栈中alias对应的值设置为value 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 { LOG.debug("invalid alias expression:" + aliasesKey); } } return invocation.invoke(); }
? ? ? ? ?该拦截器已经被包含于默认拦截器栈中,无需再指定。
?
? ? ? ? ? ? 如果访问http://127.0.0.1:8080/test/alias/name?name=this_is_name或者http://127.0.0.1:8080/test/alias/username?name=this_is_name,结果页面中都会显示出username=this_is_name,表明alias拦截器已经将name参数的值赋给了username
? ? ? ? ? ? 注:上述例子的com.warning.interceptor.action.AliasAction1类中若存在属性username,而通过http://127.0.0.1:8080/test/alias/name?name=this_is_name访问,会导致结果页面的username为null,如果通过http://127.0.0.1:8080/test/alias/name?name=this_is_name&username=this_is_username?访问结果页面的username的值为this_is_username,而不是this_is_name,这是因为在默认拦截器栈中存在一个名为chain的拦截器(该拦截器是为result的type='chain'设计的),chain拦截器会将上一个action中的属性值复制到当前action中,而在默认拦截器栈中chain拦截器位于alias拦截器之后,因此导致名为username的action中的username属性值变成了上一个action中的username值。
?
版权所有,转载请表明出处:http://blogwarning.iteye.com/blog/1332201