这段时间接到一个校验的需求改动,最开始拿到的代码大致上逻辑思路是如下的,可以分析出来他这个当前已经有了3个校验了,我本次的需求是再加1个校验且本次的校验checkData函数是不能满足的
import cn.hutool.core.collection.CollectionUtil;
import com.example.demo.resp.ResponseDataModel;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.stream.Collectors;
/**
* @author Mikey
* @version 1.0
* @date 2023/5/10 16:14
* @description 校验Controller案例
*/
@RestController
@Slf4j
@RequestMapping("/check")
public class CheckRuleController {
@ApiOperation(value = "校验数据接口", httpMethod = "GET")
@GetMapping("/checkAllData")
public ResponseDataModel checkAllData() throws ExecutionException, InterruptedException {
// 校验1
CompletableFuture<String> future1 = CompletableFuture.supplyAsync(() -> {
long l1 = System.currentTimeMillis();
System.out.println("任务1启动! =====>" + l1);
// 校验1业务逻辑校验代码
String result = checkData("1");
long l2 = System.currentTimeMillis();
System.out.println("任务1结束,耗时:! =====>" + (l2 - l1));
return result;
});
// 校验2
CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> {
long l1 = System.currentTimeMillis();
System.out.println("任务2启动! =====>" + l1);
// 校验2业务逻辑校验代码
String result = checkData("2");
long l2 = System.currentTimeMillis();
System.out.println("任务2结束,耗时:! =====>" + (l2 - l1));
return result;
});
CompletableFuture<String> future3 = CompletableFuture.supplyAsync(() -> {
long l1 = System.currentTimeMillis();
System.out.println("任务3启动! =====>" + l1);
// 校验3业务逻辑校验代码
String result = checkData("3");
long l2 = System.currentTimeMillis();
System.out.println("任务3结束,耗时:! =====>" + (l2 - l1));
return result;
});
List<String> futureList = new ArrayList<>();
futureList.add(future1.get());
futureList.add(future2.get());
futureList.add(future3.get());
List<String> resultList = Arrays.stream(futureList.toArray(new String[futureList.size()])).collect(Collectors.toList());
return CollectionUtil.isEmpty(resultList) ? ResponseDataModel.ok() : ResponseDataModel.ok(resultList);
}
/**
* 各类型规则进行校验
* @param type
* @return
*/
private String checkData(String type){
// 伪代码 doSth为你的业务逻辑代码
String result = StringUtils.EMPTY;
switch (type){
case "1":
//result = doSth1...
result = "1";
break;
case "2":
//result = doSth2...
result = "2";
break;
default:
//result = doSth default...
result = "default";
break;
}
return result;
}
}
按照如上代码思路,再加一个校验或者更多的校验代码就会向如下趋势演化
import cn.hutool.core.collection.CollectionUtil;
import com.example.demo.resp.ResponseDataModel;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.stream.Collectors;
/**
* @author Mikey
* @version 1.0
* @date 2023/5/10 16:14
* @description 校验Controller案例
*/
@RestController
@Slf4j
@RequestMapping("/check")
public class CheckRuleController {
@ApiOperation(value = "校验数据接口", httpMethod = "GET")
@GetMapping("/checkAllData")
public ResponseDataModel checkAllData() throws ExecutionException, InterruptedException {
// 校验1
CompletableFuture<String> future1 = CompletableFuture.supplyAsync(() -> {
long l1 = System.currentTimeMillis();
System.out.println("任务1启动! =====>" + l1);
// 校验1业务逻辑校验代码
String result = checkData("1");
long l2 = System.currentTimeMillis();
System.out.println("任务1结束,耗时:! =====>" + (l2 - l1));
return result;
});
// 校验2
CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> {
long l1 = System.currentTimeMillis();
System.out.println("任务2启动! =====>" + l1);
// 校验2业务逻辑校验代码
String result = checkData("2");
long l2 = System.currentTimeMillis();
System.out.println("任务2结束,耗时:! =====>" + (l2 - l1));
return result;
});
CompletableFuture<String> future3 = CompletableFuture.supplyAsync(() -> {
long l1 = System.currentTimeMillis();
System.out.println("任务5启动! =====>" + l1);
// 校验3业务逻辑校验代码
String result = checkData("3");
long l2 = System.currentTimeMillis();
System.out.println("任务5结束,耗时:! =====>" + (l2 - l1));
return result;
});
// 校验4
CompletableFuture<String> future4 = CompletableFuture.supplyAsync(() -> {
long l1 = System.currentTimeMillis();
System.out.println("任务4启动! =====>" + l1);
// 校验4业务逻辑校验代码
String result = newCheckData();
long l2 = System.currentTimeMillis();
System.out.println("任务4结束,耗时:! =====>" + (l2 - l1));
return result;
});
// 校验5
CompletableFuture<String> future5 = CompletableFuture.supplyAsync(() -> {
long l1 = System.currentTimeMillis();
System.out.println("任务5启动! =====>" + l1);
// 校验5业务逻辑校验代码
String result = otherCheckData();
long l2 = System.currentTimeMillis();
System.out.println("任务5结束,耗时:! =====>" + (l2 - l1));
return result;
});
// 校验6
CompletableFuture<String> future6 = CompletableFuture.supplyAsync(() -> {
long l1 = System.currentTimeMillis();
System.out.println("任务6启动! =====>" + l1);
// 校验6业务逻辑校验代码
String result = otherCheckData();
long l2 = System.currentTimeMillis();
System.out.println("任务6结束,耗时:! =====>" + (l2 - l1));
return result;
});
List<String> futureList = new ArrayList<>();
// 收集异步执行结果
futureList.add(future1.get());
futureList.add(future2.get());
futureList.add(future3.get());
futureList.add(future4.get());
futureList.add(future5.get());
futureList.add(future6.get());
List<String> resultList = Arrays.stream(futureList.toArray(new String[futureList.size()])).collect(Collectors.toList());
return CollectionUtil.isEmpty(resultList) ? ResponseDataModel.ok() : ResponseDataModel.ok(resultList);
}
/**
* 各类型规则进行校验
* @param type
* @return
*/
private String checkData(String type){
// 伪代码 doSth为你的业务逻辑代码
String result = StringUtils.EMPTY;
switch (type){
case "1":
//result = doSth1...
result = "1";
break;
case "2":
//result = doSth2...
result = "2";
break;
default:
//result = doSth default...
result = "default";
break;
}
return result;
}
/**
* 新业务校验规则
* @return
*/
private String newCheckData(){
return "新1";
}
/**
* 其他业务校验规则
* @return
*/
private String otherCheckData(){
return "更多其他校验";
}
}
到这里,大多数同学们应该都会发起提问,每次加个校验任务都得写一次CompletableFuture.supplyAsync、FutureList.add,代码量虽然蹭蹭往上涨,但都是无效代码,虽然实现了,但我们不做写屎山的攻城狮接下来进入优化步骤,这边演化的是最终的优化代码版本,其中碰到了很多坎,也是请教了朋友一步步改造,才完成如下代码版本
第一步,每一个校验都要加一个异步,CompletableFuture是一个重复的代码,思考有没办法扔到循环里面,用循环完成异步部署任务PS:CompletableFuture.supplyAsync可以改用采用自定义线程池配置
/**
* 部署所有异步任务
* @param suppliers
* @return
*/
public List<CompletableFuture<String>> buildCompletableFutureList(Supplier... suppliers) {
List<CompletableFuture<String>> futureList = new ArrayList<>();
for (Supplier supplier : suppliers) {
CompletableFuture<String> future = CompletableFuture.supplyAsync(supplier);
futureList.add(future);
}
return futureList;
}
第二步,根据第一步封装异步部署任务,需要提供参数Supplier的方法,对各校验函数进行改造
/**
* 各类型规则进行校验
*
* @param type
* @return
*/
private Supplier<String> checkData(String type) {
return () -> {
// 伪代码 doSth为你的业务逻辑代码
String result = StringUtils.EMPTY;
switch (type) {
case "1":
//result = doSth1...
result = "1";
break;
case "2":
//result = doSth2...
result = "2";
break;
default:
//result = doSth default...
result = "default";
break;
}
return result;
};
}
第三步,收集各异步执行结果改造
/**
* 获取所有异步任务执行结果
* @param futureList
* @return
*/
public List<String> getFutureResultList(List<CompletableFuture<String>> futureList){
// 收集各异步校验任务
CompletableFuture<Void> allFutures = CompletableFuture.allOf(futureList.toArray(new CompletableFuture[futureList.size()]));
// 等待所有任务执行结果
allFutures.join();
// 获取所有任务执行结果
List<String> resultList = new ArrayList<>();
for(CompletableFuture<String> future: futureList){
resultList.add(future.join());
}
return resultList;
}
按上述步骤整合后的代码,整体代码更为简洁,提高可读性、代码复用性
import cn.hutool.core.collection.CollectionUtil;
import com.example.demo.resp.ResponseDataModel;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.function.Supplier;
import java.util.stream.Collectors;
/**
* @author Mikey
* @version 1.0
* @date 2023/5/10 16:14
* @description 校验Controller案例
*/
@RestController
@Slf4j
@RequestMapping("/check")
public class CheckRuleController {
@ApiOperation(value = "校验数据接口", httpMethod = "GET")
@GetMapping("/checkAllData")
public ResponseDataModel checkAllData() throws ExecutionException, InterruptedException {
List<Supplier<String>> suppliers = new ArrayList<>();
// 校验1
suppliers.add(checkData("1"));
// 校验2
suppliers.add(checkData("2"));
// 校验3
suppliers.add(checkData("3"));
// 校验4
suppliers.add(newCheckData());
// 校验5
suppliers.add(otherCheckData());
// 校验6
suppliers.add(otherCheckData());
// 部署各异步校验任务
List<CompletableFuture<String>> futureList = buildCompletableFutureList(suppliers.toArray(new Supplier[suppliers.size()]));
// 获取所有异步任务执行结果
List<String> resultList = getFutureResultList(futureList);
// 响应服务端结果
return CollectionUtil.isEmpty(resultList) ? ResponseDataModel.ok() : ResponseDataModel.ok(resultList);
}
/**
* 获取所有异步任务执行结果
* @param futureList
* @return
*/
public List<String> getFutureResultList(List<CompletableFuture<String>> futureList){
// 收集各异步校验任务
CompletableFuture<Void> allFutures = CompletableFuture.allOf(futureList.toArray(new CompletableFuture[futureList.size()]));
// 等待所有任务执行结果
allFutures.join();
// 获取所有任务执行结果
List<String> resultList = new ArrayList<>();
for(CompletableFuture<String> future: futureList){
resultList.add(future.join());
}
return resultList;
}
/**
* 部署所有异步任务
* @param suppliers
* @return
*/
public List<CompletableFuture<String>> buildCompletableFutureList(Supplier... suppliers) {
List<CompletableFuture<String>> futureList = new ArrayList<>();
for (Supplier supplier : suppliers) {
CompletableFuture<String> future = CompletableFuture.supplyAsync(supplier);
futureList.add(future);
}
return futureList;
}
/**
* 各类型规则进行校验
*
* @param type
* @return
*/
private Supplier<String> checkData(String type) {
return () -> {
// 伪代码 doSth为你的业务逻辑代码
String result = StringUtils.EMPTY;
switch (type) {
case "1":
//result = doSth1...
result = "1";
break;
case "2":
//result = doSth2...
result = "2";
break;
default:
//result = doSth default...
result = "default";
break;
}
return result;
};
}
/**
* 新业务校验规则
*
* @return
*/
private Supplier<String> newCheckData() {
return () -> {
return "新1";
};
}
/**
* 其他业务校验规则
*
* @return
*/
private Supplier<String> otherCheckData() {
return () -> {
return "更多其他校验";
};
}
}
所谓“道生一生二生三生万物”,还可以考虑几个封装的函数由于使用的业务场景不同,参数类型和数据类型也可能不同,更换为泛型,这样才能让自身实力更加强大
import cn.hutool.core.collection.CollectionUtil;
import com.example.demo.resp.ResponseDataModel;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.function.Supplier;
import java.util.stream.Collectors;
/**
* @author Mikey
* @version 1.0
* @date 2023/5/10 16:14
* @description 校验Controller案例
*/
@RestController
@Slf4j
@RequestMapping("/check")
public class CheckRuleController {
@ApiOperation(value = "校验数据接口", httpMethod = "GET")
@GetMapping("/checkAllData")
public ResponseDataModel checkAllData() throws ExecutionException, InterruptedException {
List<Supplier> suppliers = new ArrayList<>();
// 校验1
suppliers.add(checkData("1"));
// 校验2
suppliers.add(checkData("2"));
// 校验3
suppliers.add(checkData("3"));
// 校验4
suppliers.add(newCheckData());
// 校验5
suppliers.add(otherCheckData());
// 校验6
suppliers.add(otherCheckData());
// 部署各异步校验任务
List<CompletableFuture<String>> futureList = buildCompletableFutureList(suppliers.toArray(new Supplier[suppliers.size()]));
// 获取所有异步任务执行结果
List<String> resultList = getFutureResultList(futureList);
// 响应服务端结果
return CollectionUtil.isEmpty(resultList) ? ResponseDataModel.ok() : ResponseDataModel.ok(resultList);
}
/**
* 获取所有异步任务执行结果
*
* @param futureList
* @return
*/
public <T> List<T> getFutureResultList(List<CompletableFuture<T>> futureList) {
// 收集各异步校验任务
CompletableFuture<Void> allFutures = CompletableFuture.allOf(futureList.toArray(new CompletableFuture[futureList.size()]));
// 等待所有任务执行结果
allFutures.join();
// 获取所有任务执行结果
List<Object> resultList = new ArrayList<>();
for (CompletableFuture<T> future : futureList) {
resultList.add(future.join());
}
return (List<T>) resultList;
}
/**
* 部署所有异步任务
*
* @param suppliers
* @return
*/
public <T> List<CompletableFuture<T>> buildCompletableFutureList(Supplier<T>... suppliers) {
List<CompletableFuture<T>> futureList = new ArrayList<>();
for (Supplier supplier : suppliers) {
CompletableFuture<T> future = CompletableFuture.supplyAsync(supplier);
futureList.add(future);
}
return futureList;
}
/**
* 各类型规则进行校验
*
* @param type
* @return
*/
private <T> Supplier<T> checkData(String type) {
return () -> {
// 伪代码 doSth为你的业务逻辑代码
String result = StringUtils.EMPTY;
switch (type) {
case "1":
//result = doSth1...
result = "1";
break;
case "2":
//result = doSth2...
result = "2";
break;
default:
//result = doSth default...
result = "default";
break;
}
return (T) result;
};
}
/**
* 新业务校验规则
*
* @return
*/
private <T> Supplier<T> newCheckData() {
return () -> {
return (T) "新1";
};
}
/**
* 其他业务校验规则
*
* @return
*/
private <T> Supplier<T> otherCheckData() {
return () -> {
return (T) "更多其他校验";
};
}
}
文章为作者独立观点,不代表 股票程序化软件自动交易接口观点