Ai
1 Star 0 Fork 0

张卢/JavaBase

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
该仓库未声明开源许可证文件(LICENSE),使用请关注具体项目描述及其代码上游依赖。
克隆/下载
StrategyPattern01.java 10.92 KB
一键复制 编辑 原始数据 按行查看 历史
package design.pattern.Lu04TemplatePattern;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.junit.Test;
import java.util.*;
import java.util.function.Function;
/**
* @program JavaBase
* @description: 模版模式 - 分布式事务
* @author: zhanglu
* @create: 2022-05-19 21:36:00
*/
@Slf4j
public class StrategyPattern01 {
/******************数据模型定义******************/
//接口定义: 请求时,什么接口的调用方式
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
static class ApiDefinition<T, R> {
//服务名
private String application;
//服务根地址
private String url;
//接口名
private String name;
//接口地址
private String api;
//请求参数
private T request;
//响应参数
private R response;
//调度日志
private StringBuffer executeMsg;
}
//响应结果
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
static class LuResponse<U> {
private Integer code;
private String message;
private U data;
private Map<String, Object> params = new LinkedHashMap<>();
private boolean isSuccess() {
return code > 0;
}
public LuResponse<U> params(String k, Object v) {
this.params.put(k, v);
return this;
}
}
//T:接口请求参数 R:接口响应参数 S:db执行结果 U:方法返回结果
//db资源
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
static class TransactionResource<T, R> {
private ApiDefinition<T, R> apiDefinition;
private ApiDefinition<T, R> undoApiDefinition;
private Function<ApiDefinition<T, R>, R> redo;
private Function<ApiDefinition<T, R>, R> undo;
private boolean success;
}
/******************模版模式******************/
//分布式管理者-协调各个资源,要么都提交,要不都回滚
@Slf4j
static abstract class Transaction2PCManage<T, R> {
private Object request;
private List<TransactionResource<T, R>> resourceList;
public Transaction2PCManage() {
resourceList = new LinkedList<>();
}
public Transaction2PCManage<T, R> setRequest(Object request) {
this.request = request;
return this;
}
public Object getRequest() {
return this.request;
}
protected TransactionResource<T, R> append(TransactionResource<T, R> resource) {
this.resourceList.add(resource);
return resource;
}
//模版方法
protected LuResponse execute() {
Integer code = 1;
//执行全部的事务
for (TransactionResource<T, R> resource : resourceList) {
log.info("----------------------");
R res = null;
try {
log.info(StrUtil.format("服务[{}]-接口[{}]-事务执行开始",
resource.getApiDefinition().getApplication(), resource.getApiDefinition().getName()));
log.info("{}-请求参数:{}", resource.getApiDefinition().getName(), this.getRequest());
resource.getApiDefinition().setRequest((T) this.getRequest());
res = resource.redo.apply(resource.getApiDefinition());
resource.getApiDefinition().setResponse(res);
resource.getApiDefinition().setExecuteMsg(new StringBuffer("redo成功"));
log.info("{}-响应结果:{}", resource.getApiDefinition().getName(), res);
this.setRequest(res);
resource.getApiDefinition().setResponse(res);
resource.setSuccess(true);
log.info(StrUtil.format("服务[{}]-接口[{}]-事务执行成功:{}",
resource.getApiDefinition().getApplication(), resource.getApiDefinition().getName(), res));
} catch (Exception e) {
code = -1;
log.info(StrUtil.format("服务[{}]-接口[{}]-事务执行异常:{}",
resource.getApiDefinition().getApplication(), resource.getApiDefinition().getName(), e));
resourceList.stream().filter(o -> o.isSuccess()).forEach(undoResource -> {
log.info("----------------------");
if (undoResource.getUndoApiDefinition() == null) {
ApiDefinition<T, R> apiDefinition = undoResource.getApiDefinition();
ApiDefinition<T, R> undoApiDefinition = new ApiDefinition<>();
BeanUtil.copyProperties(apiDefinition, undoApiDefinition);
undoResource.setUndoApiDefinition(undoApiDefinition);
}
log.info(StrUtil.format("服务[{}]-接口[{}]-分布式事务-执行回滚开始:{}",
undoResource.getUndoApiDefinition().getApplication(), undoResource.getUndoApiDefinition().getName()));
log.info("{}-请求参数:{}", undoResource.getUndoApiDefinition().getName(), undoResource.getApiDefinition().getResponse());
this.setRequest(undoResource.getApiDefinition().getResponse());
R rs = undoResource.undo.apply(undoResource.getUndoApiDefinition());
undoResource.getUndoApiDefinition().setResponse(rs);
undoResource.getUndoApiDefinition().setExecuteMsg(new StringBuffer("undo成功"));
log.info("{}-响应结果:{}", undoResource.getUndoApiDefinition().getName(), rs);
log.info(StrUtil.format("服务[{}]-接口[{}]-分布式事务-执行回滚结束:{}",
undoResource.getUndoApiDefinition().getApplication(), undoResource.getUndoApiDefinition().getName(), rs));
});
break;
}
}
return LuResponse.builder().code(code)
.data(resourceList)
.build();
}
}
/******************控制器******************/
@Slf4j
static class OrderController extends Transaction2PCManage {
public LuResponse createOrder(String data) {
//实际上应该rpc调用,执行各个服务的redo、undo操作。这里采用本地伪代码的方式执行
/*
rpc -> String res = HttpRequest.post(api.getUrl() + api.getApi()).body(request).execute().body();
*/
this.setRequest(data).append(TransactionResource.builder()
.apiDefinition(ApiDefinition.builder()
.application("stock-service").url("http://127.0.0.1:8001/stock").api("/update")
.name("扣减库存")
.build())
.redo(api -> {
String request = this.getRequest().toString();
String sql = "update stock set num=num-1 where ...";
//db执行
Integer res = 1;
Integer id = 1;
Map<String, Object> m = new HashMap<>();
m.put("id", id);
m.put("num", 1);
return m;
})
.undo(api -> {
Map<String, Object> m = (Map<String, Object>) this.getRequest();
String sql = "update stock set num=num+1 where ...";
//db执行
Integer res = 1;
return res;
}).build());
//生成订单
this.append(TransactionResource.builder()
.apiDefinition(ApiDefinition.builder()
.application("order-service").url("http://127.0.0.1:8001/order").api("/save")
.name("保存订单")
.build())
.undoApiDefinition(ApiDefinition.builder()
.application("order-service").url("http://127.0.0.1:8001/order").api("/delete")
.name("删除订单")
.build())
.redo(api -> {
String request = this.getRequest().toString();
String sql = "insert into order('','') values('','')";
//db执行
Integer res = 1;
Integer id = 1;
return id;
})
.undo(api -> {
Integer id = (Integer) this.getRequest();
String sql = "delete from order where id=" + id;
//db执行
Integer res = 1;
return res;
}).build());
this.append(TransactionResource.builder()
.apiDefinition(ApiDefinition.builder()
.application("account-service").url("http://127.0.0.1:8001/account").api("/update")
.name("扣减账户余额")
.build())
.redo(api -> {
String request = this.getRequest().toString();
String sql = "update account set gold=gold-10 where ...";
//db执行
Integer res = 1;
Integer id = 1;
Map<String, Object> m = new HashMap<>();
m.put("id", id);
m.put("gold", 10);
//模拟分布式事务异常情况
int i = 1 / 0;
return m;
})
.undo(api -> {
Map<String, Object> m = (Map<String, Object>) this.getRequest();
String sql = "update account set gold=gold+10 where ...";
//db执行
Integer res = 1;
return res;
}).build());
LuResponse response = this.execute();
log.info("本次任务全部执行完毕-执行结果:{}", JSON.toJSON(response).toString());
return response;
}
}
/******************测试******************/
@Test
public void test01() {
OrderController orderController = new OrderController();
orderController.createOrder("lu ~ 购买 猫粮 20 元 1个 address...");
}
}
Loading...
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
Java
1
https://gitee.com/ShowLuu/JavaBase.git
git@gitee.com:ShowLuu/JavaBase.git
ShowLuu
JavaBase
JavaBase
master

搜索帮助