getSeckillList();
25 |
26 | /**
27 | * 查询单个秒杀记录
28 | *
29 | * @param seckillId
30 | * @return
31 | */
32 | Seckill getById(long seckillId);
33 |
34 | /**
35 | * 秒杀开启时输出秒杀接口地址,否则输出系统时间和秒杀时间
36 | *
37 | * @param seckillId
38 | * @return
39 | */
40 | Exposer exportSeckillUrl(long seckillId);
41 |
42 | /**
43 | * 执行秒杀操作
44 | *
45 | * @param seckillId
46 | * @param userPhone
47 | * @param md5
48 | * @return
49 | * @throws SeckillException
50 | * @throws RepeatKillException
51 | * @throws SeckillCloseException
52 | */
53 | SeckillExecution executeSeckill(long seckillId, long userPhone, String md5)
54 | throws SeckillException, RepeatKillException, SeckillCloseException;
55 |
56 | /**
57 | * 执行秒杀操作by存储过程
58 | *
59 | * @param seckillId
60 | * @param userPhone
61 | * @param md5
62 | * @return
63 | * @throws SeckillException
64 | * @throws RepeatKillException
65 | * @throws SeckillCloseException
66 | */
67 | SeckillExecution executeSeckillProcedure(long seckillId, long userPhone, String md5)
68 | throws SeckillException, RepeatKillException, SeckillCloseException;
69 |
70 | }
--------------------------------------------------------------------------------
/seckill-core/.gitignore:
--------------------------------------------------------------------------------
1 | *.class
2 |
3 | # Mobile Tools for Java (J2ME)
4 | .mtj.tmp/
5 |
6 | # Package Files #
7 | *.jar
8 | *.war
9 | *.ear
10 |
11 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
12 | hs_err_pid*
13 |
--------------------------------------------------------------------------------
/seckill-core/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 | seckill
7 | com.imooc
8 | 0.0.1-SNAPSHOT
9 |
10 | 4.0.0
11 |
12 | seckill-core
13 | war
14 | seckill-dubbo-consumer Maven Webapp
15 | http://maven.apache.org
16 |
17 |
18 |
19 | org.apache.maven.plugins
20 | maven-compiler-plugin
21 |
22 | 1.8
23 | 1.8
24 |
25 |
26 |
27 |
28 |
29 |
30 | com.imooc
31 | seckill-model
32 | 0.0.1-SNAPSHOT
33 |
34 |
35 | com.imooc
36 | seckill-client
37 | 0.0.1-SNAPSHOT
38 |
39 |
40 |
41 | com.alibaba
42 | dubbo
43 | 2.5.7
44 |
45 |
46 | spring
47 | org.springframework
48 |
49 |
50 |
51 |
52 |
53 |
54 | org.apache.zookeeper
55 | zookeeper
56 | 3.5.3-beta
57 |
58 |
59 | log4j
60 | log4j
61 |
62 |
63 |
64 |
65 | com.101tec
66 | zkclient
67 | 0.8
68 |
69 |
70 |
71 |
--------------------------------------------------------------------------------
/seckill-core/src/main/java/com/imooc/aop/LogAOP.java:
--------------------------------------------------------------------------------
1 | package com.imooc.aop;
2 |
3 |
4 | import org.aspectj.lang.ProceedingJoinPoint;
5 | import org.aspectj.lang.annotation.Around;
6 | import org.aspectj.lang.annotation.Aspect;
7 | import org.aspectj.lang.annotation.Pointcut;
8 | import org.slf4j.Logger;
9 | import org.slf4j.LoggerFactory;
10 | import org.springframework.stereotype.Component;
11 | import org.springframework.validation.BindingResult;
12 |
13 | /**
14 | * @author yan
15 | *
16 | * 采用AOP的方式处理参数问题。
17 | */
18 | @Component
19 | @Aspect
20 | public class LogAOP {
21 |
22 | private final Logger LOG = LoggerFactory.getLogger(this.getClass());
23 |
24 | @Pointcut("execution(* com.imooc.web.*.*(..))")
25 | public void aopMethod() {
26 | }
27 |
28 | @Around("aopMethod()")
29 | public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
30 | String classType = joinPoint.getTarget().getClass().getName();
31 | //运用反射的原理创建对象
32 | Class> clazz = Class.forName(classType);
33 | String clazzName = clazz.getName();
34 | String clazzSimpleName = clazz.getSimpleName();
35 | String methodName = joinPoint.getSignature().getName();
36 | Logger logger = LoggerFactory.getLogger(clazzName);
37 | logger.info("clazzName: " + clazzName + ", methodName:" + methodName);
38 | long start = System.currentTimeMillis();
39 | LOG.info("before method invoking!");
40 | BindingResult bindingResult = null;
41 | System.out.println("---------------");
42 | System.out.println("调用类:" + clazzSimpleName);
43 | System.out.println("调用方法:" + methodName);
44 | return joinPoint.proceed();
45 | }
46 | }
--------------------------------------------------------------------------------
/seckill-core/src/main/java/com/imooc/web/SeckillController.java:
--------------------------------------------------------------------------------
1 | package com.imooc.web;
2 |
3 | import com.imooc.dto.SeckillExecution;
4 | import com.imooc.exception.SeckillCloseException;
5 | import com.imooc.dto.Exposer;
6 | import com.imooc.dto.SeckillResult;
7 | import com.imooc.entity.Seckill;
8 | import com.imooc.enums.SeckillStateEnum;
9 | import com.imooc.exception.RepeatKillException;
10 | import com.imooc.client.SeckillService;
11 | import org.slf4j.Logger;
12 | import org.slf4j.LoggerFactory;
13 | import org.springframework.beans.factory.annotation.Autowired;
14 | import org.springframework.stereotype.Controller;
15 | import org.springframework.ui.Model;
16 | import org.springframework.web.bind.annotation.*;
17 |
18 | import java.util.Date;
19 | import java.util.List;
20 |
21 | @Controller // @Service @Componet
22 | @RequestMapping("/seckill") // url:/模块/资源/{id}/细分 /seckill/list
23 | public class SeckillController {
24 |
25 | //sb
26 | private Logger logger = LoggerFactory.getLogger(this.getClass());
27 |
28 | @Autowired
29 | private SeckillService seckillService;
30 | //http://localhost:8080/seckill/seckill/list
31 | @RequestMapping(value = "/list", method = RequestMethod.GET)
32 | public String list(Model model) {
33 | // 获取列表页
34 | List list = seckillService.getSeckillList();
35 | model.addAttribute("list", list);
36 | // list.jsp + model = ModelAndView
37 | return "list";// WEB-INF/jsp/"list".jsp
38 | }
39 |
40 | @RequestMapping(value = "/{seckillId}/detail", method = RequestMethod.GET)
41 | public String detail(@PathVariable("seckillId") Long seckillId, Model model) {
42 | if (seckillId == null) {
43 | return "redirect:/seckill/list";
44 | }
45 | Seckill seckill = seckillService.getById(seckillId);
46 | if (seckill == null) {
47 | return "forward:/seckill/list";
48 | }
49 | model.addAttribute("seckill", seckill);
50 | return "detail";
51 | }
52 |
53 | // ajax json
54 | @RequestMapping(value = "/{seckillId}/exposer", method = RequestMethod.POST, produces = {
55 | "application/json; charset=utf-8" })
56 | @ResponseBody
57 | public SeckillResult exposer(@PathVariable("seckillId") Long seckillId) {
58 | SeckillResult result;
59 | try {
60 | Exposer exposer = seckillService.exportSeckillUrl(seckillId);
61 | result = new SeckillResult(true, exposer);
62 | } catch (Exception e) {
63 | logger.error(e.getMessage(), e);
64 | result = new SeckillResult(false, e.getMessage());
65 | }
66 | return result;
67 | }
68 |
69 | @RequestMapping(value = "/{seckillId}/{md5}/execution", method = RequestMethod.POST, produces = {
70 | "application/json; charset=utf-8" })
71 | @ResponseBody
72 | public SeckillResult execute(@PathVariable("seckillId") Long seckillId,
73 | @PathVariable("md5") String md5, @CookieValue(value = "killPhone", required = false) Long phone) {
74 | // springmvc valid
75 | if (phone == null) {
76 | return new SeckillResult(false, "未注册");
77 | }
78 | try {
79 | // 存储过程调用
80 | SeckillExecution execution = seckillService.executeSeckillProcedure(seckillId, phone, md5);
81 | return new SeckillResult(true, execution);
82 | } catch (RepeatKillException e) {
83 | SeckillExecution execution = new SeckillExecution(seckillId, SeckillStateEnum.REPEAT_KILL);
84 | return new SeckillResult(true, execution);
85 | } catch (SeckillCloseException e) {
86 | SeckillExecution execution = new SeckillExecution(seckillId, SeckillStateEnum.END);
87 | return new SeckillResult(true, execution);
88 | } catch (Exception e) {
89 | logger.error(e.getMessage(), e);
90 | SeckillExecution execution = new SeckillExecution(seckillId, SeckillStateEnum.INNER_ERROR);
91 | return new SeckillResult(true, execution);
92 | }
93 | }
94 |
95 | @RequestMapping(value = "/time/now", method = RequestMethod.GET)
96 | @ResponseBody
97 | public SeckillResult time() {
98 | Date now = new Date();
99 | return new SeckillResult(true, now.getTime());
100 | }
101 |
102 | }
103 |
--------------------------------------------------------------------------------
/seckill-core/src/main/resources/logback.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/seckill-core/src/main/resources/spring/applicationContext.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
--------------------------------------------------------------------------------
/seckill-core/src/main/resources/spring/spring-dubbo-config.xml:
--------------------------------------------------------------------------------
1 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/seckill-core/src/main/resources/spring/spring-dubbo-consumer.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/seckill-core/src/main/resources/spring/spring-web.xml:
--------------------------------------------------------------------------------
1 |
2 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
27 |
28 |
29 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
--------------------------------------------------------------------------------
/seckill-core/src/main/webapp/WEB-INF/jsp/common/head.jsp:
--------------------------------------------------------------------------------
1 | <%
2 | String path = request.getContextPath();
3 | String basePath = request.getScheme() + "://"
4 | + request.getServerName() + ":" + request.getServerPort()
5 | + path + "/";
6 | pageContext.setAttribute("basePath",basePath);
7 | %>
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
17 |
18 |
19 |
20 |
24 |
--------------------------------------------------------------------------------
/seckill-core/src/main/webapp/WEB-INF/jsp/common/tag.jsp:
--------------------------------------------------------------------------------
1 | <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
2 | <%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
--------------------------------------------------------------------------------
/seckill-core/src/main/webapp/WEB-INF/jsp/detail.jsp:
--------------------------------------------------------------------------------
1 | <%@ page language="java" contentType="text/html; charset=UTF-8"
2 | pageEncoding="UTF-8"%>
3 |
4 |
5 |
6 | <%@include file="common/head.jsp"%>
7 | 秒杀详情页
8 |
9 |
10 |
11 |
12 |
13 |
14 |
${seckill.name}
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
74 |
75 |
--------------------------------------------------------------------------------
/seckill-core/src/main/webapp/WEB-INF/jsp/list.jsp:
--------------------------------------------------------------------------------
1 | <%@ page language="java" contentType="text/html; charset=UTF-8"
2 | pageEncoding="UTF-8"%>
3 |
4 | <%@include file="common/tag.jsp" %>
5 |
6 |
7 |
8 | <%@include file="common/head.jsp"%>
9 | 秒杀列表页
10 |
11 |
12 |
13 |
14 |
15 |
16 |
秒杀列表
17 |
18 |
19 |
20 |
21 |
22 | 名称 |
23 | 库存 |
24 | 开始时间 |
25 | 结束时间 |
26 | 创建时间 |
27 | 详情页 |
28 |
29 |
30 |
31 |
32 |
33 | ${sk.name} |
34 | ${sk.number} |
35 |
36 |
37 | |
38 |
39 |
40 | |
41 |
42 |
43 | |
44 |
45 | link
46 | |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
--------------------------------------------------------------------------------
/seckill-core/src/main/webapp/WEB-INF/web.xml:
--------------------------------------------------------------------------------
1 |
5 |
6 |
7 |
8 | seckill-dispatcher
9 | org.springframework.web.servlet.DispatcherServlet
10 |
14 |
15 | contextConfigLocation
16 | classpath:spring/applicationContext.xml
17 |
18 |
19 |
20 | seckill-dispatcher
21 |
22 | /
23 |
24 |
25 | contextConfigLocation
26 | classpath:spring/applicationContext.xml
27 |
28 |
29 | org.springframework.web.context.ContextLoaderListener
30 |
31 |
32 |
--------------------------------------------------------------------------------
/seckill-core/src/main/webapp/resources/js/seckill.js:
--------------------------------------------------------------------------------
1 | // 存放主要交换逻辑js代码
2 | // javascript 模块化
3 | var seckill = {
4 | // 封装秒杀相关ajax的url
5 | URL : {
6 | basePath : function() {
7 | return $('#basePath').val();
8 | },
9 | now : function() {
10 | return seckill.URL.basePath() + 'seckill/time/now';
11 | },
12 | exposer : function(seckillId) {
13 | return seckill.URL.basePath() + 'seckill/' + seckillId + '/exposer';
14 | },
15 | execution : function(seckillId, md5) {
16 | return seckill.URL.basePath() + 'seckill/' + seckillId + '/' + md5 + '/execution';
17 | }
18 | },
19 | // 处理秒杀逻辑
20 | handleSeckill : function(seckillId, node) {
21 | // 获取秒杀地址,控制显示逻辑,执行秒杀
22 | node.hide().html('');
23 | console.log('exposerUrl=' + seckill.URL.exposer(seckillId));//TODO
24 | $.post(seckill.URL.exposer(seckillId), {}, function(result) {
25 | // 在回调函数中,执行交互流程
26 | if (result && result['success']) {
27 | var exposer = result['data'];
28 | if (exposer['exposed']) {
29 | // 开启秒杀
30 | var md5 = exposer['md5'];
31 | var killUrl = seckill.URL.execution(seckillId, md5);
32 | console.log('killUrl=' + killUrl);//TODO
33 | $('#killBtn').one('click', function() {
34 | // 执行秒杀请求
35 | // 1.先禁用按钮
36 | $(this).addClass('disabled');
37 | // 2.发送秒杀请求
38 | $.post(killUrl, {}, function(result) {
39 | if (result && result['success']) {
40 | var killResult = result['data'];
41 | var state = killResult['state'];
42 | var stateInfo = killResult['stateInfo'];
43 | // 3.显示秒杀结果
44 | node.html('' + stateInfo + '');
45 | }
46 | });
47 | });
48 | node.show();
49 | } else {
50 | // 未开启秒杀
51 | var now = exposer['now'];
52 | var start = exposer['start'];
53 | var end = exposer['end'];
54 | // 重新计算计时逻辑
55 | seckill.countdown(seckillId, now, start, end);
56 | }
57 | } else {
58 | console.log('result=' + result);
59 | }
60 | });
61 | },
62 | // 验证手机号
63 | validatePhone : function(phone) {
64 | if (phone && phone.length == 11 && !isNaN(phone)) {
65 | return true;
66 | } else {
67 | return false;
68 | }
69 | },
70 | // 倒计时
71 | countdown : function(seckillId, nowTime, startTime, endTime) {
72 | // 时间判断
73 | var seckillBox = $('#seckillBox');
74 | if (nowTime > endTime) {
75 | // 秒杀结束
76 | seckillBox.html('秒杀结束!');
77 | } else if (nowTime < startTime) {
78 | // 秒杀未开始,计时事件绑定
79 | var killTime = new Date(startTime + 1000);
80 | seckillBox.countdown(killTime, function(event) {
81 | // 时间格式
82 | var format = event.strftime('秒杀倒计时:%D天 %H时 %M分 %S秒');
83 | seckillBox.html(format);
84 | // 时间完成后回调事件
85 | }).on('finish.countdown', function() {
86 | // 获取秒杀地址,控制显示逻辑,执行秒杀
87 | seckill.handleSeckill(seckillId, seckillBox);
88 | });
89 | } else {
90 | // 秒杀开始
91 | seckill.handleSeckill(seckillId ,seckillBox);
92 | }
93 | },
94 | // 详情页秒杀逻辑
95 | detail : {
96 | // 详情页初始化
97 | init : function(params) {
98 | // 用户手机验证和登录,计时交互
99 | // 规划我们的交互流程
100 | // 在cookie中查找手机号
101 | var killPhone = $.cookie('killPhone');
102 | var startTime = params['startTime'];
103 | var endTime = params['endTime'];
104 | var seckillId = params['seckillId'];
105 | // 验证手机号
106 | if (!seckill.validatePhone(killPhone)) {
107 | // 绑定phone
108 | // 控制输出
109 | var killPhoneModal = $('#killPhoneModal');
110 | killPhoneModal.modal({
111 | show : true,// 显示弹出层
112 | backdrop : 'static',// 禁止位置关闭
113 | keyboard : false
114 | // 关闭键盘事件
115 | })
116 | $('#killPhoneBtn').click(function() {
117 | var inputPhone = $('#killphoneKey').val();
118 | console.log('inputPhone='+inputPhone);//TODO
119 | if (seckill.validatePhone(inputPhone)) {
120 | // 电话写入cookie
121 | $.cookie('killPhone', inputPhone, {
122 | expires : 7,
123 | path : '/seckill'
124 | });
125 | // 刷新页面
126 | window.location.reload();
127 | } else {
128 | $('#killphoneMessage').hide().html('').show(300);
129 | }
130 | });
131 | }
132 | // 已经登录
133 | // 计时交互
134 | var startTime = params['startTime'];
135 | var endTime = params['endTime'];
136 | var seckillId = params['seckillId'];
137 | $.get(seckill.URL.now(), {}, function(result) {
138 | if (result && result['success']) {
139 | var nowTime = result['data'];
140 | // 时间判断,计时交互
141 | seckill.countdown(seckillId, nowTime, startTime, endTime);
142 | } else {
143 | console.log(result['reult:'] + result);
144 | }
145 | });
146 | }
147 | }
148 | }
149 |
--------------------------------------------------------------------------------
/seckill-model/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 | seckill
7 | com.imooc
8 | 0.0.1-SNAPSHOT
9 |
10 | 4.0.0
11 |
12 | seckill-model
13 |
14 |
15 |
--------------------------------------------------------------------------------
/seckill-model/src/main/java/com/imooc/dto/Exposer.java:
--------------------------------------------------------------------------------
1 | package com.imooc.dto;
2 |
3 | import java.io.Serializable;
4 |
5 | /**
6 | * 暴露秒杀接口DTO
7 | *
8 | * @author yan
9 | */
10 | public class Exposer implements Serializable {
11 |
12 | // 是否开启秒杀
13 | private boolean exposed;
14 |
15 | // 一种加密措施
16 | private String md5;
17 |
18 | // id
19 | private long seckillId;
20 |
21 | // 系统当前时间(毫秒)
22 | private long now;
23 |
24 | // 开启时间
25 | private long start;
26 |
27 | // 结束时间
28 | private long end;
29 |
30 | public Exposer(boolean exposed, String md5, long seckillId) {
31 | this.exposed = exposed;
32 | this.md5 = md5;
33 | this.seckillId = seckillId;
34 | }
35 |
36 | public Exposer(boolean exposed, long seckillId, long now, long start, long end) {
37 | this.exposed = exposed;
38 | this.seckillId = seckillId;
39 | this.now = now;
40 | this.start = start;
41 | this.end = end;
42 | }
43 |
44 | public Exposer(boolean exposed, long seckillId) {
45 | this.exposed = exposed;
46 | this.seckillId = seckillId;
47 | }
48 |
49 | public boolean isExposed() {
50 | return exposed;
51 | }
52 |
53 | public void setExposed(boolean exposed) {
54 | this.exposed = exposed;
55 | }
56 |
57 | public String getMd5() {
58 | return md5;
59 | }
60 |
61 | public void setMd5(String md5) {
62 | this.md5 = md5;
63 | }
64 |
65 | public long getSeckillId() {
66 | return seckillId;
67 | }
68 |
69 | public void setSeckillId(long seckillId) {
70 | this.seckillId = seckillId;
71 | }
72 |
73 | public long getNow() {
74 | return now;
75 | }
76 |
77 | public void setNow(long now) {
78 | this.now = now;
79 | }
80 |
81 | public long getStart() {
82 | return start;
83 | }
84 |
85 | public void setStart(long start) {
86 | this.start = start;
87 | }
88 |
89 | public long getEnd() {
90 | return end;
91 | }
92 |
93 | public void setEnd(long end) {
94 | this.end = end;
95 | }
96 |
97 | //重写toString方法
98 | @Override
99 | public String toString() {
100 | return "Exposer [exposed=" + exposed + ", md5=" + md5 + ", seckillId=" + seckillId + ", now=" + now + ", start="
101 | + start + ", end=" + end + "]";
102 | }
103 |
104 | }
105 |
--------------------------------------------------------------------------------
/seckill-model/src/main/java/com/imooc/dto/SeckillExecution.java:
--------------------------------------------------------------------------------
1 | package com.imooc.dto;
2 |
3 | import com.imooc.entity.SuccessKilled;
4 | import com.imooc.enums.SeckillStateEnum;
5 |
6 | import java.io.Serializable;
7 |
8 | /**
9 | * 封装秒杀执行后结果
10 | *
11 | * @author yan
12 | */
13 | public class SeckillExecution implements Serializable {
14 |
15 | private Long seckillId;
16 |
17 | // 秒杀执行结果状态
18 | private Integer state;
19 |
20 | // 状态标识
21 | private String stateInfo;
22 |
23 | // 秒杀成功对象
24 | private SuccessKilled successKilled;
25 |
26 | public SeckillExecution(Long seckillId, SeckillStateEnum stateEnum, SuccessKilled successKilled) {
27 | this.seckillId = seckillId;
28 | this.state = stateEnum.getState();
29 | this.stateInfo = stateEnum.getStateInfo();
30 | this.successKilled = successKilled;
31 | }
32 |
33 | public SeckillExecution(Long seckillId, SeckillStateEnum stateEnum) {
34 | this.seckillId = seckillId;
35 | if(stateEnum!=null){
36 | this.state = stateEnum.getState();
37 | this.stateInfo = stateEnum.getStateInfo();
38 | }
39 | }
40 |
41 | public Long getSeckillId() {
42 | return seckillId;
43 | }
44 |
45 | public void setSeckillId(Long seckillId) {
46 | this.seckillId = seckillId;
47 | }
48 |
49 | public Integer getState() {
50 | return state;
51 | }
52 |
53 | public void setState(Integer state) {
54 | this.state = state;
55 | }
56 |
57 | public String getStateInfo() {
58 | return stateInfo;
59 | }
60 |
61 | public void setStateInfo(String stateInfo) {
62 | this.stateInfo = stateInfo;
63 | }
64 |
65 | public SuccessKilled getSuccessKilled() {
66 | return successKilled;
67 | }
68 |
69 | public void setSuccessKilled(SuccessKilled successKilled) {
70 | this.successKilled = successKilled;
71 | }
72 |
73 | @Override
74 | public String toString() {
75 | return "SeckillExecution [seckillId=" + seckillId + ", state=" + state + ", stateInfo=" + stateInfo
76 | + ", successKilled=" + successKilled + "]";
77 | }
78 |
79 | }
80 |
--------------------------------------------------------------------------------
/seckill-model/src/main/java/com/imooc/dto/SeckillResult.java:
--------------------------------------------------------------------------------
1 | package com.imooc.dto;
2 |
3 | //封装json结果
4 | public class SeckillResult {
5 |
6 | private boolean success;
7 |
8 | private T data;
9 |
10 | private String error;
11 |
12 | public SeckillResult(boolean success, String error) {
13 | this.success = success;
14 | this.error = error;
15 | }
16 |
17 | public SeckillResult(boolean success, T data) {
18 | this.success = success;
19 | this.data = data;
20 | }
21 |
22 | public boolean isSuccess() {
23 | return success;
24 | }
25 |
26 | public void setSuccess(boolean success) {
27 | this.success = success;
28 | }
29 |
30 | public T getData() {
31 | return data;
32 | }
33 |
34 | public void setData(T data) {
35 | this.data = data;
36 | }
37 |
38 | public String getError() {
39 | return error;
40 | }
41 |
42 | public void setError(String error) {
43 | this.error = error;
44 | }
45 |
46 | @Override
47 | public String toString() {
48 | return "SeckillResult [success=" + success + ", data=" + data + ", error=" + error + "]";
49 | }
50 |
51 | }
52 |
--------------------------------------------------------------------------------
/seckill-model/src/main/java/com/imooc/entity/Seckill.java:
--------------------------------------------------------------------------------
1 | package com.imooc.entity;
2 |
3 | import java.io.Serializable;
4 | import java.util.Date;
5 |
6 | /**
7 | * 秒杀库存实体
8 | *
9 | * @author yan
10 | */
11 | public class Seckill implements Serializable {
12 | private long seckillId;
13 |
14 | private String name;
15 |
16 | private int number;
17 |
18 | private Date startTime;
19 |
20 | private Date endTime;
21 |
22 | private Date createTime;
23 |
24 | public long getSeckillId() {
25 | return seckillId;
26 | }
27 |
28 | public void setSeckillId(long seckillId) {
29 | this.seckillId = seckillId;
30 | }
31 |
32 | public String getName() {
33 | return name;
34 | }
35 |
36 | public void setName(String name) {
37 | this.name = name;
38 | }
39 |
40 | public int getNumber() {
41 | return number;
42 | }
43 |
44 | public void setNumber(int number) {
45 | this.number = number;
46 | }
47 |
48 | public Date getStartTime() {
49 | return startTime;
50 | }
51 |
52 | public void setStartTime(Date startTime) {
53 | this.startTime = startTime;
54 | }
55 |
56 | public Date getEndTime() {
57 | return endTime;
58 | }
59 |
60 | public void setEndTime(Date endTime) {
61 | this.endTime = endTime;
62 | }
63 |
64 | public Date getCreateTime() {
65 | return createTime;
66 | }
67 |
68 | public void setCreateTime(Date createTime) {
69 | this.createTime = createTime;
70 | }
71 |
72 | @Override
73 | public String toString() {
74 | return "Seckill [seckillId=" + seckillId + ", name=" + name + ", number=" + number + ", startTime=" + startTime
75 | + ", endTime=" + endTime + ", createTime=" + createTime + "]";
76 | }
77 |
78 | }
79 |
--------------------------------------------------------------------------------
/seckill-model/src/main/java/com/imooc/entity/SuccessKilled.java:
--------------------------------------------------------------------------------
1 | package com.imooc.entity;
2 |
3 | import java.io.Serializable;
4 | import java.util.Date;
5 |
6 | /**
7 | * 成功秒杀实体
8 | *
9 | * @author yan
10 | */
11 | public class SuccessKilled implements Serializable {
12 |
13 | private long seckillId;
14 |
15 | private long userPhone;
16 |
17 | private short state;
18 |
19 | private Date creteTime;
20 |
21 | // 多对一的复合属性
22 | private Seckill seckill;
23 |
24 | public long getSeckillId() {
25 | return seckillId;
26 | }
27 |
28 | public void setSeckillId(long seckillId) {
29 | this.seckillId = seckillId;
30 | }
31 |
32 | public long getUserPhone() {
33 | return userPhone;
34 | }
35 |
36 | public void setUserPhone(long userPhone) {
37 | this.userPhone = userPhone;
38 | }
39 |
40 | public short getState() {
41 | return state;
42 | }
43 |
44 | public void setState(short state) {
45 | this.state = state;
46 | }
47 |
48 | public Date getCreteTime() {
49 | return creteTime;
50 | }
51 |
52 | public void setCreteTime(Date creteTime) {
53 | this.creteTime = creteTime;
54 | }
55 |
56 | public Seckill getSeckill() {
57 | return seckill;
58 | }
59 |
60 | public void setSeckill(Seckill seckill) {
61 | this.seckill = seckill;
62 | }
63 |
64 | @Override
65 | public String toString() {
66 | return "SuccessKilled [seckillId=" + seckillId + ", userPhone=" + userPhone + ", state=" + state
67 | + ", creteTime=" + creteTime + "]";
68 | }
69 |
70 | }
71 |
--------------------------------------------------------------------------------
/seckill-model/src/main/java/com/imooc/enums/SeckillStateEnum.java:
--------------------------------------------------------------------------------
1 | package com.imooc.enums;
2 |
3 | /**
4 | * 使用枚举表述常量数据字典
5 | *
6 | * @author yan
7 | */
8 | public enum SeckillStateEnum {
9 |
10 | SUCCESS(1, "秒杀成功"), END(0, "秒杀结束"),
11 |
12 | REPEAT_KILL(-1, "重复秒杀"),
13 |
14 | INNER_ERROR(-2, "系统异常"),
15 |
16 | DATA_REWRITE(-3, "数据篡改");
17 |
18 | private Integer state;
19 |
20 | private String stateInfo;
21 |
22 | private SeckillStateEnum(int state, String stateInfo) {
23 | this.state = state;
24 | this.stateInfo = stateInfo;
25 | }
26 |
27 | public Integer getState() {
28 | return state;
29 | }
30 |
31 | public String getStateInfo() {
32 | return stateInfo;
33 | }
34 |
35 | public static SeckillStateEnum stateOf(Integer index) {
36 | for (SeckillStateEnum state : values()) {
37 | if (state.getState().equals(index)) {
38 | return state;
39 | }
40 | }
41 | return null;
42 | }
43 |
44 | }
45 |
--------------------------------------------------------------------------------
/seckill-model/src/main/java/com/imooc/exception/RepeatKillException.java:
--------------------------------------------------------------------------------
1 | package com.imooc.exception;
2 |
3 | /**
4 | * 重复秒杀异常(运行期异常)
5 | *
6 | * @author yan
7 | */
8 | public class RepeatKillException extends SeckillException {
9 | public RepeatKillException(String message) {
10 | super(message);
11 | }
12 |
13 | public RepeatKillException(String message, Throwable cause) {
14 | super(message, cause);
15 | }
16 |
17 | }
18 |
--------------------------------------------------------------------------------
/seckill-model/src/main/java/com/imooc/exception/SeckillCloseException.java:
--------------------------------------------------------------------------------
1 | package com.imooc.exception;
2 |
3 | /**
4 | * 秒杀关闭异常
5 | *
6 | * @author yan
7 | */
8 | public class SeckillCloseException extends SeckillException {
9 |
10 | public SeckillCloseException(String message) {
11 | super(message);
12 | }
13 |
14 | public SeckillCloseException(String message, Throwable cause) {
15 | super(message, cause);
16 | }
17 |
18 | }
19 |
--------------------------------------------------------------------------------
/seckill-model/src/main/java/com/imooc/exception/SeckillException.java:
--------------------------------------------------------------------------------
1 | package com.imooc.exception;
2 |
3 | /**
4 | * 秒杀相关业务异常
5 | *
6 | * @author yan
7 | */
8 | public class SeckillException extends RuntimeException {
9 |
10 | public SeckillException(String message) {
11 | super(message);
12 | }
13 |
14 | public SeckillException(String message, Throwable cause) {
15 | super(message, cause);
16 | }
17 |
18 | }
19 |
--------------------------------------------------------------------------------
/seckill-service-provider/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 | seckill
7 | com.imooc
8 | 0.0.1-SNAPSHOT
9 |
10 | 4.0.0
11 |
12 | seckill-service
13 | war
14 | seckill-dubbo-consumer Maven Webapp
15 | http://maven.apache.org
16 |
17 |
18 |
19 |
20 | org.apache.maven.plugins
21 | maven-compiler-plugin
22 |
23 | 1.6
24 | 1.6
25 |
26 |
27 |
28 |
29 |
30 |
31 | com.imooc
32 | seckill-model
33 | 0.0.1-SNAPSHOT
34 |
35 |
36 | com.imooc
37 | seckill-client
38 | 0.0.1-SNAPSHOT
39 |
40 |
41 |
42 | com.alibaba
43 | dubbo
44 | 2.5.7
45 |
46 |
47 | spring
48 | org.springframework
49 |
50 |
51 |
52 |
53 |
54 |
55 | org.apache.zookeeper
56 | zookeeper
57 | 3.5.3-beta
58 |
59 |
60 | log4j
61 | log4j
62 |
63 |
64 |
65 |
66 | com.101tec
67 | zkclient
68 | 0.8
69 |
70 |
71 |
72 |
73 |
--------------------------------------------------------------------------------
/seckill-service-provider/src/main/java/com/imooc/dao/SeckillDao.java:
--------------------------------------------------------------------------------
1 | package com.imooc.dao;
2 |
3 | import com.imooc.entity.Seckill;
4 | import org.apache.ibatis.annotations.Param;
5 |
6 | import java.util.Date;
7 | import java.util.List;
8 | import java.util.Map;
9 |
10 | /**
11 | * 秒杀库存DAO接口
12 | *
13 | * @author yan
14 | */
15 | public interface SeckillDao {
16 |
17 | /**
18 | * 减库存
19 | *
20 | * @param seckillId
21 | * @param killTime
22 | * @return 如果影响行数等于>1,表示更新的记录行数
23 | */
24 | int reduceNumber(@Param("seckillId") long seckillId, @Param("killTime") Date killTime);
25 |
26 | /**
27 | * 根据id查询秒杀对象
28 | *
29 | * @param seckillId
30 | * @return
31 | */
32 | Seckill queryById(long seckillId);
33 |
34 | /**
35 | * 根据偏移量查询秒杀商品列表
36 | *
37 | * @param offset
38 | * @param limit
39 | * @return
40 | */
41 | List queryAll(@Param("offset") int offset, @Param("limit") int limit);
42 |
43 | /**
44 | * 使用存储过程执行秒杀
45 | *
46 | * @param paramMap
47 | */
48 | void killByProcedure(Map paramMap);
49 |
50 | }
51 |
--------------------------------------------------------------------------------
/seckill-service-provider/src/main/java/com/imooc/dao/SuccessKilledDao.java:
--------------------------------------------------------------------------------
1 | package com.imooc.dao;
2 |
3 | import com.imooc.entity.SuccessKilled;
4 | import org.apache.ibatis.annotations.Param;
5 |
6 | public interface SuccessKilledDao {
7 |
8 | /**
9 | * 插入购买明细,可过滤重复
10 | *
11 | * @param seckillId
12 | * @param userPhone
13 | * @return 插入的行数
14 | */
15 | int insertSuccessKilled(@Param("seckillId") long seckillId, @Param("userPhone") long userPhone);
16 |
17 | /**
18 | * 根据id查询SuccessKilled并携带秒杀产品对象实体
19 | *
20 | * @param seckillId
21 | * @param userPhone
22 | * @return
23 | */
24 | SuccessKilled queryByIdWithSeckill(@Param("seckillId") long seckillId, @Param("userPhone") long userPhone);
25 |
26 | }
27 |
--------------------------------------------------------------------------------
/seckill-service-provider/src/main/java/com/imooc/dao/cache/RedisDao.java:
--------------------------------------------------------------------------------
1 | package com.imooc.dao.cache;
2 |
3 | import com.dyuproject.protostuff.LinkedBuffer;
4 | import com.dyuproject.protostuff.ProtostuffIOUtil;
5 | import com.dyuproject.protostuff.runtime.RuntimeSchema;
6 | import com.imooc.entity.Seckill;
7 | import org.slf4j.Logger;
8 | import org.slf4j.LoggerFactory;
9 | import redis.clients.jedis.Jedis;
10 | import redis.clients.jedis.JedisPool;
11 |
12 | public class RedisDao {
13 |
14 | private final Logger logger = LoggerFactory.getLogger(this.getClass());
15 |
16 | private final JedisPool jedisPool;
17 |
18 | private RuntimeSchema schema = RuntimeSchema.createFrom(Seckill.class);
19 |
20 | public RedisDao(String ip, int port) {
21 | jedisPool = new JedisPool(ip, port);
22 | }
23 |
24 | public Seckill getSeckill(long seckillId) {
25 | // redis操作逻辑
26 | try {
27 | Jedis jedis = jedisPool.getResource();
28 | try {
29 | String key = "seckill:" + seckillId;
30 | // 并没有实现内部序列化操作
31 | // get -> byte[] -> 反序列化 -> object[Seckill]
32 | // 采用自定义序列化
33 | // protostuff : pojo.
34 | byte[] bytes = jedis.get(key.getBytes());
35 | if (bytes != null) {
36 | Seckill seckill = schema.newMessage();
37 | ProtostuffIOUtil.mergeFrom(bytes, seckill, schema);
38 | // seckill被反序列化
39 | return seckill;
40 | }
41 | } finally {
42 | jedis.close();
43 | }
44 | } catch (Exception e) {
45 | logger.error(e.getMessage(), e);
46 | }
47 | return null;
48 | }
49 |
50 | public String putSeckill(Seckill seckill) {
51 | // set Object(Seckill) -> 序列号 -> byte[]
52 | try {
53 | Jedis jedis = jedisPool.getResource();
54 | try {
55 | String key = "seckill:" + seckill.getSeckillId();
56 | byte[] bytes = ProtostuffIOUtil.toByteArray(seckill, schema,
57 | LinkedBuffer.allocate(LinkedBuffer.DEFAULT_BUFFER_SIZE));
58 | // 超时缓存
59 | int timeout = 60 * 60;
60 | String result = jedis.setex(key.getBytes(), timeout, bytes);
61 | return result;
62 | } finally {
63 | jedis.close();
64 | }
65 | } catch (Exception e) {
66 | logger.error(e.getMessage(), e);
67 | }
68 | return null;
69 | }
70 |
71 | }
72 |
--------------------------------------------------------------------------------
/seckill-service-provider/src/main/java/com/imooc/service/impl/App.java:
--------------------------------------------------------------------------------
1 | package com.imooc.service.impl;
2 |
3 | import com.imooc.client.SeckillService;
4 | import com.imooc.entity.Seckill;
5 | import org.springframework.context.support.ClassPathXmlApplicationContext;
6 |
7 | import java.io.IOException;
8 | import java.util.List;
9 |
10 | public class App {
11 | public static void main(String[] args) throws IOException {
12 | ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(new String[]{"spring/applicationContext.xml"});
13 | context.start();
14 | SeckillService seckillService = context.getBean("seckillService",SeckillService.class);
15 | List getSeckillList = seckillService.getSeckillList();
16 | System.out.println(getSeckillList);
17 | System.out.println("press any key to exit.");
18 | System.in.read();
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/seckill-service-provider/src/main/java/com/imooc/service/impl/SeckillServiceImpl.java:
--------------------------------------------------------------------------------
1 | package com.imooc.service.impl;
2 |
3 | import com.imooc.dao.SeckillDao;
4 | import com.imooc.dao.SuccessKilledDao;
5 | import com.imooc.dao.cache.RedisDao;
6 | import com.imooc.dto.Exposer;
7 | import com.imooc.dto.SeckillExecution;
8 | import com.imooc.entity.Seckill;
9 | import com.imooc.entity.SuccessKilled;
10 | import com.imooc.enums.SeckillStateEnum;
11 | import com.imooc.exception.RepeatKillException;
12 | import com.imooc.exception.SeckillCloseException;
13 | import com.imooc.exception.SeckillException;
14 | import com.imooc.client.SeckillService;
15 | import org.apache.commons.collections.MapUtils;
16 | import org.slf4j.Logger;
17 | import org.slf4j.LoggerFactory;
18 | import org.springframework.beans.factory.annotation.Autowired;
19 | import org.springframework.stereotype.Service;
20 | import org.springframework.transaction.annotation.Transactional;
21 | import org.springframework.util.DigestUtils;
22 |
23 | import java.util.Date;
24 | import java.util.HashMap;
25 | import java.util.List;
26 | import java.util.Map;
27 |
28 | //@Componet @Service @Dao @Controller
29 | @Service
30 | public class SeckillServiceImpl implements SeckillService {
31 |
32 | private Logger logger = LoggerFactory.getLogger(this.getClass());
33 |
34 | // 注入Service依赖
35 | @Autowired
36 | private SeckillDao seckillDao;
37 |
38 | @Autowired
39 | private SuccessKilledDao successKilledDao;
40 |
41 | @Autowired
42 | private RedisDao redisDao;
43 |
44 | // md5盐值字符串,用于混淆MD5
45 | private final String slat = "sdfsgsfjks;sf,lasmglksmg";
46 |
47 | @Override
48 | public List getSeckillList() {
49 | return seckillDao.queryAll(0, 6);
50 | }
51 |
52 | @Override
53 | public Seckill getById(long seckillId) {
54 | return seckillDao.queryById(seckillId);
55 | }
56 |
57 | private String getMD5(long seckillId) {
58 | String base = seckillId + "/" + slat;
59 | String md5 = DigestUtils.md5DigestAsHex(base.getBytes());
60 | return md5;
61 | }
62 |
63 | @Override
64 | public Exposer exportSeckillUrl(long seckillId) {
65 | // 优化点:缓存优化:超时的基础上维护一致性
66 | // 1.访问redis
67 | Seckill seckill = redisDao.getSeckill(seckillId);
68 | if (seckill == null) {
69 | // 2.访问数据库
70 | seckill = seckillDao.queryById(seckillId);
71 | if (seckill == null) {
72 | return new Exposer(false, seckillId);
73 | } else {
74 | // 3.访问redis
75 | redisDao.putSeckill(seckill);
76 | }
77 | }
78 | if (seckill == null) {
79 | return new Exposer(false, seckillId);
80 | }
81 | Date startTime = seckill.getStartTime();
82 | Date endTime = seckill.getEndTime();
83 | // 系统当前时间
84 | Date nowTime = new Date();
85 | if (nowTime.getTime() < startTime.getTime() || nowTime.getTime() > endTime.getTime()) {
86 | return new Exposer(false, seckillId, nowTime.getTime(), startTime.getTime(), endTime.getTime());
87 | }
88 | // 转化特定字符串的过程,不可逆
89 | String md5 = getMD5(seckillId);
90 | return new Exposer(true, md5, seckillId);
91 | }
92 |
93 | @Override
94 | @Transactional
95 | /**
96 | * 使用注解控制事务方法的优点: 1.开发团队达成一致约定,明确标注事务方法的编程风格
97 | * 2.保证事务方法的执行时间尽可能短,不要穿插其他网络操作,RPC/HTTP请求或者剥离到事务方法外部
98 | * 3.不是所有的方法都需要事务,如只有一条修改操作,只读操作不需要事务控制
99 | */
100 | public SeckillExecution executeSeckill(long seckillId, long userPhone, String md5)
101 | throws SeckillException, RepeatKillException, SeckillCloseException {
102 | if (md5 == null || !md5.equals(getMD5(seckillId))) {
103 | throw new SeckillException("seckill data rewrite");
104 | }
105 | // 执行秒杀逻辑:减库存 + 记录购买行为
106 | Date now = new Date();
107 | try {
108 | // 记录购买行为
109 | int insertCount = successKilledDao.insertSuccessKilled(seckillId, userPhone);
110 | // 唯一:seckillId,userPhone
111 | if (insertCount <= 0) {
112 | // 重复秒杀
113 | throw new RepeatKillException("seckill repeated");
114 | } else {
115 | // 减库存,热点商品竞争
116 | int updateCount = seckillDao.reduceNumber(seckillId, now);
117 | if (updateCount <= 0) {
118 | // 没有更新到记录 rollback
119 | throw new SeckillCloseException("seckill is closed");
120 | } else {
121 | // 秒杀成功 commit
122 | SuccessKilled successKilled = successKilledDao.queryByIdWithSeckill(seckillId, userPhone);
123 | return new SeckillExecution(seckillId, SeckillStateEnum.SUCCESS, successKilled);
124 | }
125 | }
126 | } catch (SeckillCloseException e1) {
127 | throw e1;
128 | } catch (RepeatKillException e2) {
129 | throw e2;
130 | } catch (Exception e) {
131 | logger.error(e.getMessage(), e);
132 | // 所有编译期异常转换为运行期异常
133 | throw new SeckillException("seckill inner error:" + e.getMessage());
134 | }
135 | }
136 |
137 | @Override
138 | public SeckillExecution executeSeckillProcedure(long seckillId, long userPhone, String md5) {
139 | if (md5 == null || !md5.equals(getMD5(seckillId))) {
140 | return new SeckillExecution(seckillId, SeckillStateEnum.DATA_REWRITE);
141 | }
142 | Date killTime = new Date();
143 | Map map = new HashMap();
144 | map.put("seckillId", seckillId);
145 | map.put("phone", userPhone);
146 | map.put("killTime", killTime);
147 | map.put("result", null);
148 | // 执行存储过程,result被赋值
149 | try {
150 | seckillDao.killByProcedure(map);
151 | // 获取result
152 | int result = MapUtils.getInteger(map, "result", -2);
153 | if (result == 1) {
154 | SuccessKilled sk = successKilledDao.queryByIdWithSeckill(seckillId, userPhone);
155 | return new SeckillExecution(seckillId, SeckillStateEnum.SUCCESS, sk);
156 | } else {
157 | return new SeckillExecution(seckillId, SeckillStateEnum.stateOf(result));
158 | }
159 | } catch (Exception e) {
160 | logger.error(e.getMessage(), e);
161 | return new SeckillExecution(seckillId, SeckillStateEnum.INNER_ERROR);
162 | }
163 | }
164 |
165 | }
166 |
--------------------------------------------------------------------------------
/seckill-service-provider/src/main/resources/dubbo.proerpties:
--------------------------------------------------------------------------------
1 | dubbo.application.name=seckill-service
2 | dubbo.registry.address=zookeeper://127.0.0.1:2181
3 | dubbo.registry.check=false
4 | dubbo.protocol.name=dubbo
--------------------------------------------------------------------------------
/seckill-service-provider/src/main/resources/jdbc.properties:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/justinbaby/seckill-demo/3c0c39e88ec9dafa36413ddc8b06c10080d58f8c/seckill-service-provider/src/main/resources/jdbc.properties
--------------------------------------------------------------------------------
/seckill-service-provider/src/main/resources/logback.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/seckill-service-provider/src/main/resources/mapper/SeckillDao.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 |
8 |
9 | UPDATE seckill
10 | SET number = number - 1
11 | WHERE
12 | seckill_id = #{seckillId}
13 | AND start_time #{killTime}
14 | AND end_time >= #{killTime}
15 | AND number > 0
16 |
17 |
18 |
31 |
32 |
47 |
48 |
56 |
--------------------------------------------------------------------------------
/seckill-service-provider/src/main/resources/mapper/SuccessKilledDao.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 |
8 | INSERT ignore INTO success_killed (seckill_id, user_phone, state)
9 | VALUES (#{seckillId}, #{userPhone}, 0)
10 |
11 |
12 |
33 |
--------------------------------------------------------------------------------
/seckill-service-provider/src/main/resources/mybatis-config.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/seckill-service-provider/src/main/resources/spring/applicationContext.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
--------------------------------------------------------------------------------
/seckill-service-provider/src/main/resources/spring/spring-dao.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
10 |
11 |
12 |
13 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
--------------------------------------------------------------------------------
/seckill-service-provider/src/main/resources/spring/spring-dubbo-config.xml:
--------------------------------------------------------------------------------
1 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/seckill-service-provider/src/main/resources/spring/spring-dubbo-provider.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/seckill-service-provider/src/main/resources/spring/spring-service.xml:
--------------------------------------------------------------------------------
1 |
2 |
12 |
13 |
14 |
15 |
16 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/seckill-service-provider/src/main/resources/spring/spring-web.xml:
--------------------------------------------------------------------------------
1 |
2 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
27 |
28 |
29 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
--------------------------------------------------------------------------------
/seckill-service-provider/src/main/webapp/WEB-INF/web.xml:
--------------------------------------------------------------------------------
1 |
5 |
6 |
7 | seckill-dispatcher
8 | org.springframework.web.servlet.DispatcherServlet
9 |
10 |
11 | contextConfigLocation
12 | classpath:spring/applicationContext.xml
13 |
14 |
15 |
16 |
17 | seckill-dispatcher
18 |
19 | /
20 |
21 |
22 |
23 | contextConfigLocation
24 | classpath:spring/applicationContext.xml
25 |
26 |
27 | org.springframework.web.context.ContextLoaderListener
28 |
29 |
--------------------------------------------------------------------------------
/seckill-service-provider/src/main/webapp/index.jsp:
--------------------------------------------------------------------------------
1 |
2 |
3 | Hello World!
4 |
5 |
6 |
--------------------------------------------------------------------------------