add: 完成经过验证的fescar集成及配套的demo

This commit is contained in:
Wendal Chen 2019-03-28 19:52:17 +08:00
parent 93957c7e6d
commit 7236f848f4
39 changed files with 12913 additions and 15 deletions

View File

@ -210,8 +210,9 @@ public class MainLauncher {
- [x] [Shiro+LCache](https://github.com/nutzam/nutzmore/tree/master/nutz-plugins-cache)基于shiro/jedis/插件的分布式可持久化的session缓存
- 分布式事务
- [x] [tcc-transaction](https://github.com/changmingxie/tcc-transaction/tree/dev-1.2.x)基于tcc-transaction的nutz容器支持
- [x] [fescar](https://github.com/alibaba/fescar) 阿里开源的分布式事务引擎
- 计划任务
- [x] **starter-[quartz](http://www.quartz-scheduler.org)**
- [x] **starter-[quartz](http://www.quartz-scheduler.org)** 大家都知道
- [x] starter-xxl-job [国产分布式任务调度平台](https://github.com/xuxueli/xxl-job/pull/253)
- [ ] starter-scheduledx 阿里云分布式任务
- 模板引擎

View File

@ -0,0 +1,47 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.nutz</groupId>
<artifactId>nutzboot-demo-dubbo-fescar</artifactId>
<version>2.3.3-SNAPSHOT</version>
</parent>
<artifactId>nutzboot-demo-dubbo-fescar-account</artifactId>
<dependencies>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
</dependency>
<dependency>
<groupId>org.nutz</groupId>
<artifactId>nutzboot-starter-dubbo</artifactId>
</dependency>
<dependency>
<groupId>org.nutz</groupId>
<artifactId>nutzboot-starter-fescar</artifactId>
</dependency>
<dependency>
<groupId>org.nutz</groupId>
<artifactId>nutzboot-starter-nutz-dao</artifactId>
</dependency>
<dependency>
<groupId>org.nutz</groupId>
<artifactId>nutzboot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.nutz</groupId>
<artifactId>nutzboot-demo-dubbo-fescar-common</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-all</artifactId>
<version>4.1.34.Final</version>
</dependency>
<dependency>
<groupId>com.alibaba.fescar</groupId>
<artifactId>fescar-dubbo-alibaba</artifactId>
<version>${fescar.version}</version>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,31 @@
package io.nutz.demo.dubbo.rpc;
import org.nutz.boot.NbApp;
import org.nutz.dao.Cnd;
import org.nutz.dao.Dao;
import org.nutz.ioc.loader.annotation.Inject;
import org.nutz.ioc.loader.annotation.IocBean;
import io.nutz.demo.bean.Account;
@IocBean(create="init")
public class DemoFescarAccountServiceLauncher {
@Inject
Dao dao;
public void init() {
dao.create(Account.class, false);
if (dao.count(Account.class, Cnd.where("userId", "=", "U100001")) == 0) {
Account account = new Account();
account.setUserId("U100001");
account.setMoney(1000);
dao.insert(account);
}
}
public static void main(String[] args) throws Exception {
new NbApp().run();
}
}

View File

@ -0,0 +1,34 @@
package io.nutz.demo.dubbo.rpc.service.impl;
import org.nutz.dao.Chain;
import org.nutz.dao.Cnd;
import org.nutz.dao.Dao;
import org.nutz.ioc.loader.annotation.Inject;
import org.nutz.ioc.loader.annotation.IocBean;
import org.nutz.log.Log;
import org.nutz.log.Logs;
import com.alibaba.dubbo.config.annotation.Service;
import com.alibaba.fescar.core.context.RootContext;
import io.nutz.demo.bean.Account;
import io.nutz.demo.dubbo.rpc.service.AccountService;
@IocBean
@Service(interfaceClass=AccountService.class)
public class AccountServiceImpl implements AccountService {
private static final Log log = Logs.get();
@Inject
private Dao dao;
@Override
public void debit(String userId, int money) {
log.info("Account Service ... xid: " + RootContext.getXID());
log.infof("Deducting balance SQL: update account_tbl set money = money - %s where user_id = %s", money, userId);
dao.update(Account.class, Chain.makeSpecial("money", "-" + money), Cnd.where("userId", "=", userId));
log.info("Account Service End ... ");
}
}

View File

@ -0,0 +1,32 @@
transport {
# tcp udt unix-domain-socket
type = "TCP"
#NIO NATIVE
server = "NIO"
#enable heartbeat
heartbeat = true
#thread factory for netty
thread-factory {
boss-thread-prefix = "NettyBoss"
worker-thread-prefix = "NettyServerNIOWorker"
server-executor-thread-prefix = "NettyServerBizHandler"
share-boss-worker = false
client-selector-thread-prefix = "NettyClientSelector"
client-selector-thread-size = 1
client-worker-thread-prefix = "NettyClientWorkerThread"
# netty boss thread size,will not be used for UDT
boss-thread-size = 1
#auto default pin or 8
worker-thread-size = 8
}
}
service {
#vgroup->rgroup
vgroup_mapping.my_test_tx_group = "localRgroup"
#only support single node
localRgroup.grouplist = "127.0.0.1:8091"
#degrade current not support
enableDegrade = false
#disable
disable = false
}

View File

@ -0,0 +1,12 @@
server.port=0
jdbc.url=jdbc:mysql://127.0.0.1/fescar_demo
jdbc.username=root
jdbc.password=root
fescar.applicationId=dubbo-fescar-account
fescar.txServiceGroup=my_test_tx_group
dubbo.application.name=dubbo-fescar-account
dubbo.registry.address=zookeeper://127.0.0.1:2181
dubbo.protocol.name=dubbo
dubbo.application.qos.enable=false

View File

@ -0,0 +1,7 @@
log4j.rootLogger=debug,Console
log4j.logger.org.eclipse.jetty=info
log4j.appender.Console=org.apache.log4j.ConsoleAppender
log4j.appender.Console.layout=org.apache.log4j.PatternLayout
log4j.appender.Console.layout.ConversionPattern=[%-5p] %d{HH:mm:ss.SSS} %l - %m%n

View File

@ -0,0 +1,27 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.nutz</groupId>
<artifactId>nutzboot-demo-dubbo-fescar</artifactId>
<version>2.3.3-SNAPSHOT</version>
</parent>
<artifactId>nutzboot-demo-dubbo-fescar-common</artifactId>
<dependencies>
<dependency>
<groupId>org.nutz</groupId>
<artifactId>nutzboot-starter-dubbo</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>dubbo</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.47</version>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,47 @@
package io.nutz.demo.bean;
import org.nutz.dao.entity.annotation.Column;
import org.nutz.dao.entity.annotation.Id;
import org.nutz.dao.entity.annotation.Index;
import org.nutz.dao.entity.annotation.Table;
import org.nutz.dao.entity.annotation.TableIndexes;
@Table("account_tbl")
@TableIndexes(@Index(fields="userId", unique=true))
public class Account {
@Id
private long id;
@Column("user_id")
private String userId;
@Column
private int money;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getUserId() {
return userId;
}
public void setUserId(String userId) {
this.userId = userId;
}
public int getMoney() {
return money;
}
public void setMoney(int money) {
this.money = money;
}
}

View File

@ -0,0 +1,54 @@
package io.nutz.demo.bean;
import java.io.Serializable;
import org.nutz.dao.entity.annotation.Column;
import org.nutz.dao.entity.annotation.Id;
import org.nutz.dao.entity.annotation.Table;
@Table("order_tbl")
public class Order implements Serializable {
private static final long serialVersionUID = 1L;
@Id
private long id;
@Column("user_id")
private String userId;
@Column("commodity_code")
private String commodityCode;
@Column
private int count;
@Column
private int money;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getUserId() {
return userId;
}
public void setUserId(String userId) {
this.userId = userId;
}
public String getCommodityCode() {
return commodityCode;
}
public void setCommodityCode(String commodityCode) {
this.commodityCode = commodityCode;
}
public int getCount() {
return count;
}
public void setCount(int count) {
this.count = count;
}
public int getMoney() {
return money;
}
public void setMoney(int money) {
this.money = money;
}
}

View File

@ -0,0 +1,41 @@
package io.nutz.demo.bean;
import org.nutz.dao.entity.annotation.Column;
import org.nutz.dao.entity.annotation.Id;
import org.nutz.dao.entity.annotation.Table;
@Table("storage_tbl")
public class Storage {
@Id
private long id;
@Column("commodity_code")
private String commodityCode;
@Column
private int count;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getCommodityCode() {
return commodityCode;
}
public void setCommodityCode(String commodityCode) {
this.commodityCode = commodityCode;
}
public int getCount() {
return count;
}
public void setCount(int count) {
this.count = count;
}
}

View File

@ -0,0 +1,8 @@
package io.nutz.demo.dubbo.rpc.service;
public interface AccountService {
/**
* debit balance of user's account
*/
void debit(String userId, int money);
}

View File

@ -0,0 +1,6 @@
package io.nutz.demo.dubbo.rpc.service;
public interface BusinessService {
void purchase(String userId, String commodityCode, int orderCount, boolean dofail);
}

View File

@ -0,0 +1,11 @@
package io.nutz.demo.dubbo.rpc.service;
import io.nutz.demo.bean.Order;
public interface OrderService {
/**
* create order
*/
Order create(String userId, String commodityCode, int orderCount);
}

View File

@ -0,0 +1,8 @@
package io.nutz.demo.dubbo.rpc.service;
public interface StorageService {
/**
* deduct storage count
*/
void deduct(String commodityCode, int count);
}

View File

@ -0,0 +1,47 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.nutz</groupId>
<artifactId>nutzboot-demo-dubbo-fescar</artifactId>
<version>2.3.3-SNAPSHOT</version>
</parent>
<artifactId>nutzboot-demo-dubbo-fescar-order</artifactId>
<dependencies>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
</dependency>
<dependency>
<groupId>org.nutz</groupId>
<artifactId>nutzboot-starter-dubbo</artifactId>
</dependency>
<dependency>
<groupId>org.nutz</groupId>
<artifactId>nutzboot-starter-nutz-dao</artifactId>
</dependency>
<dependency>
<groupId>org.nutz</groupId>
<artifactId>nutzboot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.nutz</groupId>
<artifactId>nutzboot-starter-fescar</artifactId>
</dependency>
<dependency>
<groupId>org.nutz</groupId>
<artifactId>nutzboot-demo-dubbo-fescar-common</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.alibaba.fescar</groupId>
<artifactId>fescar-dubbo-alibaba</artifactId>
<version>${fescar.version}</version>
</dependency>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-all</artifactId>
<version>4.1.34.Final</version>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,23 @@
package io.nutz.demo.dubbo.rpc;
import org.nutz.boot.NbApp;
import org.nutz.dao.Dao;
import org.nutz.ioc.loader.annotation.Inject;
import org.nutz.ioc.loader.annotation.IocBean;
import io.nutz.demo.bean.Order;
@IocBean(create="init")
public class DemoFescarOrderServiceLauncher {
@Inject Dao dao;
public void init() {
dao.create(Order.class, false);
}
public static void main(String[] args) throws Exception {
new NbApp().run();
}
}

View File

@ -0,0 +1,44 @@
package io.nutz.demo.dubbo.rpc.service.impl;
import org.nutz.dao.Dao;
import org.nutz.ioc.loader.annotation.Inject;
import org.nutz.ioc.loader.annotation.IocBean;
import com.alibaba.dubbo.config.annotation.Reference;
import com.alibaba.dubbo.config.annotation.Service;
import io.nutz.demo.bean.Order;
import io.nutz.demo.dubbo.rpc.service.AccountService;
import io.nutz.demo.dubbo.rpc.service.OrderService;
@IocBean
@Service(interfaceClass=OrderService.class)
public class OrderServiceImpl implements OrderService {
@Inject
private Dao dao;
@Inject
@Reference
private AccountService accountService;
public Order create(String userId, String commodityCode, int orderCount) {
int orderMoney = calculate(commodityCode, orderCount);
accountService.debit(userId, orderMoney);
Order order = new Order();
order.setUserId(userId);
order.setCommodityCode(commodityCode);
order.setCount(orderCount);
order.setMoney(orderMoney);
// INSERT INTO orders ...
return dao.insert(order);
}
protected int calculate(String commodityCode, int orderCount) {
return 100;
}
}

View File

@ -0,0 +1,13 @@
server.port=0
dubbo.application.name=dubbo-fescar-order
dubbo.registry.address=zookeeper://127.0.0.1:2181
dubbo.protocol.name=dubbo
dubbo.application.qos.enable=false
jdbc.url=jdbc:mysql://127.0.0.1/fescar_demo
jdbc.username=root
jdbc.password=root
fescar.applicationId=dubbo-fescar-order
fescar.txServiceGroup=my_test_tx_group

View File

@ -0,0 +1,7 @@
log4j.rootLogger=debug,Console
log4j.logger.org.eclipse.jetty=info
log4j.appender.Console=org.apache.log4j.ConsoleAppender
log4j.appender.Console.layout=org.apache.log4j.PatternLayout
log4j.appender.Console.layout.ConversionPattern=[%-5p] %d{HH:mm:ss.SSS} %l - %m%n

View File

@ -0,0 +1,47 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.nutz</groupId>
<artifactId>nutzboot-demo-dubbo-fescar</artifactId>
<version>2.3.3-SNAPSHOT</version>
</parent>
<artifactId>nutzboot-demo-dubbo-fescar-storage</artifactId>
<dependencies>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
</dependency>
<dependency>
<groupId>org.nutz</groupId>
<artifactId>nutzboot-starter-dubbo</artifactId>
</dependency>
<dependency>
<groupId>org.nutz</groupId>
<artifactId>nutzboot-starter-fescar</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.fescar</groupId>
<artifactId>fescar-dubbo-alibaba</artifactId>
<version>${fescar.version}</version>
</dependency>
<dependency>
<groupId>org.nutz</groupId>
<artifactId>nutzboot-starter-nutz-dao</artifactId>
</dependency>
<dependency>
<groupId>org.nutz</groupId>
<artifactId>nutzboot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.nutz</groupId>
<artifactId>nutzboot-demo-dubbo-fescar-common</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-all</artifactId>
<version>4.1.34.Final</version>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,30 @@
package io.nutz.demo.dubbo.rpc;
import org.nutz.boot.NbApp;
import org.nutz.dao.Cnd;
import org.nutz.dao.Dao;
import org.nutz.ioc.loader.annotation.Inject;
import org.nutz.ioc.loader.annotation.IocBean;
import io.nutz.demo.bean.Storage;
@IocBean(create="init")
public class DemoFescarStorageServiceLauncher {
@Inject Dao dao;
public void init() {
dao.create(Storage.class, false);
if (dao.count(Storage.class, Cnd.where("commodityCode", "=", "C00321")) == 0) {
Storage storage = new Storage();
storage.setCommodityCode("C00321");
storage.setCount(100);
dao.insert(storage);
}
}
public static void main(String[] args) throws Exception {
new NbApp().run();
}
}

View File

@ -0,0 +1,36 @@
package io.nutz.demo.dubbo.rpc.service.impl;
import org.nutz.dao.Chain;
import org.nutz.dao.Cnd;
import org.nutz.dao.Dao;
import org.nutz.ioc.loader.annotation.Inject;
import org.nutz.ioc.loader.annotation.IocBean;
import org.nutz.log.Log;
import org.nutz.log.Logs;
import com.alibaba.dubbo.config.annotation.Service;
import com.alibaba.fescar.core.context.RootContext;
import io.nutz.demo.bean.Storage;
import io.nutz.demo.dubbo.rpc.service.StorageService;
@IocBean
@Service(interfaceClass=StorageService.class)
public class StorageServiceImpl implements StorageService {
private static final Log log = Logs.get();
@Inject
private Dao dao;
@Override
public void deduct(String commodityCode, int count) {
log.info("Storage Service Begin ... xid: " + RootContext.getXID());
log.infof("Deducting inventory SQL: update storage_tbl set count = count - %s where commodity_code = %s", count, commodityCode);
dao.update(Storage.class, Chain.makeSpecial("count", "-" + count), Cnd.where("commodityCode", "=", commodityCode));
log.info("Storage Service End ... ");
}
}

View File

@ -0,0 +1,14 @@
server.port=0
dubbo.application.name=dubbo-fescar-storage
dubbo.registry.address=zookeeper://127.0.0.1:2181
dubbo.protocol.name=dubbo
dubbo.application.qos.enable=false
jdbc.url=jdbc:mysql://127.0.0.1/fescar_demo
jdbc.username=root
jdbc.password=root
fescar.applicationId=dubbo-fescar-storage
fescar.txServiceGroup=my_test_tx_group

View File

@ -0,0 +1,7 @@
log4j.rootLogger=debug,Console
log4j.logger.org.eclipse.jetty=info
log4j.appender.Console=org.apache.log4j.ConsoleAppender
log4j.appender.Console.layout=org.apache.log4j.PatternLayout
log4j.appender.Console.layout.ConversionPattern=[%-5p] %d{HH:mm:ss.SSS} %l - %m%n

View File

@ -0,0 +1,55 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.nutz</groupId>
<artifactId>nutzboot-demo-dubbo-fescar</artifactId>
<version>2.3.3-SNAPSHOT</version>
</parent>
<artifactId>nutzboot-demo-dubbo-fescar-web</artifactId>
<dependencies>
<dependency>
<groupId>org.nutz</groupId>
<artifactId>nutzboot-starter-nutz-mvc</artifactId>
</dependency>
<dependency>
<groupId>org.nutz</groupId>
<artifactId>nutzboot-starter-jetty</artifactId>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
</dependency>
<dependency>
<groupId>org.nutz</groupId>
<artifactId>nutzboot-demo-dubbo-fescar-common</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.nutz</groupId>
<artifactId>nutzboot-starter-dubbo</artifactId>
</dependency>
<dependency>
<groupId>org.nutz</groupId>
<artifactId>nutzboot-starter-fescar</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.fescar</groupId>
<artifactId>fescar-dubbo-alibaba</artifactId>
<version>${fescar.version}</version>
</dependency>
<dependency>
<groupId>org.nutz</groupId>
<artifactId>nutzboot-starter-nutz-dao</artifactId>
</dependency>
<dependency>
<groupId>org.nutz</groupId>
<artifactId>nutzboot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-all</artifactId>
<version>4.1.34.Final</version>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,67 @@
package io.nutz.demo.dubbo.rpc;
import org.nutz.boot.NbApp;
import org.nutz.dao.Cnd;
import org.nutz.dao.Dao;
import org.nutz.ioc.loader.annotation.Inject;
import org.nutz.ioc.loader.annotation.IocBean;
import org.nutz.lang.util.NutMap;
import org.nutz.log.Log;
import org.nutz.log.Logs;
import org.nutz.mvc.annotation.At;
import org.nutz.mvc.annotation.Ok;
import io.nutz.demo.bean.Account;
import io.nutz.demo.bean.Storage;
import io.nutz.demo.dubbo.rpc.service.BusinessService;
@IocBean
public class DemoFescarWebLauncher {
private static final Log log = Logs.get();
@Inject
protected BusinessService businessService;
// 订购信息
@Ok("json:full")
@At("/api/purchase")
public NutMap purchase(String userId, String commodityCode, int orderCount, boolean dofail) {
try {
businessService.purchase(userId, commodityCode, orderCount, dofail);
return new NutMap("ok", true);
}
catch (Throwable e) {
log.debug("purchase fail", e);
return new NutMap("ok", false);
}
}
// --------------------------------------------
@Inject
protected Dao dao;
// 用于页面显示数据
@Ok("json:full")
@At("/api/info")
public NutMap info() {
NutMap re = new NutMap();
NutMap data = new NutMap();
data.put("account", dao.fetch(Account.class, Cnd.where("userId", "=", "U100001")));
data.put("storage", dao.fetch(Storage.class, Cnd.where("commodityCode", "=", "C00321")));
return re.setv("data", data).setv("ok", true);
}
// 要启动zk做dubbo注册服务, fescar-server也需要下载启动
// 数据库名称 fescar_demo, 用户名密码均为root,可以在application.properties里面修改
//启动顺序: account,storage,order,web, 服务启动完成后再启动下一个
// 页面操作: http://127.0.0.1:8080/
//正常操作:
// http://127.0.0.1:8080/api/purchase?userId=U100001&commodityCode=C00321&orderCount=1
// 故意抛出异常:
// http://127.0.0.1:8080/api/purchase?userId=U100001&commodityCode=C00321&orderCount=1&dofail=true
public static void main(String[] args) throws Exception {
new NbApp().run();
}
}

View File

@ -0,0 +1,44 @@
package io.nutz.demo.dubbo.rpc.service.impl;
import org.nutz.ioc.loader.annotation.Inject;
import org.nutz.ioc.loader.annotation.IocBean;
import org.nutz.log.Log;
import org.nutz.log.Logs;
import com.alibaba.dubbo.config.annotation.Reference;
import com.alibaba.fescar.core.context.RootContext;
import com.alibaba.fescar.spring.annotation.GlobalTransactional;
import io.nutz.demo.dubbo.rpc.service.BusinessService;
import io.nutz.demo.dubbo.rpc.service.OrderService;
import io.nutz.demo.dubbo.rpc.service.StorageService;
@IocBean
public class BusinessServiceImpl implements BusinessService {
private static final Log log = Logs.get();
@Inject
@Reference
private StorageService storageService;
@Inject
@Reference
private OrderService orderService;
/**
* purchase
*/
@GlobalTransactional(timeoutMills = 300000, name = "dubbo-demo-tx")
public void purchase(String userId, String commodityCode, int orderCount, boolean dofail) {
log.info("purchase begin ... xid: " + RootContext.getXID());
storageService.deduct(commodityCode, orderCount);
orderService.create(userId, commodityCode, orderCount);
// for test
if (dofail)
throw new RuntimeException("just make it failed");
}
}

View File

@ -0,0 +1,14 @@
server.port=8080
server.host=0.0.0.0
dubbo.application.name=dubbo-fescar-web
dubbo.registry.address=zookeeper://127.0.0.1:2181
dubbo.protocol.name=dubbo
dubbo.application.qos.enable=false
jdbc.url=jdbc:mysql://127.0.0.1/fescar_demo
jdbc.username=root
jdbc.password=root
fescar.applicationId=dubbo-fescar-web
fescar.txServiceGroup=my_test_tx_group

View File

@ -0,0 +1,7 @@
log4j.rootLogger=debug,Console
log4j.logger.org.eclipse.jetty=info
log4j.appender.Console=org.apache.log4j.ConsoleAppender
log4j.appender.Console.layout=org.apache.log4j.PatternLayout
log4j.appender.Console.layout.ConversionPattern=[%-5p] %d{HH:mm:ss.SSS} %l - %m%n

View File

@ -0,0 +1,65 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Fescar分布式事务演示</title>
<script type="text/javascript" src="vue.js"></script>
<script type="text/javascript" src="jquery-3.3.1.min.js"></script>
</head>
<body>
<div id="app">
<div>
<span>当前余额: </span><input v-model="account_money" disabled="disabled">
</div>
<div>
<span>剩余库存: </span><input v-model="storage_count" disabled="disabled">
</div>
<div>
<button @click="buyit(false)">购买并成功</button>
</div>
<div>
<button @click="buyit(true)">购买但失败</button>
</div>
<div>
<button @click="dataReload">刷新</button>
</div>
</div>
</body>
<script type="text/javascript">
var _app = new Vue({
el : "#app",
data : {
account_money : 0,
storage_count : 0
},
methods : {
dataReload : function() {
$.ajax({
url : "api/info",
success : function(re) {
if (re && re.ok) {
_app.account_money = re.data.account.money;
_app.storage_count = re.data.storage.count;
}
}
});
},
buyit : function(dofail) {
$.ajax({
url : "api/purchase?userId=U100001&commodityCode=C00321&orderCount=1&dofail=" + dofail,
success : function(re) {
if (re && re.ok) {
alert("真的是购买成功");
}
else {
alert("真的是购买失败");
}
_app.dataReload();
}
});
}
}
});
_app.dataReload();
</script>
</html>

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,27 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.nutz</groupId>
<artifactId>nutzboot-demo</artifactId>
<version>2.3.3-SNAPSHOT</version>
</parent>
<artifactId>nutzboot-demo-dubbo-fescar</artifactId>
<packaging>pom</packaging>
<modules>
<module>nutzboot-demo-dubbo-fescar-common</module>
<module>nutzboot-demo-dubbo-fescar-web</module>
<module>nutzboot-demo-dubbo-fescar-order</module>
<module>nutzboot-demo-dubbo-fescar-account</module>
<module>nutzboot-demo-dubbo-fescar-storage</module>
<module>nutzboot-demo-dubbo-fescar-business</module>
</modules>
<properties>
</properties>
<dependencies>
<dependency>
<groupId>org.nutz</groupId>
<artifactId>nutzboot-core</artifactId>
</dependency>
</dependencies>
</project>

View File

@ -11,15 +11,15 @@
<artifactId>nutzboot-starter-fescar</artifactId>
<name>nutzboot-starter-fescar</name>
<dependencies>
<dependency>
<groupId>com.alibaba.fescar</groupId>
<artifactId>fescar-rm-datasource</artifactId>
<version>${fescar.version}</version>
</dependency>
<dependency>
<groupId>com.alibaba.fescar</groupId>
<artifactId>fescar-spring</artifactId>
<version>${fescar.version}</version>
</dependency>
<dependency>
<groupId>com.alibaba.fescar</groupId>
<artifactId>fescar-rm-datasource</artifactId>
<version>${fescar.version}</version>
</dependency>
<dependency>
<groupId>com.alibaba.fescar</groupId>
<artifactId>fescar-spring</artifactId>
<version>${fescar.version}</version>
</dependency>
</dependencies>
</project>

View File

@ -1,8 +1,12 @@
package org.nutz.boot.starter.fescar;
import java.sql.Connection;
import java.sql.Statement;
import javax.sql.DataSource;
import org.nutz.boot.AppContext;
import org.nutz.boot.annotation.PropDoc;
import org.nutz.boot.starter.ServerFace;
import org.nutz.dao.impl.NutDao;
import org.nutz.ioc.impl.PropertiesProxy;
@ -26,6 +30,15 @@ public class FescarStarter implements ServerFace {
protected static final String PRE = "fescar.";
@PropDoc(value="fescar应用id", need=true)
public static String PROP_APPID = PRE + "applicationId";
@PropDoc(value="fescar事务组", need=true)
public static String PROP_TXGROUP = PRE + "txServiceGroup";
@PropDoc(value="自动创建undo表", defaultValue="true")
public static String PROP_CREATE_UNDO = PRE + "create_undo_table";
@Inject
protected PropertiesProxy conf;
@ -49,6 +62,9 @@ public class FescarStarter implements ServerFace {
log.info("Global transaction is disabled.");
return;
}
applicationId = conf.check(PROP_APPID);
txServiceGroup = conf.check(PROP_TXGROUP);
log.infof("fescar applicationId=%s txServiceGroup=%s", applicationId, txServiceGroup);
initClient();
@ -57,12 +73,30 @@ public class FescarStarter implements ServerFace {
log.error("only DruidDataSource is support by fescar!!!");
throw new RuntimeException("only DruidDataSource is support by fescar!!!");
}
if (conf.getBoolean(PROP_CREATE_UNDO, true)) {
try (Connection conn = ds.getConnection()) {
Statement st = conn.createStatement();
st.execute("CREATE TABLE IF NOT EXISTS " + "`undo_log` (\r\n" +
" `id` bigint(20) NOT NULL AUTO_INCREMENT,\r\n" +
" `branch_id` bigint(20) NOT NULL,\r\n" +
" `xid` varchar(100) NOT NULL,\r\n" +
" `rollback_info` longblob NOT NULL,\r\n" +
" `log_status` int(11) NOT NULL,\r\n" +
" `log_created` datetime NOT NULL,\r\n" +
" `log_modified` datetime NOT NULL,\r\n" +
" `ext` varchar(100) DEFAULT NULL,\r\n" +
" PRIMARY KEY (`id`),\r\n" +
" UNIQUE KEY `ux_undo_log` (`xid`,`branch_id`)\r\n" +
") ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8");
st.close();
}
}
DataSourceProxy proxy = new DataSourceProxy((DruidDataSource) ds, "DEFAULT");
DataSourceManager.get().registerResource(proxy);
if (appContext.getIoc().has("dao")) {
log.info("looking for NutDao instance and replace DataSource");
NutDao dao = appContext.getIoc().get(NutDao.class, "dao");
dao.setDataSource(ds);
dao.setDataSource(proxy);
}
else {
log.info("NutDao instance not found, skip it");

View File

@ -12,7 +12,7 @@ import org.nutz.ioc.loader.annotation.IocBean;
import com.alibaba.fescar.spring.annotation.GlobalLock;
@IocBean
@IocBean(name = "$aop_fescar_GlobalLock")
public class FescarLockAopMaker extends SimpleAopMaker<GlobalLock> {
public List<? extends MethodInterceptor> makeIt(GlobalLock t, Method method, Ioc ioc) {
@ -24,7 +24,7 @@ public class FescarLockAopMaker extends SimpleAopMaker<GlobalLock> {
public String[] getName() {
return new String[0];
}
public boolean has(String name) {
return false;
}

View File

@ -14,7 +14,7 @@ import com.alibaba.fescar.spring.annotation.GlobalTransactional;
import com.alibaba.fescar.tm.api.DefaultFailureHandlerImpl;
import com.alibaba.fescar.tm.api.FailureHandler;
@IocBean
@IocBean(name="$aop_fescar_GlobalTransactional")
public class FescarTransAopMaker extends SimpleAopMaker<GlobalTransactional> {
private static FailureHandler DFT = new DefaultFailureHandlerImpl();

View File

@ -930,6 +930,11 @@
<artifactId>nutzboot-starter-servicecomb</artifactId>
<version>${nutzboot.version}</version>
</dependency>
<dependency>
<groupId>org.nutz</groupId>
<artifactId>nutzboot-starter-fescar</artifactId>
<version>${nutzboot.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
<repositories>