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登陆交互-------------------------------------------------