SpringBoot+Vue3+Element Plus 仿百度网盘实战
核心代码,注释必读
// download:
3w ukoou com
Java 的可变参数与 Collections 类
1. 可变参数
在JDK1.5之后,如果我们定义一个方法需要接受多个参数,并且多个参数类型一致,我们可以对其简化.
格式:
修饰符 返回值类型 方法名(参数类型... 形参名){ }
底层:
其实就是一个数组
好处:
在传递数据的时候,省的我们自己创建数组并添加元素了,JDK底层帮我们自动创建数组并添加元素了
代码演示:
public class ChangeArgs {
public static void main(String[] args) {
int sum = getSum(6, 7, 2, 12, 2121);
System.out.println(sum);
}
public static int getSum(int... arr) {
int sum = 0;
for (int a : arr) {
sum += a;
}
return sum;
}
}
注意:
1.一个方法只能有一个可变参数
2.如果方法中有多个参数,可变参数要放到最后。
应用场景: Collections
在Collections中也提供了添加一些元素方法:
public static <T> boolean addAll(Collection<T> c, T... elements) :往集合中添加一些元素。
代码演示:
public class CollectionsDemo {
public static void main(String[] args) {
ArrayList<Integer> list = new ArrayList<Integer>();
//原来写法
//list.add(12);
//list.add(14);
//list.add(15);
//list.add(1000);
//采用工具类 完成 往集合中添加元素
Collections.addAll(list, 5, 222, 1,2);
System.out.println(list);
}
2. Collections类
2.1 Collections常用功能
-
java.utils.Collections是集合工具类,用来对集合进行操作。常用方法如下:
-
public static void shuffle(List<?> list):打乱集合顺序。 -
public static <T> void sort(List<T> list):将集合中元素按照默认规则排序。 -
public static <T> void sort(List<T> list,Comparator<? super T> ):将集合中元素按照指定规则排序。
代码演示:
public class CollectionsDemo {
public static void main(String[] args) {
ArrayList<Integer> list = new ArrayList<Integer>();
list.add(100);
list.add(300);
list.add(200);
list.add(50);
//排序方法
Collections.sort(list);
System.out.println(list);
}
}
结果:
[50,100, 200, 300]
我们的集合按照默认的自然顺序进行了排列,如果想要指定顺序那该怎么办呢?
SpringBoot+Vue3+Element Plus实战
发生企业级灾难
代码执行描述:
1、用户的余额是通过后台,在每日0点开始进行入账(归入余额)。
2、使用@Scheduled作为定时脚本
3、定时任务需要获取到 redis setnx 锁的权限,才能继续执行下面的代码
@Component // 1.主要用于标记配置类,兼备Component的效果。
@EnableScheduling // 2.开启定时任务
public class OrderMoneyToMerchantMoney {
@Resource
private JedisPoolUtil jedisPoolUtil;
@Scheduled(cron = "${scheduled.timedTaskScheduled:*/5 * * * * ?}")
public void configureTasks() {
System.err.println("执行静态定时任务时间: " + LocalDateTime.now());
selectDb();
}
@Transactional // 事务操作
public void selectDb() {
……
for (Orderlist temp : allList) {
// 获取锁权限
boolean setNx = JedisPoolUtil.setNx("D1MoneyToMerchantD0Money:" + temp.getOrderid(), 60 * 10); // 锁10分钟
if (!setNx) {
continue;
}
……
}
}
使用的util工具是
@Component
public class JedisPoolUtil {
private RedisTemplate<String, Object> redisTemplate;
public RedisTemplate<String, Object> getRedisTemplate() {
return redisTemplate;
}
public boolean setNx(String key, long time) {
try {
Boolean lock = getRedisTemplate().opsForValue().setIfAbsent(key, 1, time, TimeUnit.SECONDS);
if (lock) {
// 加锁成功
return true;
} else {
// 没有分布式锁,等待,进入自旋
return false;
}
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
}
redis执行逻辑:
在程序初始化时:创建0~15库的redis连接,并放到map中
使用时,取出map中的一个值,加载到工具类的redisTemplate当中
JedisPoolUtil redisUtil = jedisPoolUtil.setRedisTemplate(jedisPoolUtilConfig.getRedisTemplateByDb(10));
服务器:一台 centos7.9
docker:docker19.03.13 + docker composer
java:运行在2个docker容器中(使用docker composer编排)
redis:运行在docker容器中 redis_6.2.6版本 使用docker官方镜像 redis:6.2.6
灾难描述:
1、用户余额在昨日,突然2个在docker中的java进程均获取到了 redis setnx 锁-->导致用户余额重复增加
2、商户余额已经提现,平台金额亏损。
发现原因:
1、猜测redis使用的spingboot2 自动注入的类
@Resource
private JedisPoolUtil jedisPoolUtil;
而不是
JedisPoolUtil redisUtil = jedisPoolUtil.setRedisTemplate(jedisPoolUtilConfig.getRedisTemplateByDb(10));
导致多个java进程(可能)连接到不同的redis库,所以不同redis库在setnx时,可以获取到锁。
2、猜测是否跟使用docker redis+docker java 有关
-->本地启动2个jar+本地redis测试结果:只能1个java进程获取到redis setnx锁,另一个获取不到
-->本地启动1个jar+线上启动2个docker java+本地连接线上redis测试结果:只能1个java进程获取到redis setnx锁,另一个获取不到