JAVA防止表单重复提交(SpringMVC,ICache)

Spring MVC表单防重提交
本文介绍了一种基于Spring MVC的表单防重提交方案,通过UUID和缓存技术确保表单不会被重复提交,并提供了完整的代码实现。

一、抽取公共BaseController类
 

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.Date;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;


import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;


import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.ServletRequestDataBinder;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;


import com.cache.ICacheUtils;
import com.common.propertyeditor.DateConvertEditor;
import com.common.util.ValidateUtil;


public class BaseController {

    /**
     * 默认编码方式
     */
    protected final String defaultEncoding = "UTF-8";

    /**
     * 获取请求中的数据信息
     *
     * @return
     */
    @SuppressWarnings("unchecked")
    protected Map<String, String> getParameters(HttpServletRequest request) {
        Map<String, String> map = new HashMap<String, String>();
        Enumeration<String> enus = request.getParameterNames();
        while (enus.hasMoreElements()) {
            String key = enus.nextElement();
            String value = request.getParameter(key);
            map.put(key, value);
        }
        return map;
    }

    /**
     * 获取get请求中的数据信息
     *
     * @return
     */
    @SuppressWarnings("unchecked")
    protected Map<String, String> getParametersByGet(HttpServletRequest request) {
        Map<String, String> map = new HashMap<String, String>();
        Enumeration<String> enus = request.getParameterNames();
        while (enus.hasMoreElements()) {
            String key = enus.nextElement();
            String value = request.getParameter(key);
            try {
                if (ValidateUtil.isNotEmpty(value)) {
                    value = java.net.URLDecoder.decode(value, "UTF-8");
                }
            } catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
                e.printStackTrace();
            }
            map.put(key, value);
        }
        return map;
    }


    @InitBinder
    protected void initBinder(HttpServletRequest request,
                              ServletRequestDataBinder binder) throws Exception {
//对于需要转换为Date类型的属性,使用DateEditor进行处理  
        binder.registerCustomEditor(Date.class, new DateConvertEditor());
    }

    /**
     * 获取项目基础路径.
     *
     * @param req
     * @return
     */
    protected String getBasePath(HttpServletRequest req) {
        StringBuffer baseUrl = new StringBuffer();
        String scheme = req.getScheme();
        int port = req.getServerPort();


        baseUrl.append(scheme); // http, https
        baseUrl.append("://");
        baseUrl.append(req.getServerName());
        if ((scheme.equals("http") && port != 80) || (scheme.equals("https") && port != 443)) {
            baseUrl.append(':');
            baseUrl.append(req.getServerPort());
        }
        return baseUrl.toString();
    }

    /**
     *      * 向前台输出json字符串
     *      * @param jsonStr 要输出的json字符串
     *      * @throws IOException
     *      *
     *      * @author zzx
     *      
     */

    protected void printOutJson(HttpServletResponse response, String jsonStr) throws IOException {
        response.setCharacterEncoding(defaultEncoding);
        response.setContentType("text/json; charset=UTF-8");
        response.getWriter().print(jsonStr);

    }


    /**
     * 此处用于处理表单重复提交
     **/


    @Autowired
    private ICacheUtils iCacheUtils;


    protected void createToken() {
        String token = UUID.randomUUID().toString();
        getRequest().getSession(false).setAttribute("token", token);//客户端token
        iCacheUtils.setToken(token);//服务端token
    }


    protected void removeToken() {
        String clinetToken = getRequest().getParameter("token");
        iCacheUtils.removeToken(clinetToken);
    }


    protected boolean isRepeatSubmit() {
        List<String> serverToken = iCacheUtils.getToken();
        if (ValidateUtil.isEmpty(serverToken)) {
            return true;
        }
        String clinetToken = getRequest().getParameter("token");
        if (clinetToken == null) {
            return true;
        }
        if (!serverToken.contains(clinetToken)) {
            return true;
        }
        return false;
    }


    /**
     * 获取用户IP.
     *
     * @param req
     * @return
     */
    protected static String getIp(HttpServletRequest req) {
        String ip = req.getHeader("x-forwarded-for");
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = req.getHeader("Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = req.getHeader("WL-Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = req.getRemoteAddr();
        }
        ip = ip.equals("0:0:0:0:0:0:0:1") ? "127.0.0.1" : ip;
        return ip;
    }

    /**
     * 取得HttpRequest的简化函数.
     */
    protected HttpServletRequest getRequest() {
        return ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
    }

    protected HttpSession getSession() {
        return getRequest().getSession();
    }


    protected HttpSession getSession(boolean isNew) {
        return getRequest().getSession(isNew);

    }


    protected String getParameter(String name) {
        return getRequest().getParameter(name);
    }

    protected ResultDO<String> toErrorResult(BindingResult br) {
        return new ResultDO<String>(ResCode.COM_PARAMERROR.getResCode(), br.getAllErrors().get(0).getDefaultMessage().toString());
    }

    protected ResultDO<String> toErrorResult(String code, String dedsc) {
        return new ResultDO<String>(code, dedsc);
    }

    protected String toErrorResultString(BindingResult br) {
        ResultDO<String> dojo = toErrorResult(br);
        return JsonUtil.toJson(dojo);
    }

    protected String toErrorResultString(ResultDO<?> dojo) {
        return JsonUtil.toJson(dojo);
    }

    protected String toErrorResultString(String code, String dedsc) {
        ResultDO<String> dojo = toErrorResult(code, dedsc);
        return JsonUtil.toJson(dojo);
    }

    protected ResultDO<String> toErrorResult(ResCode coded) {
        return new ResultDO<String>(coded.getResCode(), coded.getResDescription());
    }

    protected <T> ResultDO<T> toSuccessResult(T br) {
        return new ResultDO<T>(br);
    }

    protected <T> ResultDO<T> toSuccessResult() {
        return new ResultDO<T>(true);
    }

    protected <T> ResultDO<T> toErrorResult(ResultDO<T> _sRd) {
        return new ResultDO<T>(_sRd.getErrorCode(), _sRd.getErrorMsg(), _sRd.getObj());
    }

}

 

