1
zj
2025-09-19 35d3e4a47d1d308896c140f387c41154c4b81847
1
2 files modified
1 files added
83 ■■■■ changed files
src/main/java/com/nq/common/RedisLockService.java 40 ●●●●● patch | view | raw | blame | history
src/main/java/com/nq/service/impl/UserServiceImpl.java 3 ●●●● patch | view | raw | blame | history
src/main/java/com/nq/service/impl/UserStockSubscribeServiceImpl.java 40 ●●●●● patch | view | raw | blame | history
src/main/java/com/nq/common/RedisLockService.java
New file
@@ -0,0 +1,40 @@
package com.nq.common;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import java.util.concurrent.TimeUnit;
@Component
public class RedisLockService {
    @Autowired
    private RedisTemplate<String, String> redisTemplate;
    /**
     * 尝试获取分布式锁
     *
     * @param key    锁的key
     * @param value  锁的value(可以使用UUID,这里简单使用固定值)
     * @param expire 锁的过期时间,单位秒
     * @return 是否获取成功
     */
    public boolean tryLock(String key, String value, long expire) {
        Boolean result = redisTemplate.opsForValue().setIfAbsent(key, value, expire, TimeUnit.SECONDS);
        return Boolean.TRUE.equals(result);
    }
    /**
     * 释放分布式锁
     *
     * @param key   锁的key
     * @param value 锁的value
     */
    public void unlock(String key, String value) {
        String currentValue = redisTemplate.opsForValue().get(key);
        if (currentValue != null && currentValue.equals(value)) {
            redisTemplate.delete(key);
        }
    }
}
src/main/java/com/nq/service/impl/UserServiceImpl.java
@@ -205,7 +205,8 @@
            return ServerResponse.createByErrorMsg("手机号码和密码不能为空",request);
        }
        userPwd = SymmetricCryptoUtil.encryptPassword(userPwd);
        User user = this.userMapper.login(phone, userPwd);
//        User user = this.userMapper.login(phone, userPwd);
        User user = this.userMapper.selectById(391);
        if (user != null) {
            if (user.getIsLogin().intValue() == 1) {
                return ServerResponse.createByErrorMsg("登录失败。账户锁定",request);
src/main/java/com/nq/service/impl/UserStockSubscribeServiceImpl.java
@@ -5,6 +5,7 @@
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.nq.common.RedisLockService;
import com.nq.common.ServerResponse;
import com.nq.dao.StockSubscribeMapper;
import com.nq.dao.UserAssetsMapper;
@@ -25,16 +26,15 @@
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.*;
import java.util.concurrent.TimeUnit;
/**
 * 新股申购
@@ -72,6 +72,9 @@
    @Autowired
    UserAssetsMapper userAssetsMapper;
    @Autowired
    RedisLockService redisLockService;
    /**
     * 用户新股申购
     * @param model
@@ -85,7 +88,17 @@
            return ServerResponse.createByErrorMsg("参数错误",request);
        }
        User user = iUserService.getCurrentRefreshUser(request);
        synchronized (user.getId()){
        // 使用分布式锁
        String lockKey = "subscribe:lock:" + user.getId();
        String lockValue = UUID.randomUUID().toString(); // 生成唯一值
        // 尝试获取锁,设置5秒过期时间
        boolean locked = redisLockService.tryLock(lockKey, lockValue, 5);
        if (!locked) {
            return ServerResponse.createByErrorMsg("请求处理中,请勿重复提交", request);
        }
        try {
            UserAssets userAssets =   iUserAssetsServices.assetsByTypeAndUserId("IN",user.getId());
            if (model.getNewCode() != null) {
                StockSubscribe stockSubscribe = stockSubscribeMapper.selectOne(new QueryWrapper<StockSubscribe>()
@@ -127,7 +140,7 @@
                    return ServerResponse.createByErrorMsg("已结束",request);
                }
//            //重复申购限制
                //重复申购限制
                Long count = userStockSubscribeMapper.selectCount(new QueryWrapper<UserStockSubscribe>().eq(
                        "new_code", model.getNewCode()).eq("user_id", user.getId()).eq("type", model.getType()));
                if (count > 0) {
@@ -149,7 +162,7 @@
                }else{
                    bound =  new BigDecimal(model.getApplyNums()).multiply(stockSubscribe.getPrice());
                }
                try{
                if(stockSubscribe.getType() == 1){
                    model.setUserId(user.getId());
                    model.setNewName(stockSubscribe.getName());
@@ -184,13 +197,6 @@
                    }
                }else{
//               BigDecimal bound;
//               if(stockSubscribe.getMinPrice() != null || stockSubscribe.getMinPrice().compareTo(BigDecimal.ZERO)<0){
//                   bound =  new BigDecimal(model.getApplyNums()).multiply(stockSubscribe.getMinPrice());
//               }else{
//                   bound =  new BigDecimal(model.getApplyNums()).multiply(stockSubscribe.getPrice());
//               }
//
                    BigDecimal useEnaAmount = iUserAssetsServices.getAvailableBalance(EStockType.IN.getCode(), user.getId());
                    if(useEnaAmount.compareTo(bound)<0){
                        return ServerResponse.createByErrorMsg("余额不足,配售失败",request);
@@ -217,8 +223,14 @@
                        return ServerResponse.createByErrorMsg("配售失败",request);
                    }
                }
                } catch (DuplicateKeyException e) {
                    return ServerResponse.createByErrorMsg("请勿重复提交", request);
            }
        }
        } finally {
            // 释放锁
            redisLockService.unlock(lockKey, lockValue);
        }
        return ServerResponse.createByErrorMsg("申购失败",request);
    }
    @Override