Struts 2.1--随便写写

    学习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')}

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值