Java高并发秒杀API之web层1

4.交换逻辑编程

----4.1 cookies登陆交互-------------------------------------------------

注意:js的文件夹不能放在WEB-INF下,否则访问不到

参照:jsp文件引入js文件的方式(项目部署于web容器中)http://www.cnblogs.com/tomspapaya/p/3502563.html

 

    webapp-

  resources-script/sekill.js

  WEB-INF-

    jsp/common

     detail.jsp

  引入地址为<script src="/seckill/resources/script/seckill.js" type="text/javascript"></script>

URL:------------------------------------------------------------------------------------------

Eclipse中,seckill启动时地址就是http://localhost:8080/seckill/为index.jsp

  @Controller

      @RequestMapping("/seckill")

       public class SeckillController {

去掉@RequestMapping("/seckill"):list页面为http://localhost:8080/seckill/list

添加@RequestMapping("/seckill"):地址会变为http://localhost:8080/seckill/seckill/list

 SecController.java:
package org.seckill.web;

import java.util.Date;
import java.util.List;

import org.seckill.dto.Exposer;
import org.seckill.dto.SeckillExecution;
import org.seckill.dto.SeckillResult;
import org.seckill.entity.Seckill;
import org.seckill.enums.SeckillStatEnum;
import org.seckill.exception.RepeatKillExeception;
import org.seckill.exception.SeckillCloseException;
import org.seckill.service.SeckillService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.CookieValue;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

@Controller//類似@Service @component 
//@RequestMapping("/seckill")
//url:/模塊/資源/{id}/細分 http://localhost:8080/seckill/seckill/list
//去掉@RequestMapping("/seckill")变为http://localhost:8080/seckill/list
public class SeckillController {
    
    private final Logger logger = LoggerFactory.getLogger(this.getClass());
    
    @Autowired
    private SeckillService seckillService;
    
    @RequestMapping(value="/list",method = RequestMethod.GET)
    //二級URL
    public String list(Model model){
        //獲取列表頁
        List<Seckill> list = seckillService.getSeckillList();
        model.addAttribute("list",list);
        //list.jsp + model = ModelAndView
        return "list";//spring-web.xml配置了prefix和suffix ->WEB-INF/jsp/list.jsp
        
    }
    
    //
    @RequestMapping(value = "/{seckillId}/detail",method = RequestMethod.GET)
    //也可不写@PathVariable("seckillId"),默认能识别出,但最好还写出
    /*使用基本类型接收数据还是用包装类?
        使用@PathVariable时注意两点:
        1:参数接收类型使用基本类型
        2:不用基本类型时,给defaultValue值
        推荐使用包装类*/
    public String detail(@PathVariable("seckillId")Long seckillId,Model model){
        //null时,redirect到list.jsp
        if(seckillId == null){
            return "redirect:/seckill/list";
        }
        Seckill seckill = seckillService.getById(seckillId);
        if(seckill == null){
            return "forward:/seckill/list";
        }
        model.addAttribute("seckill",seckill);
        return "detail";
    }
    
    /*ajax json   RequestMethod.POST直接输入地址无效
     * @ResponseBody 当springmvc看到@ResponseBody的时候会将SeckillResult<Exposer>返回值封装成json

     * produces = {"application/json;charset=UTF-8"}解决json中的数据乱码问题
     * */
    @RequestMapping(value = "/{seckillId}/exposer",
            method = RequestMethod.POST,
            produces = {"application/json;charset=UTF-8"})
    @ResponseBody
    //public void/*TODO*/ exposer(Long seckillId){
    public SeckillResult<Exposer> exposer(Long seckillId){

        SeckillResult<Exposer> result;
        try{
            Exposer exposer =seckillService.exportSeckillUrl(seckillId);
            result = new SeckillResult<Exposer>(true,exposer);
        }catch (Exception e){
            logger.error(e.getMessage(),e);
            result = new SeckillResult<Exposer>(false,e.getMessage());
        }
        return result;
    }
    
    @RequestMapping(value = "/{seckillId}/{md5}/execution",
            method = RequestMethod.POST,
            produces = {"application/json;charset=UTF-8"})
    public SeckillResult<SeckillExecution> execute(@PathVariable("seckillId")Long seckillId,
                                                   @PathVariable("md5")String md5,
                                                   @CookieValue(value = "killPhone",required = false)Long phone){
        /*请求的requestpattern中没有这个cookie killPhone时,springMVC 会报错,required = false表示killPhone不是必须,就不会报错,验证逻辑放入程序*/
        //springMVC valid
        if(phone == null){
            return new SeckillResult<SeckillExecution>(false,"未注册");
        }
        SeckillResult<SeckillExecution> result;
        try{
            SeckillExecution execution = seckillService.executeSeckill(seckillId, phone, md5);
            return new SeckillResult<SeckillExecution>(true,execution);
        } catch (SeckillCloseException e) {
            SeckillExecution execution = new SeckillExecution(seckillId,SeckillStatEnum.REPEAT_KILL);
            return new SeckillResult<SeckillExecution>(false,execution);
        } catch (RepeatKillExeception e) {
            SeckillExecution execution = new SeckillExecution(seckillId,SeckillStatEnum.END);
            return new SeckillResult<SeckillExecution>(false,execution);
        }catch (Exception e){
            logger.error(e.getMessage(),e);
            SeckillExecution execution = new SeckillExecution(seckillId,SeckillStatEnum.INNER_ERROR);
            return new SeckillResult<SeckillExecution>(false,execution);
        }
    } 
    @RequestMapping(value = "/time/now",
                method = RequestMethod.GET)
    public SeckillResult<Long> time(){
        Date now = new Date();
        return new SeckillResult(true,now.getTime());
    }

}

 

 

 detail.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!-- 引入jstl -->
<%@include file="common/tag.jsp" %>
<!DOCTYPE html>
<html>
   <head>
      <title>秒杀詳情</title>
    <%@include file="common/head.jsp" %>
   </head>
   <body>
   <!-- 頁面顯示部分 :推荐放入一个div中-->
           <div class="container">
               <div class="panel panel-default">
                   <div class="panel-heading text-center">
                       <h2>秒杀详情</h2>
                       <div class="panel-heading">${seckill.name}</div>
                   </div>
                   <div class="panel-body">
                    <!-- 开发交互时补全 -->
                        <h2 class="text-danger">
                            <!-- time icon -->
                            <span class="glyphicon glyphicon-time"></span>
                            <!-- time count -->
                            <span class="glyphicon" id="seckill-box"></span>
                        </h2>
                   </div>
               </div>
           </div>
           <!-- pop layer :in put phone number ,fade 隐藏-->
           <div id="killPhoneModal" class="modal fade">
               <div class="modal-dialog">
                 <div class="modal-content">
                 <div class="modal-header">
                   <h3 class="modal-title text-center">
                       <span class="glyphicon glyphicon-phone"></span>
                   </h3>
                 </div>
                 <div class="modal-body">
                   <div class="row">
                       <div class="col-xs-8 col-xs-offset-2">
                         <input type="text" name="killPhone" id="killPhoneKey"
                          placeholder="in put phone number" class="form-control">
                       </div>
                   </div>
                 </div>
                 <div class="modal-footer">
                   <!-- 验证信息 -->
                   <span id="killPhoneMessage" jclass="glphicon"></span>
                   <button type="button" id="killPhoneBtn" class="btn btn-success">
                     <span class="glyphicon glyphicon-phone"></span>
                     submit
                   </button>
                   </div>
                 </div>                  
                 </div>
               </div>
           </div>
   </body> 
<!-- jQuery文件。务必在bootstrap.min.js 之前引入 -->
<script src="https://cdn.bootcss.com/jquery/2.1.1/jquery.min.js"></script>
<!-- 最新的 Bootstrap 核心 JavaScript 文件 -->
<script src="https://cdn.bootcss.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<!-- 使用CDN获取公共js http://www.bootcdn.cn
    使用CDN原因:使用可靠的CDN比发布到项目里更可靠(使用方式搜索 jquery-count ,把script标签复制到页面)
 -->
 <!-- jquery cookie 操作plugin -->
 <script src="https://cdn.bootcss.com/jquery-cookie/1.4.1/jquery.cookie.min.js"></script>
<!-- 搜索jquery-count得到 -->
<!-- jquery countDown 倒计时plugin -->
<script src="https://cdn.bootcss.com/jquery-countdown/2.0.1/jquery.countdown.min.js"></script>
<!-- 开始编写交互逻辑
 注意: text="text/javascript"/> 浏览器会不加载 虽然HTML语法是对的,js有特殊性必须写成如下-->
<script src="/seckill/resources/script/seckill.js" type="text/javascript"></script>
<script text="text/javascript">
$(function(){
    console.log("!!!!!!detail.jsp");
    //使用EL表达式传入参数
    seckill.detail.init({
        seckillId : ${seckill.seckillId},
        startTime : ${seckill.startTime.time},//毫秒
        endTime : ${seckill.endTime.time}
    });
});
</script>
</html>
//存放主要交换逻辑js代码
//javascript模块化
//seckill.detail.init(params);
var seckill={
    //封装秒杀相关ajax的url    
    URL:{
        
    },
    //验证手机号 isNaN(phone)数字验证
    validatePhone:function(phone){
        if(phone && phone.length == 11 && !isNaN(phone)){
            return true;
        } else {
            return false;
        }
    },
    //详情页秒杀逻辑
    detail:{
        
        //详情页初始化
        init:function(params){
            console.log("!!!!!!detail");
            //手机验证和登录,计时交互
            //规划交互流程
            //在cookie中查找手机号
            var killPhone = $.cookie('killPhone');
            var startTime = params['startTime'];
            var endTime = params['endTime'];
            var seckillId = params['seckillId'];
            //验证手机号
            if(!seckill.validatePhone(killPhone)){
                //绑定phone
                //控制输出
                console.log("!!!!!!killPhoneModal");
                var killPhoneModal = $('#killPhoneModal');
                //modal bootstrap组件,调用方法显示弹出层
                killPhoneModal.modal({
                    show:true,//show pop layer
                    backdrop:'static',//禁止位置关闭
                    keyboard:false//关闭键盘事件
                });
                $('#killPhoneBtn').click(function(){
                    var inputPhone =$('#killPhoneKey').val();
                    console.log('inputPhone:'+inputPhone);
                    if(seckill.validatePhone(inputPhone)){
                        //电话写入cookie 
                        //  {expires:7,path:'/seckill'}有效期7天,在/seckill路径下有效
                        $.cookie('killPhone',inputPhone,{expires:7,path:'/seckill'});
                        //刷新页面
                        window.location.reload();
                    } else{
                        //1.隐藏节点,2编辑节点,3显示内容
                        $('#killPhoneMessage').hide().html('<laber class="label label-danger">phone number is wrong</laber>').show(300);
                    }
                });
                //已经登录
            }
        }
    }
        
}

 

 

 

 

 

----4.1 cookies登陆交互-------------------------------------------------

 

posted @ 2017-07-21 10:29  charles999  阅读(349)  评论(0编辑  收藏  举报