成果需求:设计一个秒杀系统
初始方案
商品表设计:热销商品提供应用户秒杀,有初始库存。
@Entity
public class SecKillGoods implements Serializable{
@Id
private String id;
/**
* 剩余库存
*/
private Integer remainNum;
/**
* 秒杀商品名称
*/
private String goodsName;
}
秒杀订单表设计:记录秒杀乐成的订单环境
@Entity
public class SecKillOrder implements Serializable {
@Id
@GenericGenerator(name = "PKUUID", strategy = "uuid2")
@GeneratedValue(generator = "PKUUID")
@Column(length = 36)
private String id;
//用户名称
private String consumer;
//秒杀产物编号
private String goodsId;
//购置数量
private Integer num;
}
Dao设计:主要就是一个淘汰库存要领,图纸加密,其他CRUD利用JPA自带的要领
public interface SecKillGoodsDao extends JpaRepository<SecKillGoods,String>{
@Query("update SecKillGoods g set g.remainNum = g.remainNum - ?2 where g.id=?1")
@Modifying(clearAutomatically = true)
@Transactional
int reduceStock(String id,Integer remainNum);
}
数据初始化以及提供生存订单的操纵:
@Service
public class SecKillService {
@Autowired
SecKillGoodsDao secKillGoodsDao;
@Autowired
SecKillOrderDao secKillOrderDao;
/**
* 措施启动时:
* 初始化秒杀商品,清空订单数据
*/
@PostConstruct
public void initSecKillEntity(){
secKillGoodsDao.deleteAll();
secKillOrderDao.deleteAll();
SecKillGoods secKillGoods = new SecKillGoods();
secKillGoods.setId("123456");
secKillGoods.setGoodsName("秒杀产物");
secKillGoods.setRemainNum(10);
secKillGoodsDao.save(secKillGoods);
}
/**
* 购置乐成,生存订单
* @param consumer
* @param goodsId
* @param num
*/
public void generateOrder(String consumer, String goodsId, Integer num) {
secKillOrderDao.save(new SecKillOrder(consumer,goodsId,num));
}
}
下面就是controller层的设计
@Controller
public class SecKillController {
@Autowired
SecKillGoodsDao secKillGoodsDao;
@Autowired
SecKillService secKillService;
/**
* 普通写法
* @param consumer
* @param goodsId
* @return
*/
@RequestMapping("/seckill.html")
@ResponseBody
public String SecKill(String consumer,String goodsId,Integer num) throws InterruptedException {
//查找出用户要买的商品
SecKillGoods goods = secKillGoodsDao.findOne(goodsId);
//假如有这么多库存
if(goods.getRemainNum()>=num){
//模仿网络延时
Thread.sleep(1000);
//先减去库存
secKillGoodsDao.reduceStock(num);
//生存订单
secKillService.generateOrder(consumer,goodsId,num);
return "购置乐成";
}
return "购置失败,库存不敷";
}
}
上面是全部的基本筹备,下面利用一个单位测试要领,模仿高并发下,许多人来购置同一个热门商品的环境。
@Controller
public class SecKillSimulationOpController {
final String takeOrderUrl = "http://127.0.0.1:8080/seckill.html";
/**
* 模仿并发下单
*/
@RequestMapping("/simulationCocurrentTakeOrder")
@ResponseBody
public String simulationCocurrentTakeOrder() {
//httpClient工场
final SimpleClientHttpRequestFactory httpRequestFactory = new SimpleClientHttpRequestFactory();
//开50个线程模仿并发秒杀下单
for (int i = 0; i < 50; i++) {
//购置人姓名
final String consumerName = "consumer" + i;
new Thread(new Runnable() {
@Override
public void run() {
ClientHttpRequest request = null;
try {
URI uri = new URI(takeOrderUrl + "?consumer=consumer" + consumerName + "&goodsId=123456&num=1");
request = httpRequestFactory.createRequest(uri, HttpMethod.POST);
InputStream body = request.execute().getBody();
BufferedReader br = new BufferedReader(new InputStreamReader(body));
String line = "";
String result = "";
while ((line = br.readLine()) != null) {
result += line;//得到页面内容或返回内容
}
System.out.println(consumerName+":"+result);
} catch (Exception e) {
e.printStackTrace();
}
}
}).start();
}
return "simulationCocurrentTakeOrder";
}
}