Struts 2.1--随便写写
2010-01-24 03:30
141 查看
学习Struts 2.1有一阵了,本以为差不多了,今天拿起来练了练,几个问题却让我琢磨了好久。心血来潮写一写,给自己提个醒,也跟还没注意的朋友分享下,希望能帮你们在学习和工作中节省点时间。
1. parameters
在页面中可以使用Ognl表达式#parameters访问请求参数,Action可以实现ParameterAware接口让框架注入该Map,同样,也可以使用ActionContext.getContext().getParameters()得到请求参数Map。
今天尝试了一下,在Action中使用ActionContext.getContext().getParameters().put("test","hehe");
在页面中使用<s:property value="#parameters.test">,没有任何输出。
尝试实现ParameterAware接口,使用框架注入Map的,仍然没有。
折腾了3个小时,结论如下:
框架构造这一堆Map时(request,session,parameters,application等)有类似如下的代码:
xxx.put(ActionContext.PARAMETERS,new HashMap(parameterMap));
xxx.put("parameters",parameterMap);
对实现了ParameterAware接口的Action执行如下代码
if(action instanceof ParameterAware){
((ParameterAware)action).setParameters(context.getParameters());
}
ActionContext.getContext().getParameters()和上面的getParameters()方法如下
public Map<String,String[]> getParameters(){
return (Map<String,String[]>)get(PARAMETERS);
}
Ognl表达式#parameter访问与Map和ActionContext.getContext().getParameters()和接口注入的Map根本就不是一个对象,但要注意的是,以ActionContext.PARAMETERS为键的Map是由以"parameters"为键的Map构造的
仔细想了下,估计这种设计,为了保全原始请求参数,以至于在Action中,无论用户如何操作,都不会破坏原始请求参数Map 的结构。
2. 在使用token拦截器避免重复提交表单时,自定义错误信息。
这个问题可能是我低能了,都配置好后可以顺利的避免表单重复提交(<s:token />不能带name属性,否则会有Ognl异常,不知道为什么),只是错误信息一直是“The form has already been processed or no token was supplied, please try again.” 国际化信息是陪在Action同包里的,跟Action同名,就算加上“struts.messges.invalid.token=请不要重复提交”,也是无济于事。
解决:classes目录下建struts-message_zh_CN.properties和struts-message_en.properties两个文件,以struts.messges.invalid.token为键写上相应的中英文信息。在struts.xml中配置<constant name="struts.custom.i18n.resources" value="struts-message">实现国际化(文件名可以任意起),还可以把struts2核心文件中的struts-messages.properties里的内容全都拷过来,把一些日志信息也换成中文的,看着舒服,呵呵。
3. 控制文件下载
虽然可以在struts.xml中配置,但有时候也需要跟据情况改变下载文件的MIME类型,文件名等。
本来可以用拦截器,在下载前动态改变保存在ResultConfig中的配置信息
Map<String,ResultConfig> resultMap = invocation.getProxy().getConfig().getResults();
(如果使用注解拦截的话,invocation可以通过ActionContext.getContext().getActionInvocation()得到)
ResultConfig config = resultMap.get(invocation.getResultCode());
config.addParam()。。。
结果发现Struts 2.0中本有addParam方法,可是Struts 2.1中并没有
换了个方式,config.getParams.put(),结果更惨,unknown location异常
解决:换个方式绕着走,Action中加这样的方法
@BeforeResult
public void download(){
type = XXXXX
}
public String getContentType(){
return type; // type是Action中一个属性,在注解为@beforeResult的方法中设置其值,可达到动态修改MIME类型的效果
}
public String getFilename(){ // 这个方法名得注意一下,似乎不能为getContentDisposition,好像有冲突
try {
return new String("xxx".getBytes(),"ISO8859-1"); // 这样写是为了支持可以使用中文的文件名
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
return "xxx";
}
}
struts.xml文件中
......
<param name="contentType">${contentType}</param>
<param name="contentDisposition">attachment;filename="${filename}"</param>
......
这样就OK了,道理很简单,表达式都使用getter方法,忽忽!
4. FreeMarker中使用radio,select,doubleselect等带有那个list属性的一些标签
Struts 2对FreeMarker确实支持的很好,不过这几个标签让人摸不着门。在Freemarker模板文件中
<@s.radio name="xx" value="xx" list="#{'xx':'xx', 'xxx':'xxx'}" />
list属性这样取值是不行的,但如果用FreeMarker语法list={'xx':'xx', 'xxx':'xxx'},页面的输出绝对不是你想要的,是HashAdapter地址
确实想不通这是什么道理,不过除了去改Struts 2的模板,还有其他办法。
在Struts 2模板中,radio是这样处理的
<#if parameters.listKey??>
<#assign itemKey = stack.findValue(parameters.listKey)/>
<#else>
<#assign itemKey = stack.findValue('top')/>
</#if>
<#assign itemKeyStr = itemKey.toString() />
<#if parameters.listValue??>
<#assign itemValue = stack.findString(parameters.listValue)/>
<#else>
<#assign itemValue = stack.findString('top')/>
</#if>
这样就很明显了,页面会输出HashAdapter的地址也就正常了,因为解析标签的时候top就是那个对象
解决:给它加上listKey和listValue就好了,stack.findValue会查找listKey的值,listValue同理,这样就可以写成
<@s.radio name="xx" value="xx" list={'name':'zhangsan', 'age':'18'} listKey="top.key" listValue="top.value" />
虽说有点牛头不对马嘴,语法混用,但毕竟还是解决问题了,粗糙点而已。
解析这个标签时,栈顶对象就是那个list的值,而top.key会先被计算为name(第一次迭代,第二次迭代是age)
的确很乱,不过只要区分好FreeMarker语法和Ognl表达式就好了。比如说:输出国际化信息
<@s.property value="getText('name')" />
${action.getText('name')}
1. parameters
在页面中可以使用Ognl表达式#parameters访问请求参数,Action可以实现ParameterAware接口让框架注入该Map,同样,也可以使用ActionContext.getContext().getParameters()得到请求参数Map。
今天尝试了一下,在Action中使用ActionContext.getContext().getParameters().put("test","hehe");
在页面中使用<s:property value="#parameters.test">,没有任何输出。
尝试实现ParameterAware接口,使用框架注入Map的,仍然没有。
折腾了3个小时,结论如下:
框架构造这一堆Map时(request,session,parameters,application等)有类似如下的代码:
xxx.put(ActionContext.PARAMETERS,new HashMap(parameterMap));
xxx.put("parameters",parameterMap);
对实现了ParameterAware接口的Action执行如下代码
if(action instanceof ParameterAware){
((ParameterAware)action).setParameters(context.getParameters());
}
ActionContext.getContext().getParameters()和上面的getParameters()方法如下
public Map<String,String[]> getParameters(){
return (Map<String,String[]>)get(PARAMETERS);
}
Ognl表达式#parameter访问与Map和ActionContext.getContext().getParameters()和接口注入的Map根本就不是一个对象,但要注意的是,以ActionContext.PARAMETERS为键的Map是由以"parameters"为键的Map构造的
仔细想了下,估计这种设计,为了保全原始请求参数,以至于在Action中,无论用户如何操作,都不会破坏原始请求参数Map 的结构。
2. 在使用token拦截器避免重复提交表单时,自定义错误信息。
这个问题可能是我低能了,都配置好后可以顺利的避免表单重复提交(<s:token />不能带name属性,否则会有Ognl异常,不知道为什么),只是错误信息一直是“The form has already been processed or no token was supplied, please try again.” 国际化信息是陪在Action同包里的,跟Action同名,就算加上“struts.messges.invalid.token=请不要重复提交”,也是无济于事。
解决:classes目录下建struts-message_zh_CN.properties和struts-message_en.properties两个文件,以struts.messges.invalid.token为键写上相应的中英文信息。在struts.xml中配置<constant name="struts.custom.i18n.resources" value="struts-message">实现国际化(文件名可以任意起),还可以把struts2核心文件中的struts-messages.properties里的内容全都拷过来,把一些日志信息也换成中文的,看着舒服,呵呵。
3. 控制文件下载
虽然可以在struts.xml中配置,但有时候也需要跟据情况改变下载文件的MIME类型,文件名等。
本来可以用拦截器,在下载前动态改变保存在ResultConfig中的配置信息
Map<String,ResultConfig> resultMap = invocation.getProxy().getConfig().getResults();
(如果使用注解拦截的话,invocation可以通过ActionContext.getContext().getActionInvocation()得到)
ResultConfig config = resultMap.get(invocation.getResultCode());
config.addParam()。。。
结果发现Struts 2.0中本有addParam方法,可是Struts 2.1中并没有
换了个方式,config.getParams.put(),结果更惨,unknown location异常
解决:换个方式绕着走,Action中加这样的方法
@BeforeResult
public void download(){
type = XXXXX
}
public String getContentType(){
return type; // type是Action中一个属性,在注解为@beforeResult的方法中设置其值,可达到动态修改MIME类型的效果
}
public String getFilename(){ // 这个方法名得注意一下,似乎不能为getContentDisposition,好像有冲突
try {
return new String("xxx".getBytes(),"ISO8859-1"); // 这样写是为了支持可以使用中文的文件名
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
return "xxx";
}
}
struts.xml文件中
......
<param name="contentType">${contentType}</param>
<param name="contentDisposition">attachment;filename="${filename}"</param>
......
这样就OK了,道理很简单,表达式都使用getter方法,忽忽!
4. FreeMarker中使用radio,select,doubleselect等带有那个list属性的一些标签
Struts 2对FreeMarker确实支持的很好,不过这几个标签让人摸不着门。在Freemarker模板文件中
<@s.radio name="xx" value="xx" list="#{'xx':'xx', 'xxx':'xxx'}" />
list属性这样取值是不行的,但如果用FreeMarker语法list={'xx':'xx', 'xxx':'xxx'},页面的输出绝对不是你想要的,是HashAdapter地址
确实想不通这是什么道理,不过除了去改Struts 2的模板,还有其他办法。
在Struts 2模板中,radio是这样处理的
<#if parameters.listKey??>
<#assign itemKey = stack.findValue(parameters.listKey)/>
<#else>
<#assign itemKey = stack.findValue('top')/>
</#if>
<#assign itemKeyStr = itemKey.toString() />
<#if parameters.listValue??>
<#assign itemValue = stack.findString(parameters.listValue)/>
<#else>
<#assign itemValue = stack.findString('top')/>
</#if>
这样就很明显了,页面会输出HashAdapter的地址也就正常了,因为解析标签的时候top就是那个对象
解决:给它加上listKey和listValue就好了,stack.findValue会查找listKey的值,listValue同理,这样就可以写成
<@s.radio name="xx" value="xx" list={'name':'zhangsan', 'age':'18'} listKey="top.key" listValue="top.value" />
虽说有点牛头不对马嘴,语法混用,但毕竟还是解决问题了,粗糙点而已。
解析这个标签时,栈顶对象就是那个list的值,而top.key会先被计算为name(第一次迭代,第二次迭代是age)
的确很乱,不过只要区分好FreeMarker语法和Ognl表达式就好了。比如说:输出国际化信息
<@s.property value="getText('name')" />
${action.getText('name')}
相关文章推荐
- 随便写写
- 随便写写
- MyEclipse搭建SSH框架 Struts2.1+Spring3.0+hibernate3.3
- struts2.1、struts2.3 getJson区别
- struts2.1或2.2不能识别的部分标签
- 随便写写
- MyEclipse10搭建SSH框架 Struts2.1+Spring3.0+hibernate3.3
- struts2.1 datetimepicker日期控件的使用
- 大学杂念集 随便写写
- struts2.1之后的Junit plugin使用
- Struts2.1.x 安装及配置
- 第一次,随便写写
- 随便写写
- MyEclipse-10.0下Struts2.1+Spring3.0+Hibernate3.3整合过程
- Struts2.1笔记
- 随便写写
- 随便写写,放松心情
- 随便写写
- 光模块光路与电路设计辅助工具代码(随便写写玩下,能够提高您能对光模块的理解,不过有待进一步补充)
- 最近看了一些东西,随便写写JFinal的一些东西吧