struts2的token 防重复提交只能为整个包和action所用,但是这两场场景都不适用,用了之后有点被骗很恶心的感觉,对整个包进行防重复拦截的话,那必须所有页面都要写token,而且只能用form表单提交传,形同虚设,再说呗action所用,一个action里面不可能只写一个method方法的,一旦对action进行防重复拦截,里面所有的页面也全部要写上token,写到最后没有没办法只能一一个action对应一个token拦截对应一个方法,困扰如下:<action name="empListAction" class="com.sinosoft.frameDemo.web.actions.employee.EmpListAction">
 <result name="list">/jsp/employee/employeeList.jsp</result>
          <result name="editForward">/jsp/employee/employeeEdit.jsp</result>
          <result name="addForward">/jsp/employee/employeeAdd.jsp</result>
</action>
 
<action name="empAddAction" class="com.sinosoft.frameDemo.web.actions.employee.EmpAddAction">
<interceptor-ref name="commonInterceptor"/>
<interceptor-ref name="token" />
</action>
<action name="empEditAction" class="com.sinosoft.frameDemo.web.actions.employee.EmpEditAction">
<interceptor-ref name="commonInterceptor"/>
<interceptor-ref name="token" />
</action>
<action name="empDeleteAction" class="com.sinosoft.frameDemo.web.actions.employee.EmpDeleteAction">
<interceptor-ref name="commonInterceptor"/>
<interceptor-ref name="token" />
</action>这还不是最要恶心的,最恶心的是,我们的页面也必须逐一写上token标签,为了满足这么一个小小的token,配置竟复杂上天了,求助大家,有没有更好的设计或者办法,解决重复提交问题,不要js按钮置灰失效那种的!先拜谢....

解决方案 »

  1.   

    struts2的token 防重复提交只能为整个包和action所用?谁说的?托出去打。
    token可以只为某一个action所用。只需在需要的action中加上
    <interceptor-ref name="token" />
    <interceptor-ref name="defaultStack" />// 这个按具体情况定,是否需要或者加其他特别的拦截器然后在对应页面的加上token标签就是了
      

  2.   

    其实说白了,我想自己在程序里,获得struts2前页提交来的token,写个方法自己校验,这样就可以为action中各个不同的方法去定制防重复过滤了,这样远比全包拦截全action下所有方法拦截要灵活得多,目前只能想到这些,就是不知道怎么获取,另外还想多听听大家的意见...
      

  3.   

    1楼的兄弟,下午好,你的意思我懂,他确实能为action定制,但是不能为action中的方法定制,一旦配置了,action下所有的方法调用都会被拦截,这样的拦截会死人的
      

  4.   

    对方法的过滤拦截也是支持的。https://cwiki.apache.org/WW/interceptors.html
    你看看Method Filtering这部分,都有具体的方法。
    这些框架的运用是,他们的wiki是做好的文档
      

  5.   

    看了struts2的源码,问题终于解决了,现在把思路分享给大家,
    第一步:<s:token name="token"/>这个标签仍然借用,添加进需要进行重复提交校验的form表单
    第二步:在需要进行重复提交的action方法中,调用
    if(isRepeatValid()){   
                throw new SystemException("禁止刷新重复提交");
    },配置拦截器对自定义异常进行捕获,跳转至异常页面,struts.xml中不需要再进行重复提交拦截,完全摒弃原来的拦截思路,直接在方法中定制,也不必配置任何方法拦截,灵活可控!下面贴出全部源码:
    -----------------------------------------------------------------------------------
    public class EmpManagerAction extends BaseAction  {
    public String editEmployee() throws Exception {
    if(isRepeatValid()){   
                throw new SystemException("禁止刷新重复提交");
            }
    Thread.sleep(2000); 
    .....
    return "success";
    }
    ......
    }-----------------------------------------------------------------------------------public  class BaseAction extends ActionSupport implements ServletRequestAware, ServletResponseAware, ServletContextAware
    {
    private static final Logger LOG = LoggerFactory.getLogger(BaseAction.class);
    public Integer recTotal;//总记录数
    public Integer pageTotal;//总页数
    public List<Object> items;//数据
    public int pageno;//页码

    public HttpServletRequest request;//request请求对象
    public HttpSession session;//request请求对象
    public ServletContext servletContext;//servlet容器对象
    public HttpServletResponse response;//response相应对象

    public String getToken(){
    Map params = ActionContext.getContext().getParameters();
     String[] tokens = (String[]) params.get("token");
            if((tokens == null) || (tokens.length < 1)){
             LOG.warn("Could not find token mapped to token name ");
             throw new SystemException("没有找到token标记");
            }
            String token=tokens[0];
    return token;
    }

    /**
     * 判断是否重复提交 是返回true 否返回false
     * @return
     */
    @SuppressWarnings("unchecked")
    public boolean isRepeatValid(){
            String token=getToken();
    String stoken=(String)session.getAttribute("stoken");

    if(stoken!=null&&stoken.equals(token)){
    return true;
    }else{
    resetToken();
    return false;
    }

    }
    /**
     * 清空重置token令牌
     */
    public void resetToken(){
    String token=getToken();
    session.removeAttribute("stoken");
    session.setAttribute("stoken", token);
    }
    ........
    }---------------------------------------------------------------------------------<form action="empManagerAction!editEmployee.do" method="post" name="employee"  onsubmit="">
    <s:token />..........
    </form>------------------------------------------------------------------------------------希望大家多提点意见,看是否能有更高的改进,如果用户重复提交了,直接弹到了错误友好提示页面,可用户会大骂:老子提交了这么多次,总该有一次成功的吧?现在问题就是,用户第一次提交确实是处理成功的,后面的重复操作被挡了出去,我们怎么才能让用户知道他第一次提交的反馈结果呢??