二、创建ICacheUtils 接口

import java.util.List;

public interface ICacheUtils {
    public List<String> getToken();
    public List<String> setToken(String token);
    public List<String> removeToken(String token);
}

三、实现ICacheUtils 接口



/**
 *  * 基于ehcache的缓存工具类
 *  * @author admin
 *  *
 *  
 */
@SuppressWarnings({"rawtypes", "unchecked"})
public class EhCacheUtils implements ICacheUtils {


    public List<String> getToken() {
        String key = SYS_CACHE + "_getToken";
        List<String> tokenList = (List) get(SYS_CACHE, key);
        return tokenList;
    }

    public List<String> setToken(String token) {
        String key = SYS_CACHE + "_getToken";
        List<String> tokenList = (List) get(SYS_CACHE, key);
        if (tokenList == null) {
            tokenList = new ArrayList<String>();
        }
        tokenList.add(token);
        put(SYS_CACHE, key, tokenList);
        return tokenList;
    }

    public List<String> removeToken(String token) {
        String key = SYS_CACHE + "_getToken";
        List<String> tokenList = (List) get(SYS_CACHE, key);
        if (tokenList == null) {
            tokenList = new ArrayList<String>();
        }
        tokenList.remove(token);
        put(SYS_CACHE, key, tokenList);
        return tokenList;
    }


}

四、控制器继承基础BaseController

@Controller
@RequestMapping("/test")

public class TestController extends BaseController {

    @RequestMapping(value = "/toFormPage")
    public String toFormPage(ModelMap map) {
        createToken();
        //此处写你自己的代码
        return "/FormPage";
    }

