Java秒殺簡單設計四:service層設計


接上一篇 https://www.cnblogs.com/taiguyiba/p/9829191.html  封裝了系統傳遞的數據類和異常類

本文繼續設計service層設計:

1.SeckillService.java 

 

package com.seckill.service; import java.util.List; import com.seckill.dto.Exposer; import com.seckill.dto.SeckillExecution; import com.seckill.entity.Seckill; import com.seckill.exception.RepeatKillException; import com.seckill.exception.SeckillCloseException; import com.seckill.exception.SeckillException; /** * 三個方面:1.方法定義的粒度,參數,返回類型(return ,類型/異常) * @author kangjie * */
public interface SeckillService { /** * * 查詢所有秒殺記錄 * @return */ List <Seckill> getSeckillList(); /** * * 查詢單個秒殺記錄 * @param seckillId * @return */ Seckill getById(long seckillId); /** * 秒殺開啟時輸出秒殺接口地址 否則輸出系統時間和秒殺時間 * @param seckillId */ Exposer exportSeckillUrl(long seckillId); //執行秒殺操作
    SeckillExecution excuteSeckill(long seckillId,long userPhone,String md5) throws RepeatKillException,SeckillCloseException,SeckillException;     //執行秒殺操作by存儲過程
    SeckillExecution excuteSeckillProcedure(long seckillId,long userPhone,String md5); }

 2. SeckillServiceImpl

 秒殺事務控制,在函數中如果更新出現問題,就會拋出異常,進行事務回滾。

package com.seckill.service.impl; import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; import org.apache.commons.collections.MapUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.util.DigestUtils; import com.seckill.dao.SeckillDao; import com.seckill.dao.SuccessKilledDao; import com.seckill.dao.cache.RedisDao; import com.seckill.dto.Exposer; import com.seckill.dto.SeckillExecution; import com.seckill.entity.Seckill; import com.seckill.entity.SuccessKilled; import com.seckill.enums.SeckillStateEnum; import com.seckill.exception.RepeatKillException; import com.seckill.exception.SeckillCloseException; import com.seckill.exception.SeckillException; import com.seckill.service.SeckillService; @Service public class SeckillServiceImpl implements SeckillService { private Logger logger=LoggerFactory.getLogger(this.getClass()); @Autowired private SeckillDao seckillDao; @Autowired private SuccessKilledDao successKilledDao; @Autowired private RedisDao redisDao; //md5鹽值,用於混淆md5
    private final String salt = "!@#!@#!@#$ASDFASDFzxcv_|+)+)(("; @Override public List<Seckill> getSeckillList() { // TODO Auto-generated method stub
        return seckillDao.queryAll(0, 4); } @Override public Seckill getById(long seckillId) { // TODO Auto-generated method stub
         return seckillDao.queryById(seckillId); } @Override public Exposer exportSeckillUrl(long seckillId) { // TODO Auto-generated method stub //訪問redis:緩存優化,超時的基礎上維護一致性
        Seckill seckill = redisDao.getSeckill(seckillId); if(seckill == null) { //訪問數據庫
            seckill = seckillDao.queryById(seckillId); if(seckill == null) { return new Exposer(false, seckillId); }else { logger.error("放入redis中: " + seckill.toString()); redisDao.putSeckill(seckill); } } Date startTime = seckill.getStartTime(); Date endTime = seckill.getEndTime(); Date nowTime = new Date(); if(nowTime.getTime() > endTime.getTime() ||nowTime.getTime() < startTime.getTime()) { return new Exposer(false, nowTime.getTime(), startTime.getTime(), endTime.getTime(),seckillId); } String md5 = getMD5(seckillId); return new Exposer(true, md5, seckillId); // return null;
 } private String getMD5(long seckillId) { String base = seckillId + "/" + salt; String md5 =  DigestUtils.md5DigestAsHex(base.getBytes()); return md5; } @Override @Transactional public SeckillExecution excuteSeckill(long seckillId, long userPhone, String md5) throws RepeatKillException, SeckillCloseException, SeckillException { // TODO Auto-generated method stub
        if(md5 == null || !md5.equals(getMD5(seckillId))) { throw new SeckillException("seckill data rewirte"); } try { int insertCount = successKilledDao.insertSuccessKilled(seckillId, userPhone); if (insertCount <= 0) { // 重復秒殺
                throw new RepeatKillException("repeat seckill"); } else { int updateCount = seckillDao.reduceNumber(seckillId, new Date()); if (updateCount <= 0) { throw new SeckillCloseException("seckill closed"); } else { // 秒殺成功
                    SuccessKilled successKilled = successKilledDao.queryByIdWithSeckill(seckillId, userPhone); return new SeckillExecution(seckillId,SeckillStateEnum.SUCCESSD, successKilled); } } } catch (RepeatKillException e) { // TODO: handle exception
 logger.error(e.getMessage(),e); throw new RepeatKillException("repeat seckill"); }catch (SeckillCloseException e) { // TODO: handle exception
 logger.error(e.getMessage(),e); throw new SeckillCloseException("seckill closed"); }catch (Exception e) { logger.error(e.getMessage(), e);; throw new SeckillException("Inner error: " + e.getMessage()); } } @Override public SeckillExecution excuteSeckillProcedure(long seckillId, long userPhone, String md5){ // TODO Auto-generated method stub
        if(md5 == null || !md5.equals(getMD5(seckillId))) { return new SeckillExecution(seckillId,SeckillStateEnum.DATA_REWRITE); } Date killTime = new Date(); Map<String,Object> map = new HashMap<String,Object>(); map.put("seckillId", seckillId); map.put("phone", userPhone); map.put("killTime", killTime); map.put("result", null); try { seckillDao.killByProcedure(map); //獲取result
            int result = MapUtils.getInteger(map, "result",-2); if(result == 1) { SuccessKilled sk = successKilledDao.queryByIdWithSeckill(seckillId, userPhone); return new SeckillExecution(seckillId,SeckillStateEnum.SUCCESSD,sk); }else { return new SeckillExecution(seckillId, SeckillStateEnum.stateOf(result)); } } catch (Exception e) { // TODO Auto-generated catch block
 logger.error(e.getMessage(),e); return new SeckillExecution(seckillId, SeckillStateEnum.INNER_ERROR); }
 } }

 

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM