ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

java开发中 防止刷新后重复提交

2022-09-14 15:30:27  阅读:248  来源: 互联网

标签:java String 提交 org request key 刷新 import



对于重复提交的问题 主要涉及到时 幂等 问题,那么先说一下什么是幂等。
幂等:F(F(X)) = F(X)多次运算结果一致;简单点说就是对于完全相同的操作,操作一次与操作多次的结果是一样的。
在开发中,我们都会涉及到对数据库操作。例如:

select 查询天然幂等
delete 删除也是幂等,删除同一个多次效果一样
update 直接更新某个值(如:状态 字段固定值),幂等
update 更新累加操作(如:商品数量 字段),非幂等
(可以采用简单的乐观锁和悲观锁 个人更喜欢乐观锁。
乐观锁:数据库表加version字段的方式;
悲观锁:用了 select…for update 的方式,* 要使用悲观锁,我们必须关闭mysql数据库的自动提交属性。
这种在大数据量和高并发下效率依赖数据库硬件能力,可针对并发量不高的非核心业务;)
insert 非幂等操作,每次新增一条 重点 (数据库简单方案:可采取数据库唯一索引方式;这种在大数据量和高并发下效率依赖数据库硬件能力,可针对并发量不高的非核心业务;)

代码实现

google cache 代码实现 注解方式 Single lock

pom.xml 引入

<dependency>
            <groupId>com.google.guava</groupId>
            <artifactId>guava</artifactId>
            <version>21.0</version>
        </dependency>

 

配置文件 .yml

resubmit:
  local:
    timeOut: 60

实现代码

import java.lang.annotation.*;

@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
public @interface LocalLock {
    String  key() default "";
}
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import com.his.sale.sybgl.common.exception.ResultUtil;
import com.hx.common.model.Result;
import lombok.Data;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * @author: xx
 * @description: 单机放重复提交
 */
@Data
@Aspect
@Configuration
public class LocalLockMethodInterceptor {

    @Value("${spring.profiles.active}")
    private String springProfilesActive;
    @Value("${spring.application.name}")
    private String springApplicationName;


    private static String expireTimeSecond = "5";

    @Value("${resubmit:local:timeOut}")
    public void setExpireTimeSecond(String expireTimeSecond) {
        LocalLockMethodInterceptor.expireTimeSecond = expireTimeSecond;
    }

    //定义缓存,设置最大缓存数及过期日期
    private static final Cache<String, Object> CACHE =
            CacheBuilder.newBuilder().maximumSize(1000).expireAfterWrite(Long.parseLong(expireTimeSecond), TimeUnit.SECONDS).build();

    @Around(value = "execution(public * *(..))  && @annotation(com.his.common.util.LocalLock)")
    public Object interceptor(ProceedingJoinPoint joinPoint) {

        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();
//       LocalLock localLock = method.getAnnotation(LocalLock.class);
        try {
            String key = getLockUniqueKey(signature, joinPoint.getArgs());
            if (CACHE.getIfPresent(key) != null) {
                return  ResultUtil.succeed(null,"500","不允许重复提交,请稍后再试");
            }
            CACHE.put(key, key);

            return joinPoint.proceed();
        } catch (Throwable throwable) {
            return  ResultUtil.succeed(null,"500",throwable.getMessage());
//            throw new RuntimeException(throwable.getMessage());
        } finally {

        }
    }


    /**
     * 获取唯一标识key
     *
     * @param methodSignature
     * @param args
     * @return
     */
    private String getLockUniqueKey(MethodSignature methodSignature, Object[] args) throws NoSuchAlgorithmException {
        //请求uri, 获取类名称,方法名称
        RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
        ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) requestAttributes;
        HttpServletRequest request = servletRequestAttributes.getRequest();
//        HttpServletResponse responese = servletRequestAttributes.getResponse();

//        //获取用户信息
//        String userMsg = SecurityUtils.getUsername(); //获取登录用户名称
//        //1.判断用户是否登录
//        if (StringUtils.isEmpty(userMsg)) { //未登录用户获取真实ip
//            userMsg = IpUtils.getIpAddr(request);
//        }
        String hash = "";
        List list = new ArrayList();
        if (args.length > 0) {
            String[] parameterNames = methodSignature.getParameterNames();
            for (int i = 0; i < parameterNames.length; i++) {
                Object obj = args[i];
                list.add(obj);
            }
//            hash = JSONObject.toJSONString(list);

        }
        //项目名称 + 环境编码 + 获取类名称 + 方法名称 + 唯一key
        String key = "locallock:" + springApplicationName + ":" + springProfilesActive + ":" + request.getRequestURI();
        if (StringUtils.isNotEmpty(key)) {
            key = key + ":" + hash;
        }
//        key = MyMD5Util.getMD5(key);
        return key;
    }
}

使用:

 

 

https://blog.csdn.net/qq_33454058/article/details/125516310

标签:java,String,提交,org,request,key,刷新,import
来源: https://www.cnblogs.com/yangxiaoli/p/16693194.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有