    @RequestMapping(value = "/doSaveTest", method = RequestMethod.POST)
    public @ResponseBody
    ResultDO<?> doSaveTest(HttpServletRequest request) {
        /**判断是否重复提交**/
        if (isRepeatSubmit()) {
            return toErrorResult(new ResultDO<Boolean>(ResCode.COM_EXCEPTION.getResCode(), "表单已提交成功"));
        }
        try {
            /**此处写调用service层代码**/
            /**如果成功则:**/
            removeToken();
        } catch (Exception e) {

        }
    }

五、jsp页面Form表单

<form action="${pageContext.request.contextPath}/test/doSaveTest" method="post" id="myForm">

            <input type="hidden" value="${token}" name="token" />

                 .......其他表单数据

            <input type="submit"/>

</form>

 

 

六、一些工具类

1、JsonUtil 

import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Set;


import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;


/**
 *  * this is a common Class work with Json
 *  * 
 *  * @author ylzhang20
 *  
 */
public abstract class JsonUtil {


    /**
     * Encapsulate <code>Object</code> to a JSON String
     *  
     *
     * @param o             Oject
     * @return JSON JSON String
     */
    @SuppressWarnings({"unchecked", "rawtypes"})
    public static String toJson(final Object o) {
        if (o == null) {
            return "null";
        }
        if (o instanceof String) // String
        {
            return string2Json((String) o);
        }
        if (o instanceof Boolean) // Boolean
        {
            return boolean2Json((Boolean) o);
        }
        if (o instanceof Number) // Number
        {
            return number2Json((Number) o);
        }
        if (o instanceof Map) // Map
        {
            return map2Json((Map<String, Object>) o);
        }
        if (o instanceof Collection) // List Set
        {
            return collection2Json((Collection) o);
        }
        if (o instanceof Object[]) // List of object
        {
            return array2Json((Object[]) o);
        }


        if (o instanceof int[])// int type
        {
            return intArray2Json((int[]) o);
        }
        if (o instanceof boolean[])// boolean type
        {
            return booleanArray2Json((boolean[]) o);
        }
        if (o instanceof long[]) {
            return longArray2Json((long[]) o);
        }
        if (o instanceof float[]) {
            return floatArray2Json((float[]) o);
        }
        if (o instanceof double[]) {
            return doubleArray2Json((double[]) o);
        }
        if (o instanceof short[]) {
            return shortArray2Json((short[]) o);
        }
        if (o instanceof byte[]) {
            return byteArray2Json((byte[]) o);
        }
        if (o instanceof Object) {
            return object2Json(o);
        }


        throw new RuntimeException("No support type Object:"
                + o.getClass().getName());
    }


    /**
     * Change a String to an JSON String
     *  
     *
     * @param s             a String
     * @return a JSON String
     */
    public static String string2Json(final String s) {
        final StringBuilder sb = new StringBuilder(s.length() + 20);
        sb.append('\"');
        for (int i = 0; i < s.length(); i++) {
            final char c = s.charAt(i);
            switch (c) {
                case '\"':
                    sb.append("\\\"");
                    break;
                case '\\':
                    sb.append("\\\\");
                    break;
                case '/':
                    sb.append("\\/");
                    break;
                case '\b':
                    sb.append("\\b");
                    break;
                case '\f':
                    sb.append("\\f");
                    break;
                case '\n':
                    sb.append("\\n");
                    break;
                case '\r':
                    sb.append("\\r");
                    break;
                case '\t':
                    sb.append("\\t");
                    break;
                default:
                    sb.append(c);
            }
        }
        sb.append('\"');
        return sb.toString();
    }


    /**
     * Change a Number to JSON
     *  
     *
     * @param number             Number
     * @return a JSON String
     */
    public static String number2Json(final Number number) {
        return number.toString();
    }


