发货系统和订单系统基于Spring-Boot项目,其中springboot整合了mybatis,log4j2等 ,项目中使用到了generator代码生成工具,生成dao/domain/mapper.xml文件
发货系统模拟(target-service)
Controller层实现
/**
* @description: 模拟仓库发货类
* @author: fan
* @create: 2018-08-14 09:53
**/
@RestController
@RequestMapping("/bank")
public class BankController {
private Logger logger = LoggerFactory.getLogger(getClass());
/**
* @Description: 远程提供发货处理接口
* @Param: [orderid]
* @return: java.lang.String
* @Author: fan
* @Date: 2018/8/15 14:05
*/
@RequestMapping(value = "/handleOrder")
public String handleOrder(@RequestParam(required = false) String orderid){
logger.info("收到订单号:" + orderid + ",正在出货处理中……");
try {
Thread.currentThread().sleep(10000);
}catch (Exception e){
logger.error("出现错误了"+e.getMessage());
e.printStackTrace();
return "-1";
}
return "0";
}
}
订单系统模拟(client-service)
mapper.xml文件
<select id="findOrderById" resultMap="result">
SELECT * FROM t_order where orderId = #{orderid};
</select>
<update id="update" parameterType="com.gara.lock_demo.domain.Order"
flushCache="true">
<![CDATA[
update t_order
set orderStatus =
#{orderStatus,jdbcType=VARCHAR}
where
orderId = #{orderId,jdbcType=VARCHAR}
]]>
</update>
<insert id="updateByVersion" parameterType="com.gara.lock_demo.domain.Order"
flushCache="true">
<![CDATA[
update t_order
set orderStatus =
#{orderStatus,jdbcType=VARCHAR},
version = version+1
where
orderId = #{orderId,jdbcType=VARCHAR} and version = #{version}
]]>
</insert>
Controller实现
/**
* @description: 消费端
* @author: fan
* @create: 2018-08-14 14:33
**/
/*
接口层:对外开放接口路径及地址 http://127.0.0.1:8080/order/sendOrder?orderid=1
*/
@RestController
@RequestMapping("/order")
public class CustController {
@Autowired
private OrderService orderService;
@RequestMapping("/query")
@ResponseBody
public Object query(@RequestParam(required = true) String orderid) {
Order order = orderService.findOrderById(orderid);
return order;
}
@RequestMapping("/sendOrder")
@ResponseBody
public String sendOrder(@RequestParam(required = true) String orderid) {
Order order = orderService.findOrderById(orderid);
return orderService.sendOrder(order);
}
@RequestMapping("/sendOrderByTemplate")
@ResponseBody
public String sendOrderByTemplate(@RequestParam(required = true) String orderid) {
Order order = orderService.findOrderById(orderid);
return orderService.sendOrderByTemplate(order);
}
@RequestMapping("/sendOrderByTemplateThread")
@ResponseBody
public String sendOrderByTemplateThread(@RequestParam(required = true) String orderid) {
Order order = orderService.findOrderById(orderid);
for (int i = 0; i < 6; i++) {
Thread t = new Thread(new ExcuteThread(order));
t.start();
}
return null;
}
private class ExcuteThread implements Runnable {
private Order order;
public ExcuteThread(Order order) {
this.order = order;
}
@Override
public void run() {
orderService.sendOrderByTemplateThread(order);
}
}
}
使用RestTemplate.getForEntity()方法,调用远程发货接口
@Autowired
private RestTemplate restTemplate;
/**
* @Description: 获取发货系统返回数据
* @Param: [url, orderid]
* @return: java.lang.String
* @Author: fan
* @Date: 2018/8/15 17:12
*/
@Override
public String invoke(String url, String orderid) {
return restTemplate.getForEntity(url+orderid,String.class).getBody();
}
Service实现(sendOrderByTemplateThread方法)
重点: 这里做了一个判断,对每次传入的订单实体,会进行一次数据库update操作,只有第一次进入的线程才会返回true,后续的重复请求返回false , 从而实现乐观锁 1 == orderMapper.updateByVersion(order)
/**
* @Description: 基于状态机的乐观锁
* @Param: [order]
* @return: java.lang.String
* @Author: GaraYing
* @Date: 2018/8/15 9:35
*/
@Override
public String sendOrderByTemplateThread(Order order) {
String orderId = order.getOrderId();
// 只有第一个操作返回true,其他返回false
Boolean lock = template.execute(new TransactionCallback<Boolean>() {
@Override
public Boolean doInTransaction(TransactionStatus transactionStatus) {
Order order = new Order();
order.setOrderId(orderId);
order.setOrderStatus("4");//订单处理中
order.setVersion(0);
// orderMapper.update(order);
return 1 == orderMapper.updateByVersion(order);//受影响的记录数
}
});
if (lock) {
// 只允许一个线程发货,其他全部拦截
String flag = transService.invoke(url, orderId);
template.execute(new TransactionCallback<Object>() {
@Override
public Object doInTransaction(TransactionStatus transactionStatus) {
Order orderFin = new Order();
orderFin.setOrderId(orderId);
orderFin.setOrderStatus(flag);//订单处理中
orderFin.setVersion(1);
// orderMapper.update(order);
orderMapper.updateByVersion(orderFin);//受影响的记录数
return null;
}
});
} else {
logger.error("lockFail************" + order.getOrderId());
}
return null;
}
实体类参考
/**
* @description: Order订单实体类
* @author: GaraYing
* @create: 2018-08-14 10:45
**/
public class Order {
private String orderId; //订单ID
private String orderTime; // 订单时间
private Long orderMoney; // 订单金额
private String orderStatus; //订单状态:0未处理/1处理中/2处理失败/3处理成功/4处理完成
private Integer version; // 版本
public Order() {
}
public Order(String orderId, String orderTime, Long orderMoney, String orderStatus, Integer version) {
this.orderId = orderId;
this.orderTime = orderTime;
this.orderMoney = orderMoney;
this.orderStatus = orderStatus;
this.version = version;
}
public String getOrderId() {
return orderId;
}
public void setOrderId(String orderId) {
this.orderId = orderId;
}
public String getOrderTime() {
return orderTime;
}
public void setOrderTime(String orderTime) {
this.orderTime = orderTime;
}
public Long getOrderMoney() {
return orderMoney;
}
public void setOrderMoney(Long orderMoney) {
this.orderMoney = orderMoney;
}
public String getOrderStatus() {
return orderStatus;
}
public void setOrderStatus(String orderStatus) {
this.orderStatus = orderStatus;
}
public Integer getVersion() {
return version;
}
public void setVersion(Integer version) {
this.version = version;
}
@Override
public String toString() {
return "Order{" +
"orderId='" + orderId + '\'' +
", orderTime='" + orderTime + '\'' +
", orderMoney=" + orderMoney +
", orderStatus='" + orderStatus + '\'' +
", version='" + version + '\'' +
'}';
}
}
核心点总结:基于状态机的乐观锁的实现主要利用了一下核心数据库语句,当用户在前端页面,以单身狗的手速疯狂点击产生重复订单的情况下,可以保证只有第一次请求会处理并进入,即完成了只有一个线程发货,其他全部拦截
update t_order set orderStatus =#{orderStatus,jdbcType=VARCHAR},version = version+1 where orderId = #{orderId,jdbcType=VARCHAR} and version = #{version}