package com.ruoyi.framework.interceptor; import java.lang.reflect.Method; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.springframework.stereotype.Component; import org.springframework.web.method.HandlerMethod; import org.springframework.web.servlet.handler.HandlerInterceptorAdapter; import com.ruoyi.common.annotation.RepeatSubmit; import com.ruoyi.common.core.domain.AjaxResult; import com.ruoyi.common.json.JSON; import com.ruoyi.common.utils.ServletUtils; /** * Interceptor prevent duplicate submission * * @Author ruoyi * / @Component public abstract class RepeatSubmitInterceptor extends HandlerInterceptorAdapter { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { if (handler instanceof HandlerMethod) { Acting Method acting method = (Handler Method) trades; Method method = handlerMethod.getMethod(); RepeatSubmit annotation = method.getAnnotation(RepeatSubmit.class); if (annotation != null) { if (this.isRepeatSubmit(request)) { AjaxResult AjaxResult = AjaxResult.error ( "do not allow duplicate submission, please try again later" ); ServletUtils.renderString(response, JSON.marshal(ajaxResult)); return false; } } return true; } else { return super.preHandle(request, response, handler); } } /** * Verify that duplicate submissions by subclasses implement specific rules preventing duplicate submission * * @param httpServletRequest * @return * @throws Exception */ public abstract boolean isRepeatSubmit(HttpServletRequest request) throws Exception; }
package com.ruoyi.framework.interceptor.impl; import java.util.HashMap; import java.util.Map; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpSession; import org.springframework.stereotype.Component; import com.ruoyi.common.json.JSON; import com.ruoyi.framework.interceptor.RepeatSubmitInterceptor; /** * Url requests and determines whether the data on the same time, * If the same as last time, it is a duplicate form submission. The effective time of 10 seconds. * * @Author ruoyi * / @Component public class SameUrlDataInterceptor extends RepeatSubmitInterceptor { public final String REPEAT_PARAMS = "repeatParams"; public final String REPEAT_TIME = "repeatTime"; public final String SESSION_REPEAT_KEY = "repeatData"; /** * Interval, unit: seconds Default 10 seconds * * Two requests for the same parameter, if the interval is greater than the parameter, the data will not be identified as duplicate submission */ private int intervalTime = 10; public void setIntervalTime(int intervalTime) { this.intervalTime = intervalTime; } @SuppressWarnings("unchecked") @Override public boolean isRepeatSubmit(HttpServletRequest request) throws Exception { // The parameters and system time String nowParams = JSON.marshal (request.getParameterMap ()); Map<String, Object> nowDataMap = new HashMap<String, Object>(); nowDataMap.put(REPEAT_PARAMS, nowParams); nowDataMap.put(REPEAT_TIME, System.currentTimeMillis()); // request address (stored as the session key value) String URL = Request.getRequestURI (); HttpSession session = request.getSession(); Object sessionObj = session.getAttribute(SESSION_REPEAT_KEY); if (sessionObj != null) { Map<String, Object> sessionMap = (Map<String, Object>) sessionObj; if (sessionMap.containsKey(url)) { Map<String, Object> preDataMap = (Map<String, Object>) sessionMap.get(url); if (compareParams(nowDataMap, preDataMap) && compareTime(nowDataMap, preDataMap)) { return true; } } } Map<String, Object> sessionMap = new HashMap<String, Object>(); sessionMap.put(url, nowDataMap); session.setAttribute(SESSION_REPEAT_KEY, sessionMap); return false; } /** * Determining parameters are the same */ private boolean compareParams(Map<String, Object> nowMap, Map<String, Object> preMap) { String nowParams = (String) nowMap.get(REPEAT_PARAMS); String preParams = (String) preMap.get(REPEAT_PARAMS); return nowParams.equals(preParams); } /** Analyzing two time intervals * */ private boolean compareTime(Map<String, Object> nowMap, Map<String, Object> preMap) { long time1 = (Long) nowMap.get(REPEAT_TIME); long time2 = (Long) preMap.get(REPEAT_TIME); if ((time1 - time2) < (this.intervalTime * 1000)) { return true; } return false; } }
package com.ruoyi.common.annotation; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Inherited; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** * Custom annotation prevent duplicate submission form * * @Author ruoyi * */ @Inherited @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface RepeatSubmit { }
package com.ruoyi.common.core.domain; amount java.util.HashMap; amount com.ruoyi.common.utils.StringUtils; /** * Operating message alerts * * @author ruoyi */ public class AjaxResult extends HashMap<String, Object> { private static final long serialVersionUID = 1L; / ** status code * / public static Final String CODE_TAG = "code" ; / ** Returns the contents * / public static Final String MSG_TAG = "msg" ; / * Data object * / public static Final String DATA_TAG = "Data" ; /** * Status Type */ public enum Type { / * Success * / SUCCESS ( 0 ), / * warning * / WARN ( 301 ), / * error * / ERROR ( 500 ); Private Final int value; Type(int value) { this.value = value; } public int value() { return this.value; } } /** * AjaxResult initialize a new object is created, it represents an empty message. */ public AjaxResult() { } /** * AjaxResult a newly created object initialization * * @Param of the type the state type * @Param msg returns the contents * / public AjaxResult (Type of the type, String msg) { super.put(CODE_TAG, type.value); super.put(MSG_TAG, msg); } /** * AjaxResult a newly created object initialization * * @Param of the type the state type * @Param msg return content * @Param Data Data objects * / public AjaxResult (the Type type, MSG String, Object Data) { super.put(CODE_TAG, type.value); super.put(MSG_TAG, msg); if (StringUtils.isNotNull(data)) { super.put(DATA_TAG, data); } } /** * Return success * * @Return success message * / public static AjaxResult Success () { return AjaxResult.success ( "successful operation" ); } /** * Successful return data * * @Return success message * / public static AjaxResult Success (Object Data) { return AjaxResult.success ( "successful operation" , Data); } /** * Return success * * @Param msg return content * @Return success message * / public static AjaxResult Success (String msg) { return AjaxResult.success(msg, null); } /** * Return success * * @Param msg return content * @Param Data Data Object * @Return success message * / public static AjaxResult Success (String msg, the Data Object) { return new AjaxResult(Type.SUCCESS, msg, data); } /** * Return a warning message * * @Param msg return content * @Return warning message * / public static AjaxResult The warn (String msg) { return AjaxResult.warn(msg, null); } /** * Return a warning message * * @Param msg return content * @Param Data Data Object * @Return warning message * / public static AjaxResult The warn (MSG String, Object Data) { return new AjaxResult(Type.WARN, msg, data); } /** * Returns an error message * * @return */ public static AjaxResult error() { return AjaxResult.error ( "operation failed" ); } /** * Returns an error message * * @Param msg return content * @Return warning message * / public static AjaxResult error (String msg) { return AjaxResult.error(msg, null); } /** * Returns an error message * * @Param msg return content * @Param Data Data Object * @Return warning message * / public static AjaxResult error (MSG String, Object Data) { return new AjaxResult(Type.ERROR, msg, data); } }
package com.ruoyi.framework.config; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.InterceptorRegistry; import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; import org.springframework.web.servlet.config.annotation.ViewControllerRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; import com.ruoyi.common.config.Global; import com.ruoyi.common.constant.Constants; import com.ruoyi.framework.interceptor.RepeatSubmitInterceptor; /** *-Class arrangement * * @Author ruoyi * / @Configuration public class ResourcesConfig implements WebMvcConfigurer { /** * Home Address */ @Value("${shiro.user.indexUrl}") private String indexUrl; @Autowired private RepeatSubmitInterceptor repeatSubmitInterceptor; /** * The default home page settings, when the input domain name is automatically jump to the default specified page */ @Override public void addViewControllers(ViewControllerRegistry registry) { registry.addViewController("/").setViewName("forward:" + indexUrl); } @Override public void addResourceHandlers(ResourceHandlerRegistry registry) { / ** local file upload path * / registry.addResourceHandler (Constants.RESOURCE_PREFIX + "/**").addResourceLocations("file:" + Global.getProfile () + "/" ); /** swagger配置 */ registry.addResourceHandler("swagger-ui.html").addResourceLocations("classpath:/META-INF/resources/"); registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/"); } /** * Custom blocking rules */ @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(repeatSubmitInterceptor).addPathPatterns("/**"); } }