    /**
     * Change Boolean to JSON
     *  
     *
     * @param bool             Boolean
     * @return a JSON String
     */
    public static String boolean2Json(final Boolean bool) {
        return bool.toString();
    }


    /**
     * Change Collection to JSON (List,Set)
     *  
     *
     * @param c             a Collection Object
     * @return a JSON String
     */
    public static String collection2Json(final Collection<Object> c) {
        final Object[] arrObj = c.toArray();
        return toJson(arrObj);
    }

    /**
     * 把list数据转换的json字符串
     *  
     *
     * @param labels list数据
     * @return 返回转换后的json字符串
     * @author xfzhou
     */
    public static String collection2Json(final Object obj) {
        if (obj == null) return null;
        Gson gson = new Gson();

        return gson.toJson(obj);
    }

    /**
     * 把json数据字符串,转换成list对象
     *  
     *
     * @param str json数据字符串
     * @return 返回list对象,元素是map对象
     * @author xfzhou
     */
    public static List<String> json2List(String str) {
        if (ValidateUtil.isEmpty(str)) return null;

        Gson jsonObj = new Gson();
        Type listType = new TypeToken<List<String>>() {
        }.getType();

        return jsonObj.fromJson(str, listType);
    }


    /**
     * Change Map<String, Object> to JSON
     *  
     *
     * @param map             a Map
     * @return a JSON String
     */
    public static String map2Json(final Map<String, Object> map) {
        if (map.isEmpty()) {
            return "{}";
        }
        final StringBuilder sb = new StringBuilder(map.size() << 4);
        sb.append('{');
        final Set<String> keys = map.keySet();
        for (final String key : keys) {
            final Object value = map.get(key);
            sb.append('\"');
            sb.append(key); // Can not be special character
            sb.append('\"');
            sb.append(':');
            sb.append(toJson(value));
            sb.append(',');
        }
        // add last "}"
        sb.setCharAt(sb.length() - 1, '}');
        return sb.toString();
    }


    /**
     * Change array to JSON
     *  
     *
     * @param array             an Object array
     * @return a JSON String
     */
    public static String array2Json(final Object[] array) {
        if (array.length == 0) {
            return "[]";
        }
        final StringBuilder sb = new StringBuilder(array.length << 4); // the
        // power
        // of
        // four
        sb.append('[');
        for (final Object o : array) {
            sb.append(toJson(o));
            sb.append(',');
        }
        // change last "," to "]"
        sb.setCharAt(sb.length() - 1, ']');
        return sb.toString();
    }


    /**
     * Change int array to JSON
     *  
     *
     * @param array             a int array
     * @return a JSON String
     */
    public static String intArray2Json(final int[] array) {
        if (array.length == 0) {
            return "[]";
        }
        final StringBuilder sb = new StringBuilder(array.length << 4);
        sb.append('[');
        for (final int o : array) {
            sb.append(Integer.toString(o));
            sb.append(',');
        }
        // set last ',' to ']':
        sb.setCharAt(sb.length() - 1, ']');
        return sb.toString();
    }


    /**
     * Change long array to JSON
     *  
     *
     * @param array             a long array
     * @return a JSON String
     */
    public static String longArray2Json(final long[] array) {
        if (array.length == 0) {
            return "[]";
        }
        final StringBuilder sb = new StringBuilder(array.length << 4);
        sb.append('[');
        for (final long o : array) {
            sb.append(Long.toString(o));
            sb.append(',');
        }
        // set last ',' to ']':
        sb.setCharAt(sb.length() - 1, ']');
        return sb.toString();
    }


    /**
     * Change boolean array to JSON
     *  
     *
     * @param array             an boolean array
     * @return a JSON String
     */
    public static String booleanArray2Json(final boolean[] array) {
        if (array.length == 0) {
            return "[]";
        }
        final StringBuilder sb = new StringBuilder(array.length << 4);
        sb.append('[');
        for (final boolean o : array) {
            sb.append(Boolean.toString(o));
            sb.append(',');
        }
        // set last ',' to ']':
        sb.setCharAt(sb.length() - 1, ']');
        return sb.toString();
    }


