天天看點

java 後端防止前端重複送出資料

//自定義一個防止重複送出的注解

package com.mingwen.common.SubmitMore;

import java.lang.annotation.Documented;

import java.lang.annotation.ElementType;

import java.lang.annotation.Retention;

import java.lang.annotation.RetentionPolicy;

import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME)

@Target(ElementType.METHOD)

@Documented

public @interface CannotSubmit{

    // 儲存重複送出标記 預設為需要儲存

    boolean save() default true;

}

//寫一個防止重複送出的攔截器

package com.mingwen.common.SubmitMore;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

import org.aspectj.lang.JoinPoint;

import org.aspectj.lang.annotation.AfterReturning;

import org.aspectj.lang.annotation.Aspect;

import org.aspectj.lang.annotation.Before;

import org.aspectj.lang.annotation.Pointcut;

import org.springframework.stereotype.Component;

import com.mingwen.common.exception.DuplicateSubmitException;

import cn.hutool.core.lang.UUID;

import lombok.extern.slf4j.Slf4j;

@Aspect

@Component

@Slf4j

public class DuplicateSubmitAspect {

    public static final String DUPLICATE_TOKEN_KEY = "duplicate_token_key";

    //掃描controller層

  @Pointcut("execution(public * com.mingwen.privatestock.controller..*(..))")

    public void webLog() {

    }

    @Before("webLog() && @annotation(submit)")

    public void before(final JoinPoint joinPoint, CannotSubmit submit) throws DuplicateSubmitException {

        if (submit != null) {

            Object[] args = joinPoint.getArgs();

            HttpServletRequest request = null;

            HttpServletResponse response = null;

            for (int i = 0; i < args.length; i++) {

                if (args[i] instanceof HttpServletRequest) {

                    request = (HttpServletRequest) args[i];

                }

                if (args[i] instanceof HttpServletResponse) {

                    response = (HttpServletResponse) args[i];

                }

            }

            boolean isSaveSession = submit.save();

            if (isSaveSession) {

                Object t = request.getSession().getAttribute(DUPLICATE_TOKEN_KEY);

                if (null == t) {

                    String uuid = UUID.randomUUID().toString();

                    request.getSession().setAttribute(DUPLICATE_TOKEN_KEY, uuid);

                } else {

                    throw new DuplicateSubmitException("請不要重複請求!");

                }

            }

        }

    }

    @AfterReturning("webLog() && @annotation(submit)")

    public void doAfterReturning(JoinPoint joinPoint, CannotSubmit submit) {

        // 處理完請求,傳回内容

        if (submit != null) {

            Object[] args = joinPoint.getArgs();

            HttpServletRequest request = null;

            for (int i = 0; i < args.length; i++) {

                if (args[i] instanceof HttpServletRequest) {

                    request = (HttpServletRequest) args[i];

                }

            }

            boolean isSaveSession = submit.save();

            if (isSaveSession) {

                Object t = request.getSession().getAttribute(DUPLICATE_TOKEN_KEY);

                if (null != t) {

                    request.getSession(false).removeAttribute(DUPLICATE_TOKEN_KEY);

                }

            }

        }

    }

}

//自定義一個表單重複送出異常

public class DuplicateSubmitException extends RuntimeException{

    public DuplicateSubmitException(String msg) {

        super(msg);

    }

}

//遇到重複送出的異常要将資訊傳回到前端顯示  攔截器抛的異常在controller是無法捕獲到的 是以這裡統一異常捕獲類 控制器增強

@ControllerAdvice

@ResponseBody

@Slf4j

public class ExceptionCatch  {

protected Map<String, Object> getResultObjectData(ResultCode result, Object pd, String msg) {

        Map<String, Object> resultData = new HashMap<>();

        resultData.put("code", result.getCode());

        resultData.put("message", result.getMsg());

        resultData.put("data", pd);

        return resultData;

    }

    // 捕獲CustomException此類異常

    @ExceptionHandler(DuplicateSubmitException.class)

    public Map<String, Object> customException(DuplicateSubmitException bmException) {

        bmException.printStackTrace();

        // 記錄日志

        log.error("catch exception:{}", "不可重複送出");

        return getResultObjectData(ResultCode.NO_SUBMIT, "", "不可重複送出");

    }

}

//測試controller

   @CannotSubmit

    @RequestMapping("/test")

    public Map<String, Object> test(HttpServletRequest request) {

     //往request 裡面存入每次請求的接口位址 這樣控制器能能拿到request裡面的請求位址 必須要的步驟

        request.getSession().setAttribute("request Url", request.getRequestURL());

        try {

       //休眠的目的是讓你自己在前端能有時間重複點選一下接口調用

            Thread.sleep(5000);

        } catch (InterruptedException e) {

            e.printStackTrace();

        }

        Map<String, Object> map = new HashMap<>();

        map.put("request Url", request.getRequestURL());

        return map;

    }

//效果

接口快速點選兩次

java 後端防止前端重複送出資料