diff --git a/.idea/libraries/Maven__com_google_guava_guava_18_0.xml b/.idea/libraries/Maven__com_google_guava_guava_18_0.xml
new file mode 100644
index 0000000..bbd71d7
--- /dev/null
+++ b/.idea/libraries/Maven__com_google_guava_guava_18_0.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/workspace.xml b/.idea/workspace.xml
index 9b467f6..dc8eb08 100644
--- a/.idea/workspace.xml
+++ b/.idea/workspace.xml
@@ -2,9 +2,18 @@
+
+
+
+
+
+
+
+
+
@@ -20,57 +29,59 @@
-
-
-
-
-
+
+
+
+
+
+
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
-
+
+
@@ -81,9 +92,9 @@
-
-
-
+
+
+
@@ -93,67 +104,38 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
-
+
-
-
-
-
-
-
-
-
-
-
-
+
+
-
-
-
-
+
+
+
+
+
+
+
-
+
-
-
-
-
-
-
-
-
-
-
-
+
+
@@ -161,8 +143,8 @@
-
-
+
+
@@ -170,27 +152,61 @@
-
-
+
+
-
+
-
-
+
+
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -208,6 +224,8 @@
refreshVerifyCode
path
/path
+ UserContext
+ user
@@ -216,12 +234,6 @@
@@ -313,9 +331,6 @@
-
-
-
@@ -349,33 +364,6 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
@@ -399,6 +387,9 @@
+
+
+
@@ -410,7 +401,7 @@
-
+
@@ -449,7 +440,20 @@
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -463,6 +467,19 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -493,9 +510,13 @@
+
+
+
+
@@ -522,12 +543,19 @@
-
+
+
+
+
+
+
+
+
-
+
@@ -542,7 +570,7 @@
-
+
@@ -551,14 +579,14 @@
-
-
-
+
+
+
-
+
@@ -621,7 +649,7 @@
file://$PROJECT_DIR$/src/main/java/com/geekq/miaosha/controller/MiaoshaController.java
- 122
+ 132
@@ -633,7 +661,7 @@
file://$PROJECT_DIR$/src/main/java/com/geekq/miaosha/controller/MiaoshaController.java
- 94
+ 104
@@ -645,7 +673,7 @@
file://$PROJECT_DIR$/src/main/java/com/geekq/miaosha/controller/MiaoshaController.java
- 108
+ 118
@@ -673,6 +701,12 @@
+
+ file://$PROJECT_DIR$/src/main/java/com/geekq/miaosha/service/MiaoShaUserService.java
+ 81
+
+
+
@@ -704,62 +738,6 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
@@ -872,13 +850,6 @@
-
-
-
-
-
-
-
@@ -886,13 +857,6 @@
-
-
-
-
-
-
-
@@ -907,48 +871,10 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
@@ -963,16 +889,6 @@
-
-
-
-
-
-
-
-
-
-
@@ -990,40 +906,6 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
@@ -1034,13 +916,7 @@
-
-
-
-
-
-
-
+
@@ -1051,17 +927,173 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
+
diff --git a/README.md b/README.md
index d358e3a..346f8c0 100644
--- a/README.md
+++ b/README.md
@@ -92,7 +92,33 @@ redis的数量不是库存,他的作用仅仅只是为了阻挡多余的请求
1.具体我会有时间更新关于redis的知识
### 15.rabbitmq如何做到消息不重复不丢失即使服务器重启?
+
1.exchange持久化2.queue持久化3.发送消息设置MessageDeliveryMode.persisent这个也是默认的行为4.手动确认
+### 15.为什么threadlocal存储user对象,原理??
-
\ No newline at end of file
+![整体流程](http://i2.bvimg.com/601558/3293e36cc2c7e303.png)
+
+1.并发编程中重要的问题就是数据共享,当你在一个线程中改变任意属性时,所有的线程都会因此受到影响,同时会看到第一个线程修改后的值
+有时我们希望如此,比如:多个线程增大或减小同一个计数器变量
+但是,有时我们希望确保每个线程,只能工作在它自己的线程实例的拷贝上,同时不会影响其他线程的数据
+
+举例: 举个例子,想象你在开发一个电子商务应用,你需要为每一个控制器处理的顾客请求,生成一个唯一的事务ID,同时将其传到管理器或DAO的业务方法中,以便记录日志。一种方案是将事务ID作为一个参数,传到所有的业务方法中。但这并不是一个好的方案,它会使代码变得冗余。
+
+ 你可以使用ThreadLocal类型的变量解决这个问题。首先在控制器或者任意一个预处理器拦截器中生成一个事务ID
+ 然后在ThreadLocal中 设置事务ID,最后,不论这个控制器调用什么方法,都能从threadlocal中获取事务ID
+ 而且这个应用的控制器可以同时处理多个请求,
+ 同时在框架 层面,因为每一个请求都是在一个单独的线程中处理的,所以事务ID对于每一个线程都是唯一的,而且可以从所有线程的执行路径获取
+运行结果可以看出每个线程都在维护自己的变量:
+ Starting Thread: 0 : Fri Sep 21 23:05:34 CST 2018
+ Starting Thread: 2 : Fri Sep 21 23:05:34 CST 2018
+ Starting Thread: 1 : Fri Jan 02 05:36:17 CST 1970
+ Thread Finished: 1 : Fri Jan 02 05:36:17 CST 1970
+ Thread Finished: 0 : Fri Sep 21 23:05:34 CST 2018
+ Thread Finished: 2 : Fri Sep 21 23:05:34 CST 2018
+
+ 局部线程通常使用在这样的情况下,当你有一些对象并不满足线程安全,但是你想避免在使用synchronized关键字
+ 块时产生的同步访问,那么,让每个线程拥有它自己的对象实例
+ 注意:局部变量是同步或局部线程的一个好的替代,它总是能够保证线程安全。唯一可能限制你这样做的是你的应用设计约束
+
+ 所以设计threadlocal存储user不会对对象产生影响,每次进来一个请求都会产生自身的线程变量来存储
\ No newline at end of file
diff --git a/miaosha.iml b/miaosha.iml
index 82576de..4adfa99 100644
--- a/miaosha.iml
+++ b/miaosha.iml
@@ -49,6 +49,7 @@
+
diff --git a/pom.xml b/pom.xml
index d93bc45..cae2ac4 100644
--- a/pom.xml
+++ b/pom.xml
@@ -24,7 +24,11 @@
org.springframework.boot
spring-boot-starter-web
-
+
+ com.google.guava
+ guava
+ 18.0
+
org.springframework.boot
spring-boot-starter-thymeleaf
diff --git a/src/main/java/com/geekq/miaosha/DemoTask.java b/src/main/java/com/geekq/miaosha/DemoTask.java
new file mode 100644
index 0000000..da000d1
--- /dev/null
+++ b/src/main/java/com/geekq/miaosha/DemoTask.java
@@ -0,0 +1,54 @@
+package com.geekq.miaosha;
+
+import java.util.Date;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicInteger;
+
+public class DemoTask implements Runnable
+{
+ // Atomic integer containing the next thread ID to be assigned
+ private static final AtomicInteger nextId = new AtomicInteger(0);
+
+ // Thread local variable containing each thread's ID
+ private static final ThreadLocal threadId = new ThreadLocal()
+ {
+ @Override
+ protected Integer initialValue()
+ {
+ return nextId.getAndIncrement();
+ }
+ };
+
+ // Returns the current thread's unique ID, assigning it if necessary
+ public int getThreadId()
+ {
+ return threadId.get();
+ }
+ // Returns the current thread's starting timestamp
+ private static final ThreadLocal startDate = new ThreadLocal()
+ {
+ protected Date initialValue()
+ {
+ if(threadId.get()==1){
+ return new Date(77777777L);
+ }
+ return new Date();
+ }
+ };
+
+
+
+ @Override
+ public void run()
+ {
+ System.out.printf("Starting Thread: %s : %s\n", getThreadId(), startDate.get());
+ try
+ {
+ TimeUnit.SECONDS.sleep((int) Math.rint(Math.random() * 10));
+ } catch (InterruptedException e)
+ {
+ e.printStackTrace();
+ }
+ System.out.printf("Thread Finished: %s : %s\n", getThreadId(), startDate.get());
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/geekq/miaosha/Test.java b/src/main/java/com/geekq/miaosha/Test.java
new file mode 100644
index 0000000..8e26828
--- /dev/null
+++ b/src/main/java/com/geekq/miaosha/Test.java
@@ -0,0 +1,15 @@
+package com.geekq.miaosha;
+
+public class Test {
+ public static void main(String[] args) {
+ DemoTask demoTask = new DemoTask();
+ DemoTask demoTask1 = new DemoTask();
+ DemoTask demoTask2 = new DemoTask();
+ Thread t = new Thread(demoTask);
+ t.start();
+ new Thread(demoTask).start();
+ new Thread(demoTask2).start();
+
+
+ }
+}
diff --git a/src/main/java/com/geekq/miaosha/config/UserArgumentResolver.java b/src/main/java/com/geekq/miaosha/config/UserArgumentResolver.java
index 90166ff..0e192fb 100644
--- a/src/main/java/com/geekq/miaosha/config/UserArgumentResolver.java
+++ b/src/main/java/com/geekq/miaosha/config/UserArgumentResolver.java
@@ -1,8 +1,8 @@
package com.geekq.miaosha.config;
+import com.geekq.miaosha.access.UserContext;
import com.geekq.miaosha.domain.MiaoshaUser;
import com.geekq.miaosha.service.MiaoShaUserService;
-import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.MethodParameter;
import org.springframework.stereotype.Service;
@@ -13,7 +13,6 @@ import org.springframework.web.method.support.ModelAndViewContainer;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
@Service
public class UserArgumentResolver implements HandlerMethodArgumentResolver {
@@ -28,16 +27,18 @@ public class UserArgumentResolver implements HandlerMethodArgumentResolver {
@Override
public Object resolveArgument(MethodParameter methodParameter, ModelAndViewContainer modelAndViewContainer, NativeWebRequest webRequest, WebDataBinderFactory webDataBinderFactory) throws Exception {
- HttpServletRequest request = webRequest.getNativeRequest(HttpServletRequest.class);
- HttpServletResponse response = webRequest.getNativeResponse(HttpServletResponse.class);
-
- String paramToken = request.getParameter(MiaoShaUserService.COOKIE_NAME_TOKEN);
- String cookieToken = getCookieValue(request, MiaoShaUserService.COOKIE_NAME_TOKEN);
- if(StringUtils.isEmpty(cookieToken) && StringUtils.isEmpty(paramToken)) {
- return null;
- }
- String token = StringUtils.isEmpty(paramToken)?cookieToken:paramToken;
- return userService.getByToken(response, token);
+// HttpServletRequest request = webRequest.getNativeRequest(HttpServletRequest.class);
+// HttpServletResponse response = webRequest.getNativeResponse(HttpServletResponse.class);
+//
+// String paramToken = request.getParameter(MiaoShaUserService.COOKIE_NAME_TOKEN);
+// String cookieToken = getCookieValue(request, MiaoShaUserService.COOKIE_NAME_TOKEN);
+// if(StringUtils.isEmpty(cookieToken) && StringUtils.isEmpty(paramToken)) {
+// return null;
+// }
+// String token = StringUtils.isEmpty(paramToken)?cookieToken:paramToken;
+// return userService.getByToken(response, token);
+ //threadlocal 存储线程副本 保证线程不冲突
+ return UserContext.getUser();
}
private String getCookieValue(HttpServletRequest request, String cookiName) {
diff --git a/src/main/java/com/geekq/miaosha/controller/MiaoshaController.java b/src/main/java/com/geekq/miaosha/controller/MiaoshaController.java
index 0d8434a..9b8db4a 100644
--- a/src/main/java/com/geekq/miaosha/controller/MiaoshaController.java
+++ b/src/main/java/com/geekq/miaosha/controller/MiaoshaController.java
@@ -66,12 +66,22 @@ public class MiaoshaController implements InitializingBean {
return Result.error(CodeMsg.SESSION_ERROR);
}
+
//验证path
boolean check = miaoshaService.checkPath(user, goodsId, path);
if(!check){
return Result.error(CodeMsg.REQUEST_ILLEGAL);
}
+// //使用RateLimiter 限流
+// RateLimiter rateLimiter = RateLimiter.create(10);
+// //判断能否在1秒内得到令牌,如果不能则立即返回false,不会阻塞程序
+// if (!rateLimiter.tryAcquire(1000, TimeUnit.MILLISECONDS)) {
+// System.out.println("短期无法获取令牌,真不幸,排队也瞎排");
+// return Result.error(CodeMsg.MIAOSHA_FAIL);
+//
+// }
+
//是否已经秒杀到
MiaoshaOrder order = orderService.getMiaoshaOrderByUserIdGoodsId(user.getId(), goodsId);
if(order!=null){
diff --git a/src/main/java/com/geekq/miaosha/controller/RateLimiterController.java b/src/main/java/com/geekq/miaosha/controller/RateLimiterController.java
new file mode 100644
index 0000000..c3fe9b5
--- /dev/null
+++ b/src/main/java/com/geekq/miaosha/controller/RateLimiterController.java
@@ -0,0 +1,10 @@
+package com.geekq.miaosha.controller;
+
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.RequestMapping;
+
+@Controller
+@RequestMapping("/ratelimiter")
+public class RateLimiterController {
+
+}
diff --git a/target/classes/com/geekq/miaosha/DemoTask$1.class b/target/classes/com/geekq/miaosha/DemoTask$1.class
new file mode 100644
index 0000000..d5a3e7a
Binary files /dev/null and b/target/classes/com/geekq/miaosha/DemoTask$1.class differ
diff --git a/target/classes/com/geekq/miaosha/DemoTask$2.class b/target/classes/com/geekq/miaosha/DemoTask$2.class
new file mode 100644
index 0000000..024b906
Binary files /dev/null and b/target/classes/com/geekq/miaosha/DemoTask$2.class differ
diff --git a/target/classes/com/geekq/miaosha/DemoTask.class b/target/classes/com/geekq/miaosha/DemoTask.class
new file mode 100644
index 0000000..0f77919
Binary files /dev/null and b/target/classes/com/geekq/miaosha/DemoTask.class differ
diff --git a/target/classes/com/geekq/miaosha/Test.class b/target/classes/com/geekq/miaosha/Test.class
new file mode 100644
index 0000000..44178aa
Binary files /dev/null and b/target/classes/com/geekq/miaosha/Test.class differ
diff --git a/target/classes/com/geekq/miaosha/config/UserArgumentResolver.class b/target/classes/com/geekq/miaosha/config/UserArgumentResolver.class
index cae769d..f723885 100644
Binary files a/target/classes/com/geekq/miaosha/config/UserArgumentResolver.class and b/target/classes/com/geekq/miaosha/config/UserArgumentResolver.class differ
diff --git a/target/classes/com/geekq/miaosha/controller/MiaoshaController.class b/target/classes/com/geekq/miaosha/controller/MiaoshaController.class
index d62c817..45d4cfe 100644
Binary files a/target/classes/com/geekq/miaosha/controller/MiaoshaController.class and b/target/classes/com/geekq/miaosha/controller/MiaoshaController.class differ
diff --git a/target/classes/com/geekq/miaosha/controller/RateLimiterController.class b/target/classes/com/geekq/miaosha/controller/RateLimiterController.class
new file mode 100644
index 0000000..5c9eba0
Binary files /dev/null and b/target/classes/com/geekq/miaosha/controller/RateLimiterController.class differ