    /**
     * Change float array to JSON
     *  
     *
     * @param array             a float array
     * @return a JSON String
     */
    public static String floatArray2Json(final float[] array) {
        if (array.length == 0) {
            return "[]";
        }
        final StringBuilder sb = new StringBuilder(array.length << 4);
        sb.append('[');
        for (final float o : array) {
            sb.append(Float.toString(o));
            sb.append(',');
        }
// set last ',' to ']':
        sb.setCharAt(sb.length() - 1, ']');
        return sb.toString();
    }


    /**
     * Change double array to JSON
     *  
     *
     * @param array             an double array
     * @return a JSON String
     */
    public static String doubleArray2Json(final double[] array) {
        if (array.length == 0) {
            return "[]";
        }
        final StringBuilder sb = new StringBuilder(array.length << 4);
        sb.append('[');
        for (final double o : array) {
            sb.append(Double.toString(o));
            sb.append(',');
        }
// set last ',' to ']':
        sb.setCharAt(sb.length() - 1, ']');
        return sb.toString();
    }


    public static String shortArray2Json(final short[] array) {
        if (array.length == 0) {
            return "[]";
        }
        final StringBuilder sb = new StringBuilder(array.length << 4);
        sb.append('[');
        for (final short o : array) {
            sb.append(Short.toString(o));
            sb.append(',');
        }
        // set last ',' to ']':
        sb.setCharAt(sb.length() - 1, ']');
        return sb.toString();
    }


    /**
     * Change byte array to JSON
     *  
     *
     * @param array             an byte array
     * @return a JSON String
     */
    public static String byteArray2Json(final byte[] array) {
        if (array.length == 0) {
            return "[]";
        }
        final StringBuilder sb = new StringBuilder(array.length << 4);
        sb.append('[');
        for (final byte o : array) {
            sb.append(Byte.toString(o));
            sb.append(',');
        }
        // set last ',' to ']':
        sb.setCharAt(sb.length() - 1, ']');
        return sb.toString();
    }


    /**
     * Change an Object to JSON
     *  
     *
     * @param bean             Object to json
     * @return a JSON String
     */
    public static String object2Json(final Object bean) {
        // check null
        if (bean == null) {
            return "{}";
        }
        final Method[] methods = bean.getClass().getMethods();
        final StringBuilder sb = new StringBuilder(methods.length << 4);
        // the power of four
        sb.append('{');


        for (final Method method : methods) {
            try {
                final String name = method.getName();
                String key = "";
                if (name.startsWith("get")) {
                    key = name.substring(3);


                    final String[] arrs = {"Class"};// prevention of endless
                    // loop
                    boolean bl = false;
                    for (final String s : arrs) {
                        if (s.equals(key)) {
                            bl = true;
                            continue;
                        }
                    }
                    if (bl) {
                        continue; // prevention of endless loop
                    }
                } else if (name.startsWith("is")) {
                    key = name.substring(2);
                }
                if (key.length() > 0 && Character.isUpperCase(key.charAt(0))
                        && method.getParameterTypes().length == 0) {
                    if (key.length() == 1) {
                        key = key.toLowerCase();
                    } else if (!Character.isUpperCase(key.charAt(1))) {
                        key = key.substring(0, 1).toLowerCase()
                                + key.substring(1);
                    }
                    final Object elementObj = method.invoke(bean);


                    // System.out.println("###" + key + ":" +
                    // elementObj.toString());


                    sb.append('\"');
                    sb.append(key); // can't content special character
                    sb.append('\"');
                    sb.append(':');
                    sb.append(toJson(elementObj));
                    sb.append(',');
                }
            } catch (final Exception e) {
                // e.getMessage();
                throw new RuntimeException("Packing Object Exception��"
                        + e.getMessage(), e);
            }
        }
        if (sb.length() == 1) {
            return bean.toString();
        } else {
            sb.setCharAt(sb.length() - 1, '}');
            return sb.toString();
        }
    }


