成果需求:设计一个秒杀系统
初始方案
商品表设计:热销商品提供应用户秒杀,有初始库存。
@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"; } }