由于struts2标签的性能不好,项目组决定不使用,但是如果用struts2自带的拦截器防止重复提交又必须struts标签,所以只好自定拦器实现,具体步骤如下:新建拦截器类:public class TokenAtionInterceptor extends AbstractInterceptor {public String intercept(ActionInvocation invocation) throws Exception {Map<String, Object> session =invocation.getInvocationContext().getSession();HttpServletRequest request = ServletActionContext.getRequest();String strGUID = RandomGUIDUtil.newGuid();//生成令牌String strRequestToken = (String)session.get("request_token");//取出会话中的令牌String strToken = request.getParameter("token"); //页面中的令牌if(strRequestToken != null&& !strRequestToken.equals(strToken)){ //重复提交,重置令牌session.put("request_token", strGUID);request.setAttribute("token", strGUID);return"invalidToken";}session.put("request_token", strGUID);request.setAttribute("token", strGUID);return invocation.invoke(); //否则正常运行}}建一个生成令牌的工具类:public class RandomGUIDUtil extends Object {/**日志管理类对象*/private Logger logger= Logger.getLogger(this.getClass().getName());public String valueBeforeMD5 = "";public String valueAfterMD5 = "";private static Random myRand;private static SecureRandom mySecureRand;private static String s_id;/** 静态块初始化*/static {mySecureRand = new SecureRandom();long secureInitializer = mySecureRand.nextLong();myRand = new Random(secureInitializer);try {s_id = InetAddress.getLocalHost().toString();} catch (UnknownHostException e) {System.out.println("构造带指定详细消息和嵌入异常!");}}public RandomGUIDUtil() throws Exception {getRandomGUID(false);}public RandomGUIDUtil(boolean secure) throws Exception { getRandomGUID(secure);}/** 随机生成GUID*/private void getRandomGUID(boolean secure) throws Exception { MessageDigest md5 = null;StringBuffer sbValueBeforeMD5 = new StringBuffer();try {md5 = MessageDigest.getInstance("MD5");} catch (NoSuchAlgorithmException e) {logger.error("初始化MD5出错!");throw new NoSuchAlgorithmException("初始化MD5出错!");}try {long time = System.currentTimeMillis();long rand = 0;if (secure) {rand = mySecureRand.nextLong();} else {rand = myRand.nextLong();}sbValueBeforeMD5.append(s_id);sbValueBeforeMD5.append(":");sbValueBeforeMD5.append(Long.toString(time));sbValueBeforeMD5.append(":");sbValueBeforeMD5.append(Long.toString(rand));valueBeforeMD5 = sbValueBeforeMD5.toString();md5.update(valueBeforeMD5.getBytes());byte[] array = md5.digest();StringBuffer sb = new StringBuffer();for (int j = 0; j < array.length; ++j) {int b = array[j] & 0xFF;if (b < 0x10) sb.append('0');sb.append(Integer.toHexString(b));}valueAfterMD5 = sb.toString();} catch (Exception e) {logger.error("获得MD5加密码出错!");throw new Exception("初始化MD5出错!");}}/***生成一个GUID串*@return GUID*@throws Exception*/public static String newGuid() throws Exception{ RandomGUIDUtil rdmGUID = new RandomGUIDUtil();return rdmGUID.toString();}/** 生成以主机串号、显卡串号、主板号,以保证唯一性的32位编码*/public String toString() {String raw = valueAfterMD5.toUpperCase();StringBuffer sb = new StringBuffer();sb.append(raw.substring(0, 8));sb.append(raw.substring(8, 12));sb.append(raw.substring(12, 16));sb.append(raw.substring(16, 20));sb.append(raw.substring(20));return sb.toString();}}在struts配置文件中对应的包下定义拦截器,注意顺序,package里元素必须按照一定的顺序排列。
这个顺序就是result-typesinterceptorsdefault-interceptor-refdefault-action-refdefault-class-refglobal-resultsglobal-exception-mappingsaction*(就是所有的action放到最后)<action>配置中加上名为” invalidToken”的result,就是拦截器中,重复提交跳转的路径如:<package name="template" extends="struts-default" namespace="/"> <interceptors><interceptor name="invocationToken"class="com.tydic.ppm.util.TokenAtionInterceptor"></interceptor> </interceptors><global-results><result name="error">/error.jsp</result><result name="openError">/openError.jsp</result> </global-results><action name="addTemplate" class="templateConfigAction"> <interceptor-ref name="defaultStack"></interceptor-ref><interceptor-ref name="invocationToken"></interceptor-ref><result name="input">/content/templateManage/configTemplate/templateBaseInfo.jsp </result><result name="success">/content/templateManage/configTemplate/templateBaseInfo.jsp </result><result name="invalidToken">/content/templateManage/configTemplate/templateBaseInfo.jsp </result></action></package>最后在页面上加一个隐藏域,用来保存页面令牌的,如:<input type="hidden" name="token" value="${token }"/><!-- 防止重复提交所用 -->经过上面的步骤就可以实现防止重复提交了,要注意拦截器在struts配置文件中定义的位置。