    /**
     * Change an Object to JSON,the jsonString has object name.
     *  
     *
     * @param array             an int array
     * @return a JSON String
     */
    public static String object2JsonWithName(final Object bean) {
        StringBuffer objectContent = new StringBuffer(object2Json(bean));
        return objectContent.append(bean.getClass().getSimpleName()).toString();
    }

    /**
     * 把json数据字符串,转换成map对象
     *  
     *
     * @param jsonData son数据字符串
     * @return 返回map对象
     * @author xfzhou
     */
    public static Map<String, String> json2Map(String jsonData) {
        if (ValidateUtil.isEmpty(jsonData)) return null;

        Gson jsonObj = new Gson();
        Type mapType = new TypeToken<Map<String, String>>() {
        }.getType();

        return jsonObj.fromJson(jsonData, mapType);
    }


    /**
     * 把json数据字符串,转换成list对象
     *  
     *
     * @param fileInfoList json数据字符串
     * @return 返回list对象,元素是map对象
     * @author xfzhou
     */
    public static List<Map<String, String>> json2MapList(String fileInfoList) {
        if (ValidateUtil.isEmpty(fileInfoList)) return null;

        Gson jsonObj = new Gson();
        Type listType = new TypeToken<List<Map<String, String>>>() {
        }.getType();

        return jsonObj.fromJson(fileInfoList, listType);
    }

}

2、返回体


import java.io.Serializable;


/**
 *  * 业务操作响应Bean.
 *  * @param <T>
 *  
 */
public class ResultDO<T> extends BaseVo implements Serializable {
    private static final long serialVersionUID = -2042618546543630713L;
    // 业务操作是否成功
    private boolean isOK = true;
    // 返回值,可以是任何类型
    private T obj;
    // 响应错误码
    private String errorMsg;
    // 响应码
    private String errorCode;


    public ResultDO() {
    }

    public ResultDO(boolean _isOK) {
        this.isOK = _isOK;
    }

    public ResultDO(T result) {
        this.isOK = true;
        this.obj = result;
    }


    public ResultDO(String errorCode, String errorMsg) {
        this.isOK = false;
        this.errorCode = errorCode;
        this.errorMsg = errorMsg;
    }


    public ResultDO(String errorCode, String errorMsg, T result) {
        this.isOK = false;
        this.errorCode = errorCode;
        this.errorMsg = errorMsg;
        this.obj = result;
    }


    public String getErrorCode() {
        return errorCode;
    }


    public void setErrorCode(String errorCode) {
        this.errorCode = errorCode;
    }


    public boolean isOK() {
        return isOK;
    }


    public ResultDO<T> setOK(boolean isOK) {
        this.isOK = isOK;
        return this;
    }


    public T getObj() {
        return obj;
    }


    public ResultDO<T> setObj(T obj) {
        this.obj = obj;
        return this;
    }


    public String getErrorMsg() {
        return errorMsg;
    }


    public ResultDO<T> setErrorMsg(String errorMsg) {
        this.isOK = false;
        this.errorMsg = errorMsg;
        return this;
    }

}

 

3、基础实体类

import java.io.Serializable;

public abstract class BaseVo implements Serializable {

    /**
     * 
     */
    private static final long serialVersionUID = 1169083819505759557L;
    
    @Override
    public String toString(){
        return JsonUtil.toJson(this);
    }

}

推荐一个公众号

号主为一线大厂架构师,优快云博客专家,博客访问量突破一千万。主要分享Java、golang架构,源码,分布式,高并发等技术,用大厂程序员的视角来探讨技术进阶、面试指南、职业规划等。15W技术人的选择!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

张音乐

请我喝杯咖啡吧

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值