欢迎访问昆山宝鼎软件有限公司网站! 设为首页 | 网站地图 | XML | RSS订阅 | 宝鼎邮箱 | 宝鼎售后问题提交 | 后台管理


新闻资讯

MENU

软件开发知识

却造成了很 昆山软件定制开发 大的改变

点击: 次  来源:宝鼎软件 时间:2017-08-04

原文出处: 常大皮卡丘

成果需求:设计一个秒杀系统

初始方案

商品表设计:热销商品提供应用户秒杀,有初始库存。

@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";
    }

}