├── .classpath ├── .project ├── .settings ├── .jsdtscope ├── org.eclipse.core.resources.prefs ├── org.eclipse.jdt.core.prefs ├── org.eclipse.m2e.core.prefs ├── org.eclipse.wst.common.component ├── org.eclipse.wst.common.project.facet.core.xml ├── org.eclipse.wst.jsdt.ui.superType.container ├── org.eclipse.wst.jsdt.ui.superType.name └── org.eclipse.wst.validation.prefs ├── README.md ├── pom.xml ├── src └── main │ ├── java │ ├── com │ │ └── nian │ │ │ ├── LogTools │ │ │ ├── ExtElement.java │ │ │ ├── LogKV.java │ │ │ ├── LogMessage.java │ │ │ └── SpanIdGenerator.java │ │ │ └── rabbitmq │ │ │ ├── MQConfig.java │ │ │ └── SecondKillMessage.java │ └── nian │ │ └── shop │ │ ├── App.java │ │ ├── DTO │ │ └── ResultDTO.java │ │ ├── VO │ │ ├── GoodsDetailVo.java │ │ ├── GoodsVo.java │ │ ├── LoginVO.java │ │ └── OrderDetailVo.java │ │ ├── access │ │ ├── AccessInterceptor.java │ │ ├── AccessLimit.java │ │ └── UserContext.java │ │ ├── aspect │ │ └── LogAspect.java │ │ ├── bloomFilter │ │ ├── BloomFilter.java │ │ └── BloomFilterCache.java │ │ ├── common │ │ └── CommonValidator.java │ │ ├── config │ │ ├── UserArgumentResolver.java │ │ └── WebConfig.java │ │ ├── controller │ │ ├── DemoController.java │ │ ├── GoodsController.java │ │ ├── LoginController.java │ │ ├── OrderController.java │ │ ├── SecondController.java │ │ └── UserController.java │ │ ├── dao │ │ ├── GoodsDao.java │ │ ├── OrderDao.java │ │ ├── SecondUserDao.java │ │ └── UserDao.java │ │ ├── entity │ │ ├── Goods.java │ │ ├── OrderInfo.java │ │ ├── SecondGoods.java │ │ ├── SecondOrder.java │ │ ├── SecondUser.java │ │ └── User.java │ │ ├── exception │ │ ├── GlobalExceptionHandler.java │ │ └── SecondException.java │ │ ├── redis │ │ ├── AccessKey.java │ │ ├── BasePrefix.java │ │ ├── GoodsKey.java │ │ ├── KeyPrefix.java │ │ ├── OrderKey.java │ │ ├── RedisConfig.java │ │ ├── RedisPoolFactory.java │ │ ├── SecondKey.java │ │ ├── SecondUserKey.java │ │ └── UserKey.java │ │ ├── rocketmq │ │ ├── ConsumerDemo.java │ │ ├── ProducerDemo.java │ │ ├── RocketMQConfig.java │ │ ├── RocketMQReceiver.java │ │ └── RocketMQSender.java │ │ ├── service │ │ ├── GoodsService.java │ │ ├── MqReceiver.java │ │ ├── MqSender.java │ │ ├── OrderService.java │ │ ├── RedisService.java │ │ ├── SecondKillService.java │ │ ├── SecondUserService.java │ │ └── UserService.java │ │ ├── task │ │ ├── BloomFilterTask.java │ │ └── UserDataProduct.java │ │ ├── utils │ │ ├── DBUtil.java │ │ ├── MD5Util.java │ │ ├── ResultCode.java │ │ ├── SecondResEnum.java │ │ ├── SecondStatusEnum.java │ │ ├── UUIDUtil.java │ │ └── ValidatorUtil.java │ │ └── validator │ │ ├── IsMobile.java │ │ └── IsMobileValidator.java │ ├── resources │ ├── application.properties │ ├── static │ │ ├── bootstrap │ │ │ ├── css │ │ │ │ ├── bootstrap-theme.css │ │ │ │ ├── bootstrap-theme.css.map │ │ │ │ ├── bootstrap-theme.min.css │ │ │ │ ├── bootstrap-theme.min.css.map │ │ │ │ ├── bootstrap.css │ │ │ │ ├── bootstrap.css.map │ │ │ │ ├── bootstrap.min.css │ │ │ │ └── bootstrap.min.css.map │ │ │ ├── fonts │ │ │ │ ├── glyphicons-halflings-regular.eot │ │ │ │ ├── glyphicons-halflings-regular.svg │ │ │ │ ├── glyphicons-halflings-regular.ttf │ │ │ │ ├── glyphicons-halflings-regular.woff │ │ │ │ └── glyphicons-halflings-regular.woff2 │ │ │ └── js │ │ │ │ ├── bootstrap.js │ │ │ │ ├── bootstrap.min.js │ │ │ │ └── npm.js │ │ ├── goods_detail.htm │ │ ├── img │ │ │ ├── iphone8p.png │ │ │ ├── iphonex.png │ │ │ └── meta10.png │ │ ├── jquery-validation │ │ │ ├── additional-methods.min.js │ │ │ ├── jquery.validate.min.js │ │ │ └── localization │ │ │ │ └── messages_zh.min.js │ │ ├── js │ │ │ ├── common.js │ │ │ ├── jquery.min.js │ │ │ └── md5.min.js │ │ ├── layer │ │ │ ├── layer.js │ │ │ ├── mobile │ │ │ │ ├── layer.js │ │ │ │ └── need │ │ │ │ │ └── layer.css │ │ │ └── skin │ │ │ │ └── default │ │ │ │ ├── icon-ext.png │ │ │ │ ├── icon.png │ │ │ │ ├── layer.css │ │ │ │ ├── loading-0.gif │ │ │ │ ├── loading-1.gif │ │ │ │ └── loading-2.gif │ │ ├── order_detail.htm │ │ └── sql.markdown │ └── templates │ │ ├── goods_detail.html │ │ ├── goods_list.html │ │ ├── hello.html │ │ ├── jquery.min.js │ │ ├── login.html │ │ ├── order_detail.html │ │ └── secondKill_fail.html │ └── test │ └── second │ └── TestService.java └── target ├── classes ├── META-INF │ ├── MANIFEST.MF │ └── maven │ │ └── nian.login │ │ └── second │ │ ├── pom.properties │ │ └── pom.xml ├── application.properties ├── com │ └── nian │ │ ├── LogTools │ │ ├── ExtElement.class │ │ ├── LogKV.class │ │ ├── LogMessage$1.class │ │ ├── LogMessage.class │ │ └── SpanIdGenerator.class │ │ └── rabbitmq │ │ ├── MQConfig.class │ │ └── SecondKillMessage.class ├── nian │ └── shop │ │ ├── App.class │ │ ├── DTO │ │ └── ResultDTO.class │ │ ├── VO │ │ ├── GoodsDetailVo.class │ │ ├── GoodsVo.class │ │ ├── LoginVO.class │ │ └── OrderDetailVo.class │ │ ├── access │ │ ├── AccessInterceptor.class │ │ ├── AccessLimit.class │ │ └── UserContext.class │ │ ├── aspect │ │ └── LogAspect.class │ │ ├── bloomFilter │ │ ├── BloomFilter$MisjudgmentRate.class │ │ ├── BloomFilter.class │ │ └── BloomFilterCache.class │ │ ├── common │ │ └── CommonValidator.class │ │ ├── config │ │ ├── UserArgumentResolver.class │ │ └── WebConfig.class │ │ ├── controller │ │ ├── DemoController.class │ │ ├── GoodsController.class │ │ ├── LoginController.class │ │ ├── OrderController.class │ │ ├── SecondController.class │ │ └── UserController.class │ │ ├── dao │ │ ├── GoodsDao.class │ │ ├── OrderDao.class │ │ ├── SecondUserDao.class │ │ └── UserDao.class │ │ ├── entity │ │ ├── Goods.class │ │ ├── OrderInfo.class │ │ ├── SecondGoods.class │ │ ├── SecondOrder.class │ │ ├── SecondUser.class │ │ └── User.class │ │ ├── exception │ │ ├── GlobalExceptionHandler.class │ │ └── SecondException.class │ │ ├── redis │ │ ├── AccessKey.class │ │ ├── BasePrefix.class │ │ ├── GoodsKey.class │ │ ├── KeyPrefix.class │ │ ├── OrderKey.class │ │ ├── RedisConfig.class │ │ ├── RedisPoolFactory.class │ │ ├── SecondKey.class │ │ ├── SecondUserKey.class │ │ └── UserKey.class │ │ ├── rocketmq │ │ ├── ConsumerDemo$1.class │ │ ├── ConsumerDemo.class │ │ ├── ProducerDemo$1.class │ │ ├── ProducerDemo.class │ │ ├── RocketMQConfig.class │ │ ├── RocketMQReceiver$1.class │ │ ├── RocketMQReceiver.class │ │ ├── RocketMQSender$1.class │ │ └── RocketMQSender.class │ │ ├── service │ │ ├── GoodsService.class │ │ ├── MqReceiver.class │ │ ├── MqSender.class │ │ ├── OrderService.class │ │ ├── RedisService.class │ │ ├── SecondKillService.class │ │ ├── SecondUserService.class │ │ └── UserService.class │ │ ├── task │ │ ├── BloomFilterTask.class │ │ └── UserDataProduct.class │ │ ├── utils │ │ ├── DBUtil.class │ │ ├── MD5Util.class │ │ ├── ResultCode.class │ │ ├── SecondResEnum.class │ │ ├── SecondStatusEnum.class │ │ ├── UUIDUtil.class │ │ └── ValidatorUtil.class │ │ └── validator │ │ ├── IsMobile.class │ │ └── IsMobileValidator.class ├── second │ └── TestService.class ├── static │ ├── bootstrap │ │ ├── css │ │ │ ├── bootstrap-theme.css │ │ │ ├── bootstrap-theme.css.map │ │ │ ├── bootstrap-theme.min.css │ │ │ ├── bootstrap-theme.min.css.map │ │ │ ├── bootstrap.css │ │ │ ├── bootstrap.css.map │ │ │ ├── bootstrap.min.css │ │ │ └── bootstrap.min.css.map │ │ ├── fonts │ │ │ ├── glyphicons-halflings-regular.eot │ │ │ ├── glyphicons-halflings-regular.svg │ │ │ ├── glyphicons-halflings-regular.ttf │ │ │ ├── glyphicons-halflings-regular.woff │ │ │ └── glyphicons-halflings-regular.woff2 │ │ └── js │ │ │ ├── bootstrap.js │ │ │ ├── bootstrap.min.js │ │ │ └── npm.js │ ├── goods_detail.htm │ ├── img │ │ ├── iphone8p.png │ │ ├── iphonex.png │ │ └── meta10.png │ ├── jquery-validation │ │ ├── additional-methods.min.js │ │ ├── jquery.validate.min.js │ │ └── localization │ │ │ └── messages_zh.min.js │ ├── js │ │ ├── common.js │ │ ├── jquery.min.js │ │ └── md5.min.js │ ├── layer │ │ ├── layer.js │ │ ├── mobile │ │ │ ├── layer.js │ │ │ └── need │ │ │ │ └── layer.css │ │ └── skin │ │ │ └── default │ │ │ ├── icon-ext.png │ │ │ ├── icon.png │ │ │ ├── layer.css │ │ │ ├── loading-0.gif │ │ │ ├── loading-1.gif │ │ │ └── loading-2.gif │ ├── order_detail.htm │ └── sql.markdown └── templates │ ├── goods_detail.html │ ├── goods_list.html │ ├── hello.html │ ├── jquery.min.js │ ├── login.html │ ├── order_detail.html │ └── secondKill_fail.html ├── maven-archiver └── pom.properties ├── maven-status └── maven-compiler-plugin │ └── compile │ └── default-compile │ ├── createdFiles.lst │ └── inputFiles.lst ├── second.jar ├── second.jar.original └── test-classes └── nian └── shop └── AppTest.class /.classpath: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 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 | -------------------------------------------------------------------------------- /.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | second 4 | 5 | 6 | 7 | 8 | 9 | org.eclipse.wst.common.project.facet.core.builder 10 | 11 | 12 | 13 | 14 | org.eclipse.jdt.core.javabuilder 15 | 16 | 17 | 18 | 19 | org.springframework.ide.eclipse.core.springbuilder 20 | 21 | 22 | 23 | 24 | org.springframework.ide.eclipse.boot.validation.springbootbuilder 25 | 26 | 27 | 28 | 29 | org.eclipse.wst.validation.validationbuilder 30 | 31 | 32 | 33 | 34 | org.eclipse.m2e.core.maven2Builder 35 | 36 | 37 | 38 | 39 | 40 | org.eclipse.jem.workbench.JavaEMFNature 41 | org.eclipse.wst.common.modulecore.ModuleCoreNature 42 | org.springframework.ide.eclipse.core.springnature 43 | org.eclipse.jdt.core.javanature 44 | org.eclipse.m2e.core.maven2Nature 45 | org.eclipse.wst.common.project.facet.core.nature 46 | org.eclipse.wst.jsdt.core.jsNature 47 | 48 | 49 | -------------------------------------------------------------------------------- /.settings/.jsdtscope: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.settings/org.eclipse.core.resources.prefs: -------------------------------------------------------------------------------- 1 | eclipse.preferences.version=1 2 | encoding//src/main/java=UTF-8 3 | encoding//src/main/resources=UTF-8 4 | encoding/=UTF-8 5 | -------------------------------------------------------------------------------- /.settings/org.eclipse.jdt.core.prefs: -------------------------------------------------------------------------------- 1 | eclipse.preferences.version=1 2 | org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled 3 | org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 4 | org.eclipse.jdt.core.compiler.compliance=1.8 5 | org.eclipse.jdt.core.compiler.problem.assertIdentifier=error 6 | org.eclipse.jdt.core.compiler.problem.enumIdentifier=error 7 | org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning 8 | org.eclipse.jdt.core.compiler.source=1.8 9 | -------------------------------------------------------------------------------- /.settings/org.eclipse.m2e.core.prefs: -------------------------------------------------------------------------------- 1 | activeProfiles= 2 | eclipse.preferences.version=1 3 | resolveWorkspaceProjects=true 4 | version=1 5 | -------------------------------------------------------------------------------- /.settings/org.eclipse.wst.common.component: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /.settings/org.eclipse.wst.common.project.facet.core.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /.settings/org.eclipse.wst.jsdt.ui.superType.container: -------------------------------------------------------------------------------- 1 | org.eclipse.wst.jsdt.launching.baseBrowserLibrary -------------------------------------------------------------------------------- /.settings/org.eclipse.wst.jsdt.ui.superType.name: -------------------------------------------------------------------------------- 1 | Window -------------------------------------------------------------------------------- /.settings/org.eclipse.wst.validation.prefs: -------------------------------------------------------------------------------- 1 | disabled=06target 2 | eclipse.preferences.version=1 3 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## 功能实现的目标 2 | 3 | 1-基于springBoot平台,集成Redis,实现注册、登录、商品展示、商品详情、订单详情以及秒杀抢购功能 4 | 2-解决缓存穿透、缓存雪崩及缓存击穿等问题 5 | 3-添加消息队列消峰 6 | 4-利用JMeter进行压测 7 | 5-master-slave服务器,分摊DB压力 8 | 9 | ## 已完成的工作 10 | 11 | 1环境搭建(Spring Boot+MyBatis+Druid) 12 | 2登录功能实现与完善(包括数据校验、异常处理等) 13 | 3Redis实现分布式Session 14 | 4各种页面展示以及秒杀功能开发 15 | 5利用AOP对service方法进行拦截,打印日志 16 | 6展示页面的优化加速,对象缓存+页面缓存+页面静态化+前后端分离 17 | 7利用jmeter进行压测,查看优化效果 18 | 8集成RocketMQ,利用消息队列进行消峰、业务解耦 19 | 9添加布隆过滤器防止缓存穿透 20 | 10Redis缓存过期时间在原基础上附加一个随机值,避免缓存雪崩 21 | 11安全方面:1)接口隐藏 ; 2)首次秒杀不需验证码,之后的请求需要验证码,将请求散开,分摊压力; 3)ip限流 22 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4.0.0 4 | 5 | nian.login 6 | second 7 | 0.0.1-SNAPSHOT 8 | jar 9 | 10 | second 11 | http://maven.apache.org 12 | 13 | 14 | UTF-8 15 | 16 | 17 | org.springframework.boot 18 | spring-boot-starter-parent 19 | 1.5.8.RELEASE 20 | 21 | 22 | 23 | 24 | 25 | org.springframework.boot 26 | spring-boot-starter-aop 27 | 28 | 29 | org.springframework.boot 30 | spring-boot-starter-web 31 | 32 | 33 | org.springframework.boot 34 | spring-boot-starter-test 35 | test 36 | 37 | 38 | org.springframework.boot 39 | spring-boot-starter-thymeleaf 40 | 41 | 42 | org.mybatis.spring.boot 43 | mybatis-spring-boot-starter 44 | 1.3.2 45 | 46 | 47 | mysql 48 | mysql-connector-java 49 | 50 | 51 | 52 | com.alibaba 53 | druid 54 | 1.0.5 55 | 56 | 57 | 58 | com.google.guava 59 | guava 60 | 19.0 61 | 62 | 63 | org.projectlombok 64 | lombok 65 | provided 66 | 67 | 68 | redis.clients 69 | jedis 70 | 71 | 72 | com.alibaba 73 | fastjson 74 | 1.2.38 75 | 76 | 77 | 78 | commons-codec 79 | commons-codec 80 | 81 | 82 | org.apache.commons 83 | commons-lang3 84 | 3.7 85 | 86 | 87 | org.springframework.boot 88 | spring-boot-starter-validation 89 | 90 | 91 | 92 | org.springframework.boot 93 | spring-boot-starter-amqp 94 | 95 | 96 | 97 | 98 | com.alibaba.rocketmq 99 | rocketmq-client 100 | 3.6.2.Final 101 | 102 | 103 | 104 | com.alibaba.rocketmq 105 | rocketmq-all 106 | 3.2.6 107 | pom 108 | 109 | 110 | 111 | 112 | 113 | ${project.artifactId} 114 | 115 | 116 | org.springframework.boot 117 | spring-boot-maven-plugin 118 | 119 | 120 | 121 | 122 | -------------------------------------------------------------------------------- /src/main/java/com/nian/LogTools/ExtElement.java: -------------------------------------------------------------------------------- 1 | package com.nian.LogTools; 2 | /** 3 | * @author created by NianTianlei 4 | * @createDate on 2018年7月15日 下午6:43:28 5 | */ 6 | public class ExtElement { 7 | private String traceId = ""; 8 | private String spanId = ""; 9 | 10 | public ExtElement() { 11 | } 12 | 13 | public String getTraceId() { 14 | return this.traceId; 15 | } 16 | 17 | public void setTraceId(String traceId) { 18 | this.traceId = traceId; 19 | } 20 | 21 | public String getSpanId() { 22 | if (this.spanId == null || this.spanId.equals("")) { 23 | this.spanId = SpanIdGenerator.getSpanId(); 24 | } 25 | 26 | return this.spanId; 27 | } 28 | 29 | public void setSpanId(String spanId) { 30 | this.spanId = spanId; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/com/nian/LogTools/LogKV.java: -------------------------------------------------------------------------------- 1 | package com.nian.LogTools; 2 | 3 | import java.util.List; 4 | import java.util.Map; 5 | 6 | import com.alibaba.fastjson.JSON; 7 | 8 | /** 9 | * @author created by NianTianlei 10 | * @createDate on 2018年7月15日 下午6:41:01 11 | */ 12 | public class LogKV { 13 | private String key; 14 | private String value; 15 | 16 | public LogKV(String key, Object value) { 17 | this.key = key; 18 | if (value == null) { 19 | value = ""; 20 | } 21 | 22 | if (!(value instanceof List) && !(value instanceof Map)) { 23 | this.value = value.toString(); 24 | } else { 25 | this.value = JSON.toJSONString(value); 26 | } 27 | 28 | } 29 | 30 | public String getKey() { 31 | return this.key; 32 | } 33 | 34 | public void setKey(String key) { 35 | this.key = key; 36 | } 37 | 38 | public String getValue() { 39 | return this.value; 40 | } 41 | 42 | public void setValue(String value) { 43 | this.value = value; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/main/java/com/nian/LogTools/LogMessage.java: -------------------------------------------------------------------------------- 1 | package com.nian.LogTools; 2 | 3 | import java.util.ArrayList; 4 | import java.util.Iterator; 5 | import java.util.List; 6 | 7 | /** 8 | * @author created by NianTianlei 9 | * @createDate on 2018年7月15日 下午6:40:01 10 | */ 11 | 12 | public class LogMessage { 13 | public static String HEADER_TRACEID = "niantianlei-header-rid"; 14 | public static String HEADER_SPANID = "niantianlei-header-spanid"; 15 | private static String DEFAULT_DLTAG = "_undef"; 16 | private static ThreadLocal extElements = new InheritableThreadLocal() { 17 | protected ExtElement initialValue() { 18 | return new ExtElement(); 19 | } 20 | }; 21 | private String dltag = ""; 22 | private String cspanId = ""; 23 | private List logElements = new ArrayList(); 24 | 25 | public LogMessage() { 26 | } 27 | 28 | public static String getTraceId() { 29 | return ((ExtElement)extElements.get()).getTraceId(); 30 | } 31 | 32 | public static String getSpanId() { 33 | return ((ExtElement)extElements.get()).getSpanId(); 34 | } 35 | 36 | public static void setTraceId(String traceId) { 37 | ((ExtElement)extElements.get()).setTraceId(traceId); 38 | } 39 | 40 | public static void setSpanId(String spanId) { 41 | ((ExtElement)extElements.get()).setSpanId(spanId); 42 | } 43 | 44 | public static String generatorNewSpanid() { 45 | String newSpanid = SpanIdGenerator.getSpanId(); 46 | return newSpanid; 47 | } 48 | 49 | public static String genertorNewTraceid() { 50 | String traceid = SpanIdGenerator.getTraceId(); 51 | return traceid; 52 | } 53 | 54 | public LogMessage setCspanId(String cspanId) { 55 | this.cspanId = cspanId; 56 | return this; 57 | } 58 | 59 | public LogMessage setDltag(String dltag) { 60 | this.dltag = dltag; 61 | return this; 62 | } 63 | 64 | public LogMessage add(String key, Object value) { 65 | LogKV logKV = new LogKV(key, value); 66 | this.logElements.add(logKV); 67 | return this; 68 | } 69 | 70 | public List getLogElements() { 71 | return this.logElements; 72 | } 73 | 74 | public void setLogElements(List logElements) { 75 | this.logElements = logElements; 76 | } 77 | 78 | public String getDltag() { 79 | return this.dltag != null && !this.dltag.equals("") ? this.dltag : DEFAULT_DLTAG; 80 | } 81 | 82 | public String getCspanId() { 83 | return this.cspanId; 84 | } 85 | 86 | public static void remove() { 87 | extElements.remove(); 88 | } 89 | 90 | public String toString() { 91 | ExtElement extElement = (ExtElement)extElements.get(); 92 | StringBuffer sb = new StringBuffer(); 93 | sb.append(this.getDltag()); 94 | sb.append("||traceid="); 95 | sb.append(extElement.getTraceId()); 96 | sb.append("||spanid="); 97 | sb.append(extElement.getSpanId()); 98 | sb.append("||cspanid="); 99 | sb.append(this.getCspanId()); 100 | if (this.logElements.size() > 0) { 101 | Iterator var4 = this.logElements.iterator(); 102 | 103 | while(var4.hasNext()) { 104 | LogKV param = (LogKV)var4.next(); 105 | sb.append("||"); 106 | sb.append(param.getKey()); 107 | sb.append("="); 108 | sb.append(param.getValue()); 109 | } 110 | } 111 | 112 | return sb.toString(); 113 | } 114 | } 115 | -------------------------------------------------------------------------------- /src/main/java/com/nian/LogTools/SpanIdGenerator.java: -------------------------------------------------------------------------------- 1 | package com.nian.LogTools; 2 | /** 3 | * @author created by NianTianlei 4 | * @createDate on 2018年7月15日 下午6:44:59 5 | */ 6 | import java.net.Inet4Address; 7 | import java.net.InetAddress; 8 | import java.net.NetworkInterface; 9 | import java.net.SocketException; 10 | import java.util.ArrayList; 11 | import java.util.Date; 12 | import java.util.Enumeration; 13 | import java.util.Iterator; 14 | import java.util.List; 15 | import java.util.concurrent.atomic.AtomicLong; 16 | 17 | public class SpanIdGenerator { 18 | private static final long ipFactor = getIpFactor(); 19 | private static AtomicLong counter = new AtomicLong(); 20 | 21 | static { 22 | counter.set(0L); 23 | } 24 | 25 | public SpanIdGenerator() { 26 | } 27 | 28 | private static long ip2long(String ip) { 29 | int ret = 0; 30 | String[] ipGroups = ip.split("\\."); 31 | Integer[] ipInt = new Integer[4]; 32 | 33 | for(int i = 0; i < ipGroups.length; ++i) { 34 | ipInt[i] = Integer.valueOf(ipGroups[i]); 35 | } 36 | 37 | ret = ipInt[0] << 24 | ipInt[1] << 16 | ipInt[2] << 8 | ipInt[3]; 38 | return (long)ret; 39 | } 40 | 41 | private static long timeFactor() { 42 | Date data = new Date(); 43 | long msec = data.getTime(); 44 | return msec; 45 | } 46 | 47 | private static long timeFactorInSecond() { 48 | return timeFactor() / 1000L; 49 | } 50 | 51 | private static long randFactor() { 52 | long ret = (long)(Math.random() * Math.pow(2.0D, 32.0D)); 53 | return ret; 54 | } 55 | 56 | private static List getLocalIpList() { 57 | ArrayList ipList = new ArrayList(); 58 | 59 | try { 60 | Enumeration networkInterfaces = NetworkInterface.getNetworkInterfaces(); 61 | 62 | while(networkInterfaces.hasMoreElements()) { 63 | NetworkInterface networkInterface = (NetworkInterface)networkInterfaces.nextElement(); 64 | Enumeration inetAddresses = networkInterface.getInetAddresses(); 65 | 66 | while(inetAddresses.hasMoreElements()) { 67 | InetAddress inetAddress = (InetAddress)inetAddresses.nextElement(); 68 | if (inetAddress != null && inetAddress instanceof Inet4Address) { 69 | String ip = inetAddress.getHostAddress(); 70 | ipList.add(ip); 71 | } 72 | } 73 | } 74 | } catch (SocketException var6) { 75 | ; 76 | } 77 | 78 | return ipList; 79 | } 80 | 81 | private static long getIpFactor() { 82 | List ips = getLocalIpList(); 83 | String ipAddr = "127.0.0.1"; 84 | if (ips != null && ips.size() != 0) { 85 | Iterator var3 = ips.iterator(); 86 | 87 | while(var3.hasNext()) { 88 | String iptmp = (String)var3.next(); 89 | if (!iptmp.equals("127.0.0.1")) { 90 | ipAddr = iptmp; 91 | break; 92 | } 93 | } 94 | 95 | return ip2long(ipAddr); 96 | } else { 97 | return ip2long(ipAddr); 98 | } 99 | } 100 | 101 | static String getSpanId() { 102 | long timeFactor = timeFactor(); 103 | long randFactor = randFactor(); 104 | long spanId = (ipFactor & timeFactor) << 32 | randFactor & -1L; 105 | return handleFormat(Long.toHexString(spanId), 16); 106 | } 107 | 108 | static String getTraceId() { 109 | long timeFactor = timeFactorInSecond(); 110 | long randFactor1 = randFactor(); 111 | long randFactor2 = counter.incrementAndGet(); 112 | long traceIdpart1 = ipFactor << 32 | timeFactor & -1L; 113 | long traceIdpart2 = randFactor1 << 32 | (randFactor2 & 16777215L) << 8 | 134L; 114 | return handleFormat(Long.toHexString(traceIdpart1), 16) + handleFormat(Long.toHexString(traceIdpart2), 16); 115 | } 116 | 117 | private static String handleFormat(String value, int digit) { 118 | if (value == null) { 119 | return "00000000"; 120 | } else { 121 | while(value.length() < digit) { 122 | value = "0" + value; 123 | } 124 | 125 | return value; 126 | } 127 | } 128 | } 129 | -------------------------------------------------------------------------------- /src/main/java/com/nian/rabbitmq/MQConfig.java: -------------------------------------------------------------------------------- 1 | package com.nian.rabbitmq; 2 | 3 | import java.util.HashMap; 4 | import java.util.Map; 5 | 6 | import org.springframework.amqp.core.Binding; 7 | import org.springframework.amqp.core.BindingBuilder; 8 | import org.springframework.amqp.core.FanoutExchange; 9 | import org.springframework.amqp.core.HeadersExchange; 10 | import org.springframework.amqp.core.Queue; 11 | import org.springframework.amqp.core.TopicExchange; 12 | import org.springframework.context.annotation.Bean; 13 | import org.springframework.context.annotation.Configuration; 14 | 15 | @Configuration 16 | public class MQConfig { 17 | 18 | public static final String MIAOSHA_QUEUE = "miaosha.queue"; 19 | public static final String QUEUE = "queue"; 20 | public static final String TOPIC_QUEUE1 = "topic.queue1"; 21 | public static final String TOPIC_QUEUE2 = "topic.queue2"; 22 | public static final String HEADER_QUEUE = "header.queue"; 23 | public static final String TOPIC_EXCHANGE = "topicExchage"; 24 | public static final String FANOUT_EXCHANGE = "fanoutExchage"; 25 | public static final String HEADERS_EXCHANGE = "headersExchage"; 26 | 27 | /** 28 | * Direct模式 交换机Exchange 29 | **/ 30 | @Bean 31 | public Queue queue() { 32 | return new Queue(QUEUE, true); 33 | } 34 | 35 | /** 36 | * Topic模式 交换机Exchange 37 | **/ 38 | @Bean 39 | public Queue topicQueue1() { 40 | return new Queue(TOPIC_QUEUE1, true); 41 | } 42 | @Bean 43 | public Queue topicQueue2() { 44 | return new Queue(TOPIC_QUEUE2, true); 45 | } 46 | @Bean 47 | public TopicExchange topicExchage(){ 48 | return new TopicExchange(TOPIC_EXCHANGE); 49 | } 50 | @Bean 51 | public Binding topicBinding1() { 52 | return BindingBuilder.bind(topicQueue1()).to(topicExchage()).with("topic.key1"); 53 | } 54 | @Bean 55 | public Binding topicBinding2() { 56 | return BindingBuilder.bind(topicQueue2()).to(topicExchage()).with("topic.#"); 57 | } 58 | /** 59 | * Fanout模式 交换机Exchange 60 | **/ 61 | @Bean 62 | public FanoutExchange fanoutExchage(){ 63 | return new FanoutExchange(FANOUT_EXCHANGE); 64 | } 65 | @Bean 66 | public Binding FanoutBinding1() { 67 | return BindingBuilder.bind(topicQueue1()).to(fanoutExchage()); 68 | } 69 | @Bean 70 | public Binding FanoutBinding2() { 71 | return BindingBuilder.bind(topicQueue2()).to(fanoutExchage()); 72 | } 73 | /** 74 | * Header模式 交换机Exchange 75 | **/ 76 | @Bean 77 | public HeadersExchange headersExchage(){ 78 | return new HeadersExchange(HEADERS_EXCHANGE); 79 | } 80 | @Bean 81 | public Queue headerQueue1() { 82 | return new Queue(HEADER_QUEUE, true); 83 | } 84 | @Bean 85 | public Binding headerBinding() { 86 | Map map = new HashMap(); 87 | map.put("header1", "value1"); 88 | map.put("header2", "value2"); 89 | return BindingBuilder.bind(headerQueue1()).to(headersExchage()).whereAll(map).match(); 90 | } 91 | 92 | } 93 | -------------------------------------------------------------------------------- /src/main/java/com/nian/rabbitmq/SecondKillMessage.java: -------------------------------------------------------------------------------- 1 | package com.nian.rabbitmq; 2 | 3 | import lombok.Data; 4 | import nian.shop.entity.SecondUser; 5 | 6 | @Data 7 | public class SecondKillMessage { 8 | private SecondUser user; 9 | private long goodsId; 10 | 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/nian/shop/App.java: -------------------------------------------------------------------------------- 1 | package nian.shop; 2 | 3 | import org.springframework.boot.*; 4 | import org.springframework.boot.autoconfigure.*; 5 | import org.springframework.boot.web.client.RestTemplateBuilder; 6 | import org.springframework.context.annotation.Bean; 7 | import org.springframework.transaction.annotation.EnableTransactionManagement; 8 | import org.springframework.web.client.RestTemplate; 9 | /** 10 | * 11 | * @author Niantianlei 12 | * @date 2018年5月17日 下午3:43:40 13 | */ 14 | @SpringBootApplication 15 | @EnableTransactionManagement 16 | public class App { 17 | 18 | public static void main(String[] args) throws Exception { 19 | SpringApplication.run(App.class, args); 20 | } 21 | 22 | @Bean 23 | public RestTemplate restTemplate(RestTemplateBuilder builder) { 24 | return builder.build(); 25 | } 26 | } -------------------------------------------------------------------------------- /src/main/java/nian/shop/DTO/ResultDTO.java: -------------------------------------------------------------------------------- 1 | package nian.shop.DTO; 2 | 3 | import java.io.Serializable; 4 | 5 | import nian.shop.utils.ResultCode; 6 | /** 7 | * 8 | * @author Niantianlei 9 | * @date 2018年5月18日 下午3:15:20 10 | * @param 11 | */ 12 | public class ResultDTO implements Serializable { 13 | 14 | private static final long serialVersionUID = -3091492566196534172L; 15 | private int code; 16 | private String msg; 17 | private T data; 18 | 19 | public static ResultDTO success(T data) { 20 | return new ResultDTO(data); 21 | } 22 | 23 | public static ResultDTO fail(String msg){ 24 | ResultDTO r = new ResultDTO<>(); 25 | r.setCode(-1); 26 | r.setMsg(msg); 27 | 28 | return r; 29 | } 30 | public static ResultDTO error(T errorInfo) { 31 | ResultDTO resultDTO = new ResultDTO<>(errorInfo); 32 | resultDTO.setCode(ResultCode.FAIL.getCode()); 33 | return resultDTO; 34 | } 35 | 36 | public static ResultDTO error(Integer code, String msg) { 37 | ResultDTO resultDTO = new ResultDTO<>(); 38 | resultDTO.setCode(code); 39 | resultDTO.setMsg(msg); 40 | return resultDTO; 41 | } 42 | private ResultDTO(T data) { 43 | this.data = data; 44 | } 45 | 46 | private ResultDTO() { 47 | 48 | } 49 | 50 | public ResultDTO(int code, String msg, T data) { 51 | super(); 52 | this.code = code; 53 | this.msg = msg; 54 | this.data = data; 55 | } 56 | public int getCode() { 57 | return code; 58 | } 59 | public void setCode(int code) { 60 | this.code = code; 61 | } 62 | public String getMsg() { 63 | return msg; 64 | } 65 | public void setMsg(String msg) { 66 | this.msg = msg; 67 | } 68 | public T getData() { 69 | return data; 70 | } 71 | public void setData(T data) { 72 | this.data = data; 73 | } 74 | 75 | 76 | } 77 | -------------------------------------------------------------------------------- /src/main/java/nian/shop/VO/GoodsDetailVo.java: -------------------------------------------------------------------------------- 1 | package nian.shop.VO; 2 | 3 | import lombok.Data; 4 | import nian.shop.entity.SecondUser; 5 | 6 | @Data 7 | public class GoodsDetailVo { 8 | private int miaoshaStatus = 0; 9 | private int remainSeconds = 0; 10 | private GoodsVo goods ; 11 | private SecondUser user; 12 | private int isFirst; 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/nian/shop/VO/GoodsVo.java: -------------------------------------------------------------------------------- 1 | package nian.shop.VO; 2 | 3 | import java.util.Date; 4 | 5 | import nian.shop.entity.Goods; 6 | 7 | public class GoodsVo extends Goods{ 8 | private Integer stockCount; 9 | private Date startDate; 10 | private Date endDate; 11 | private Double secondPrice; 12 | 13 | public Double getSecondPrice() { 14 | return secondPrice; 15 | } 16 | public void setSecondPrice(Double secondPrice) { 17 | this.secondPrice = secondPrice; 18 | } 19 | public Integer getStockCount() { 20 | return stockCount; 21 | } 22 | public void setStockCount(Integer stockCount) { 23 | this.stockCount = stockCount; 24 | } 25 | public Date getStartDate() { 26 | return startDate; 27 | } 28 | public void setStartDate(Date startDate) { 29 | this.startDate = startDate; 30 | } 31 | public Date getEndDate() { 32 | return endDate; 33 | } 34 | public void setEndDate(Date endDate) { 35 | this.endDate = endDate; 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/nian/shop/VO/LoginVO.java: -------------------------------------------------------------------------------- 1 | package nian.shop.VO; 2 | 3 | import javax.validation.constraints.NotNull; 4 | 5 | import org.hibernate.validator.constraints.Length; 6 | 7 | import lombok.Data; 8 | import nian.shop.validator.IsMobile; 9 | 10 | @Data 11 | public class LoginVO { 12 | @NotNull 13 | @IsMobile 14 | private String mobile; 15 | @NotNull 16 | @Length(min=32) 17 | private String password; 18 | 19 | 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/nian/shop/VO/OrderDetailVo.java: -------------------------------------------------------------------------------- 1 | package nian.shop.VO; 2 | 3 | import lombok.Data; 4 | import nian.shop.entity.OrderInfo; 5 | 6 | @Data 7 | public class OrderDetailVo { 8 | private GoodsVo goods; 9 | private OrderInfo order; 10 | 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/nian/shop/access/AccessInterceptor.java: -------------------------------------------------------------------------------- 1 | package nian.shop.access; 2 | 3 | import java.io.OutputStream; 4 | 5 | import javax.servlet.http.Cookie; 6 | import javax.servlet.http.HttpServletRequest; 7 | import javax.servlet.http.HttpServletResponse; 8 | 9 | import org.apache.commons.lang3.StringUtils; 10 | import org.springframework.beans.factory.annotation.Autowired; 11 | import org.springframework.stereotype.Service; 12 | import org.springframework.web.method.HandlerMethod; 13 | import org.springframework.web.servlet.handler.HandlerInterceptorAdapter; 14 | 15 | import com.alibaba.fastjson.JSON; 16 | 17 | import nian.shop.DTO.ResultDTO; 18 | import nian.shop.entity.SecondUser; 19 | import nian.shop.redis.AccessKey; 20 | import nian.shop.service.RedisService; 21 | import nian.shop.service.SecondUserService; 22 | 23 | @Service 24 | public class AccessInterceptor extends HandlerInterceptorAdapter{ 25 | 26 | @Autowired 27 | SecondUserService userService; 28 | 29 | @Autowired 30 | RedisService redisService; 31 | 32 | @Override 33 | public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) 34 | throws Exception { 35 | if(handler instanceof HandlerMethod) { 36 | SecondUser user = getUser(request, response); 37 | //保存用户信息 38 | UserContext.setUser(user); 39 | 40 | HandlerMethod hm = (HandlerMethod)handler; 41 | AccessLimit accessLimit = hm.getMethodAnnotation(AccessLimit.class); 42 | if(accessLimit == null) { 43 | return true; 44 | } 45 | int seconds = accessLimit.seconds(); 46 | int maxCount = accessLimit.maxCount(); 47 | boolean needLogin = accessLimit.needLogin(); 48 | String key = request.getRequestURI(); 49 | if(needLogin) { 50 | if(user == null) { 51 | render(response, ResultDTO.fail("session错误")); 52 | return false; 53 | } 54 | key += "_" + user.getId(); 55 | }else { 56 | //nothing to do 57 | } 58 | AccessKey accessKey = AccessKey.withExpire(seconds); 59 | Integer count = redisService.get(accessKey, key, Integer.class); 60 | if(count == null) { 61 | redisService.set(accessKey, key, 1); 62 | } else if(count < maxCount) { 63 | redisService.incr(accessKey, key); 64 | } else { 65 | render(response, ResultDTO.fail("请求过于频繁")); 66 | return false; 67 | } 68 | } 69 | return true; 70 | } 71 | 72 | private void render(HttpServletResponse response, ResultDTO resultDTO)throws Exception { 73 | response.setContentType("application/json;charset=UTF-8"); 74 | OutputStream out = response.getOutputStream(); 75 | String str = JSON.toJSONString(resultDTO); 76 | out.write(str.getBytes("UTF-8")); 77 | out.flush(); 78 | out.close(); 79 | } 80 | 81 | private SecondUser getUser(HttpServletRequest request, HttpServletResponse response) { 82 | String paramToken = request.getParameter(SecondUserService.COOKIE_NAME_TOKEN); 83 | String cookieToken = getCookieValue(request, SecondUserService.COOKIE_NAME_TOKEN); 84 | if(StringUtils.isEmpty(cookieToken) && StringUtils.isEmpty(paramToken)) { 85 | return null; 86 | } 87 | String token = StringUtils.isEmpty(paramToken)?cookieToken:paramToken; 88 | return userService.getByToken(response, token); 89 | } 90 | 91 | private String getCookieValue(HttpServletRequest request, String cookiName) { 92 | Cookie[] cookies = request.getCookies(); 93 | if(cookies == null || cookies.length <= 0){ 94 | return null; 95 | } 96 | for(Cookie cookie : cookies) { 97 | if(cookie.getName().equals(cookiName)) { 98 | return cookie.getValue(); 99 | } 100 | } 101 | return null; 102 | } 103 | 104 | } 105 | -------------------------------------------------------------------------------- /src/main/java/nian/shop/access/AccessLimit.java: -------------------------------------------------------------------------------- 1 | package nian.shop.access; 2 | 3 | import static java.lang.annotation.ElementType.METHOD; 4 | import static java.lang.annotation.RetentionPolicy.RUNTIME; 5 | 6 | import java.lang.annotation.Retention; 7 | import java.lang.annotation.Target; 8 | 9 | @Retention(RUNTIME) 10 | @Target(METHOD) 11 | public @interface AccessLimit { 12 | int seconds(); 13 | int maxCount(); 14 | boolean needLogin() default true; 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/nian/shop/access/UserContext.java: -------------------------------------------------------------------------------- 1 | package nian.shop.access; 2 | 3 | import nian.shop.entity.SecondUser; 4 | 5 | public class UserContext { 6 | 7 | private static ThreadLocal userHolder = new ThreadLocal<>(); 8 | 9 | public static void setUser(SecondUser user) { 10 | userHolder.set(user); 11 | } 12 | 13 | public static SecondUser getUser() { 14 | return userHolder.get(); 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/nian/shop/aspect/LogAspect.java: -------------------------------------------------------------------------------- 1 | package nian.shop.aspect; 2 | 3 | import java.util.List; 4 | import java.util.Map; 5 | import java.util.Map.Entry; 6 | 7 | import org.aspectj.lang.JoinPoint; 8 | import org.aspectj.lang.annotation.Aspect; 9 | import org.aspectj.lang.annotation.Before; 10 | import org.aspectj.lang.annotation.Pointcut; 11 | import org.slf4j.Logger; 12 | import org.slf4j.LoggerFactory; 13 | import org.springframework.stereotype.Component; 14 | 15 | import com.alibaba.fastjson.JSON; 16 | import com.google.common.collect.Lists; 17 | import com.nian.LogTools.LogKV; 18 | import com.nian.LogTools.LogMessage; 19 | 20 | /** 21 | * @author created by NianTianlei 22 | * @createDate on 2018年7月15日 下午5:44:37 23 | */ 24 | @Aspect 25 | @Component 26 | public class LogAspect { 27 | private static final Logger LOG = LoggerFactory.getLogger(LogAspect.class); 28 | 29 | @Pointcut("within(nian.shop.service..*) ") 30 | public void log() { 31 | 32 | } 33 | 34 | @Before("log()") 35 | public void logAround(JoinPoint joinPoint) { 36 | Object[] args = joinPoint.getArgs(); 37 | if (args != null) { 38 | String[] paramStrs = new String[args.length]; 39 | for (int i = args.length - 1; i >= 0; i--) { 40 | paramStrs[i] = args[i].toString(); 41 | } 42 | 43 | String className = joinPoint.getSignature().getDeclaringTypeName(); 44 | String methodName = joinPoint.getSignature().getName(); 45 | 46 | LogMessage logMessage = new LogMessage(); 47 | logMessage.setDltag("request_in"); 48 | List logKVList = Lists.newArrayList(); 49 | LogKV classLog = new LogKV("SecondKillRequest", className + "." + methodName); 50 | logKVList.add(classLog); 51 | 52 | int index = 1; 53 | for (String paramStr : paramStrs) { 54 | try { 55 | Map map = JSON.parseObject(paramStr, Map.class); 56 | for (Entry entry : map.entrySet()) { 57 | String key = entry.getKey(); 58 | Object value = entry.getValue(); 59 | LogKV logKV = new LogKV(key, value); 60 | logKVList.add(logKV); 61 | } 62 | 63 | } catch(Exception e) { 64 | String key = "arg" + index; 65 | LogKV logKV = new LogKV(key, paramStr); 66 | logKVList.add(logKV); 67 | } 68 | index++; 69 | } 70 | logMessage.setLogElements(logKVList); 71 | LOG.info(logMessage.toString()); 72 | } 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /src/main/java/nian/shop/bloomFilter/BloomFilterCache.java: -------------------------------------------------------------------------------- 1 | package nian.shop.bloomFilter; 2 | 3 | /** 4 | * @author created by NianTianlei 5 | * @createDate on 2018年6月24日 下午7:56:49 6 | */ 7 | public class BloomFilterCache { 8 | public static BloomFilter bloomFilter; 9 | } 10 | -------------------------------------------------------------------------------- /src/main/java/nian/shop/common/CommonValidator.java: -------------------------------------------------------------------------------- 1 | package nian.shop.common; 2 | /** 3 | * @author created by NianTianlei 4 | * @createDate on 2018年5月26日 下午9:18:14 5 | */ 6 | public class CommonValidator { 7 | 8 | } 9 | -------------------------------------------------------------------------------- /src/main/java/nian/shop/config/UserArgumentResolver.java: -------------------------------------------------------------------------------- 1 | package nian.shop.config; 2 | 3 | import javax.servlet.http.Cookie; 4 | import javax.servlet.http.HttpServletRequest; 5 | 6 | import org.springframework.beans.factory.annotation.Autowired; 7 | import org.springframework.core.MethodParameter; 8 | import org.springframework.stereotype.Service; 9 | import org.springframework.web.bind.support.WebDataBinderFactory; 10 | import org.springframework.web.context.request.NativeWebRequest; 11 | import org.springframework.web.method.support.HandlerMethodArgumentResolver; 12 | import org.springframework.web.method.support.ModelAndViewContainer; 13 | 14 | import nian.shop.access.UserContext; 15 | import nian.shop.entity.SecondUser; 16 | import nian.shop.service.SecondUserService; 17 | 18 | @Service 19 | public class UserArgumentResolver implements HandlerMethodArgumentResolver { 20 | 21 | @Autowired 22 | SecondUserService userService; 23 | 24 | public boolean supportsParameter(MethodParameter parameter) { 25 | Class clazz = parameter.getParameterType(); 26 | return clazz == SecondUser.class; 27 | } 28 | 29 | public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, 30 | NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception { 31 | /*HttpServletRequest request = webRequest.getNativeRequest(HttpServletRequest.class); 32 | HttpServletResponse response = webRequest.getNativeResponse(HttpServletResponse.class); 33 | 34 | String paramToken = request.getParameter(SecondUserService.COOKIE_NAME_TOKEN); 35 | String cookieToken = getCookieValue(request, SecondUserService.COOKIE_NAME_TOKEN); 36 | if(ValidatorUtil.isEmpty(cookieToken) && ValidatorUtil.isEmpty(paramToken)) { 37 | return null; 38 | } 39 | String token = ValidatorUtil.isEmpty(paramToken)?cookieToken:paramToken; 40 | return userService.getByToken(response, token);*/ 41 | return UserContext.getUser(); 42 | } 43 | 44 | private String getCookieValue(HttpServletRequest request, String cookiName) { 45 | Cookie[] cookies = request.getCookies(); 46 | if(cookies == null || cookies.length == 0) { 47 | return null; 48 | } 49 | for(Cookie cookie : cookies) { 50 | if(cookie.getName().equals(cookiName)) { 51 | return cookie.getValue(); 52 | } 53 | } 54 | return null; 55 | } 56 | 57 | } 58 | -------------------------------------------------------------------------------- /src/main/java/nian/shop/config/WebConfig.java: -------------------------------------------------------------------------------- 1 | package nian.shop.config; 2 | 3 | import java.util.List; 4 | 5 | import org.springframework.beans.factory.annotation.Autowired; 6 | import org.springframework.context.annotation.Configuration; 7 | import org.springframework.web.method.support.HandlerMethodArgumentResolver; 8 | import org.springframework.web.servlet.config.annotation.InterceptorRegistry; 9 | import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; 10 | 11 | import nian.shop.access.AccessInterceptor; 12 | 13 | @Configuration 14 | public class WebConfig extends WebMvcConfigurerAdapter{ 15 | 16 | @Autowired 17 | UserArgumentResolver userArgumentResolver; 18 | 19 | @Autowired 20 | AccessInterceptor accessInterceptor; 21 | 22 | @Override 23 | public void addArgumentResolvers(List argumentResolvers) { 24 | argumentResolvers.add(userArgumentResolver); 25 | } 26 | @Override 27 | public void addInterceptors(InterceptorRegistry registry) { 28 | registry.addInterceptor(accessInterceptor); 29 | } 30 | 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/nian/shop/controller/DemoController.java: -------------------------------------------------------------------------------- 1 | package nian.shop.controller; 2 | 3 | import java.io.UnsupportedEncodingException; 4 | 5 | import org.springframework.beans.factory.annotation.Autowired; 6 | import org.springframework.stereotype.Controller; 7 | import org.springframework.ui.Model; 8 | import org.springframework.web.bind.annotation.RequestMapping; 9 | import org.springframework.web.bind.annotation.ResponseBody; 10 | 11 | import com.alibaba.rocketmq.client.exception.MQBrokerException; 12 | import com.alibaba.rocketmq.client.exception.MQClientException; 13 | import com.alibaba.rocketmq.remoting.exception.RemotingException; 14 | 15 | import nian.shop.DTO.ResultDTO; 16 | import nian.shop.entity.User; 17 | import nian.shop.redis.UserKey; 18 | import nian.shop.rocketmq.RocketMQReceiver; 19 | import nian.shop.rocketmq.RocketMQSender; 20 | import nian.shop.service.MqSender; 21 | import nian.shop.service.RedisService; 22 | import nian.shop.service.UserService; 23 | 24 | @Controller 25 | @RequestMapping("/demo") 26 | public class DemoController { 27 | @Autowired 28 | UserService userService; 29 | @Autowired 30 | RedisService redisService; 31 | @Autowired 32 | MqSender mqSender; 33 | @Autowired 34 | RocketMQSender rocketMQSender; 35 | @Autowired 36 | RocketMQReceiver rocketMQReceiver; 37 | 38 | @RequestMapping("/") 39 | @ResponseBody 40 | String home() { 41 | return "Hello World!"; 42 | } 43 | 44 | @RequestMapping("/success") 45 | @ResponseBody 46 | ResultDTO hello() { 47 | return ResultDTO.success("asd"); 48 | } 49 | 50 | @RequestMapping("/fail") 51 | @ResponseBody 52 | ResultDTO fail() { 53 | return ResultDTO.error("服务端异常"); 54 | } 55 | 56 | @RequestMapping("/thymeleaf") 57 | String thymeleaf(Model model) { 58 | model.addAttribute("name", "tyler"); 59 | return "hello"; 60 | } 61 | 62 | @RequestMapping("/db/getById") 63 | @ResponseBody 64 | ResultDTO getByIds() { 65 | User user = userService.getUserById(1); 66 | return ResultDTO.success(user); 67 | } 68 | 69 | @RequestMapping("/db/tx") 70 | @ResponseBody 71 | ResultDTO tx() { 72 | userService.tx(); 73 | return ResultDTO.success(true); 74 | } 75 | 76 | @RequestMapping("/redis/get") 77 | @ResponseBody 78 | ResultDTO redisGet() { 79 | User user = redisService.get(UserKey.getById, "" + 1, User.class); 80 | return ResultDTO.success(user); 81 | } 82 | 83 | @RequestMapping("/redis/set") 84 | @ResponseBody 85 | ResultDTO redisSet() { 86 | User user = new User(); 87 | user.setId(1); 88 | user.setName("123456"); 89 | redisService.set(UserKey.getById, "" + 1, user); 90 | return ResultDTO.success(true); 91 | } 92 | 93 | @RequestMapping("/mq") 94 | @ResponseBody 95 | ResultDTO mq() { 96 | try { 97 | rocketMQSender.sendSecondKillMessage("hello, world"); 98 | } catch (Exception e) { 99 | // TODO Auto-generated catch block 100 | e.printStackTrace(); 101 | } 102 | return ResultDTO.success("hello, world"); 103 | } 104 | 105 | @RequestMapping("/mq1") 106 | @ResponseBody 107 | ResultDTO mq1() { 108 | try { 109 | rocketMQSender.sendSecondKillMessage("hello, tianlei"); 110 | } catch (Exception e) { 111 | // TODO Auto-generated catch block 112 | e.printStackTrace(); 113 | } 114 | return ResultDTO.success("hello, world"); 115 | } 116 | 117 | // @RequestMapping("/mq") 118 | // @ResponseBody 119 | // ResultDTO mq() { 120 | // mqSender.send("hello, world"); 121 | // return ResultDTO.success("hello, world"); 122 | // } 123 | // 124 | // @RequestMapping("/mq/topic") 125 | // @ResponseBody 126 | // ResultDTO mq_topic() { 127 | // mqSender.sendTopic("hello, world"); 128 | // return ResultDTO.success("hello, world"); 129 | // } 130 | // 131 | // @RequestMapping("/mq/fanout") 132 | // @ResponseBody 133 | // public ResultDTO fanout() { 134 | // mqSender.sendFanout("hello,world"); 135 | // return ResultDTO.success("Hello,world"); 136 | // } 137 | // @RequestMapping("/mq/header") 138 | // @ResponseBody 139 | // public ResultDTO header() { 140 | // mqSender.sendHeader("hello,world"); 141 | // return ResultDTO.success("Hello,world"); 142 | // } 143 | } 144 | -------------------------------------------------------------------------------- /src/main/java/nian/shop/controller/LoginController.java: -------------------------------------------------------------------------------- 1 | package nian.shop.controller; 2 | 3 | 4 | import javax.servlet.http.HttpServletResponse; 5 | import javax.validation.Valid; 6 | 7 | import org.slf4j.Logger; 8 | import org.slf4j.LoggerFactory; 9 | import org.springframework.beans.factory.annotation.Autowired; 10 | import org.springframework.stereotype.Controller; 11 | import org.springframework.web.bind.annotation.RequestMapping; 12 | import org.springframework.web.bind.annotation.ResponseBody; 13 | import nian.shop.DTO.ResultDTO; 14 | import nian.shop.VO.LoginVO; 15 | import nian.shop.service.RedisService; 16 | import nian.shop.service.SecondUserService; 17 | 18 | @Controller 19 | @RequestMapping("/login") 20 | public class LoginController { 21 | @Autowired 22 | RedisService redisService; 23 | @Autowired 24 | SecondUserService secondUserService; 25 | 26 | @RequestMapping("/to_login") 27 | public String toLogin() { 28 | return "login"; 29 | } 30 | 31 | 32 | @RequestMapping("/do_login") 33 | @ResponseBody 34 | public ResultDTO doLogin(HttpServletResponse response, @Valid LoginVO loginVO) { 35 | String token = secondUserService.login(response, loginVO); 36 | return ResultDTO.success(token); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/nian/shop/controller/OrderController.java: -------------------------------------------------------------------------------- 1 | package nian.shop.controller; 2 | 3 | import org.springframework.beans.factory.annotation.Autowired; 4 | import org.springframework.stereotype.Controller; 5 | import org.springframework.ui.Model; 6 | import org.springframework.web.bind.annotation.RequestMapping; 7 | import org.springframework.web.bind.annotation.RequestParam; 8 | import org.springframework.web.bind.annotation.ResponseBody; 9 | 10 | import nian.shop.DTO.ResultDTO; 11 | import nian.shop.VO.GoodsVo; 12 | import nian.shop.VO.OrderDetailVo; 13 | import nian.shop.entity.OrderInfo; 14 | import nian.shop.entity.SecondUser; 15 | import nian.shop.service.GoodsService; 16 | import nian.shop.service.OrderService; 17 | import nian.shop.service.RedisService; 18 | import nian.shop.service.SecondUserService; 19 | 20 | @Controller 21 | @RequestMapping("/order") 22 | public class OrderController { 23 | 24 | @Autowired 25 | SecondUserService userService; 26 | 27 | @Autowired 28 | RedisService redisService; 29 | 30 | @Autowired 31 | OrderService orderService; 32 | 33 | @Autowired 34 | GoodsService goodsService; 35 | 36 | @RequestMapping("/detail") 37 | @ResponseBody 38 | public ResultDTO info(Model model, SecondUser user, 39 | @RequestParam("orderId") long orderId) { 40 | if(user == null) { 41 | return ResultDTO.fail("session错误"); 42 | } 43 | OrderInfo order = orderService.getOrderById(orderId); 44 | if(order == null) { 45 | return ResultDTO.fail("order不存在"); 46 | } 47 | long goodsId = order.getGoodsId(); 48 | GoodsVo goods = goodsService.getGoodsVoByGoodsId(goodsId); 49 | OrderDetailVo vo = new OrderDetailVo(); 50 | vo.setOrder(order); 51 | vo.setGoods(goods); 52 | return ResultDTO.success(vo); 53 | } 54 | 55 | } 56 | -------------------------------------------------------------------------------- /src/main/java/nian/shop/controller/UserController.java: -------------------------------------------------------------------------------- 1 | package nian.shop.controller; 2 | 3 | import org.springframework.beans.factory.annotation.Autowired; 4 | import org.springframework.stereotype.Controller; 5 | import org.springframework.ui.Model; 6 | import org.springframework.web.bind.annotation.RequestMapping; 7 | import org.springframework.web.bind.annotation.ResponseBody; 8 | 9 | import nian.shop.DTO.ResultDTO; 10 | import nian.shop.entity.SecondUser; 11 | import nian.shop.service.RedisService; 12 | import nian.shop.service.SecondUserService; 13 | 14 | 15 | 16 | 17 | @Controller 18 | @RequestMapping("/user") 19 | public class UserController { 20 | 21 | @Autowired 22 | SecondUserService userService; 23 | 24 | @Autowired 25 | RedisService redisService; 26 | 27 | @RequestMapping("/info") 28 | @ResponseBody 29 | public ResultDTO info(Model model, SecondUser user) { 30 | return ResultDTO.success(user); 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/nian/shop/dao/GoodsDao.java: -------------------------------------------------------------------------------- 1 | package nian.shop.dao; 2 | 3 | import java.util.List; 4 | 5 | import org.apache.ibatis.annotations.Mapper; 6 | import org.apache.ibatis.annotations.Param; 7 | import org.apache.ibatis.annotations.Select; 8 | import org.apache.ibatis.annotations.Update; 9 | 10 | import nian.shop.VO.GoodsVo; 11 | import nian.shop.entity.SecondGoods; 12 | 13 | 14 | @Mapper 15 | public interface GoodsDao { 16 | 17 | @Select("select g.*,sg.stock_count, sg.start_date, sg.end_date,sg.second_price from second_goods sg left join goods g on sg.goods_id = g.id") 18 | public List listGoodsVo(); 19 | 20 | @Select("select g.*,sg.stock_count, sg.start_date, sg.end_date,sg.second_price from second_goods sg left join goods g on sg.goods_id = g.id where g.id = #{goodsId}") 21 | public GoodsVo getGoodsVoByGoodsId(@Param("goodsId")long goodsId); 22 | 23 | @Update("update second_goods set stock_count = stock_count - 1 where goods_id = #{goodsId} and stock_count > 0") 24 | public int reduceStock(SecondGoods g); 25 | 26 | @Update("update second_goods set stock_count = #{stockCount} where goods_id = #{goodsId}") 27 | public int resetStock(SecondGoods g); 28 | 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/nian/shop/dao/OrderDao.java: -------------------------------------------------------------------------------- 1 | package nian.shop.dao; 2 | 3 | import org.apache.ibatis.annotations.Delete; 4 | import org.apache.ibatis.annotations.Insert; 5 | import org.apache.ibatis.annotations.Mapper; 6 | import org.apache.ibatis.annotations.Param; 7 | import org.apache.ibatis.annotations.Select; 8 | import org.apache.ibatis.annotations.SelectKey; 9 | 10 | import nian.shop.entity.OrderInfo; 11 | import nian.shop.entity.SecondOrder; 12 | 13 | @Mapper 14 | public interface OrderDao { 15 | @Select("select * from second_order where user_id=#{userId} and goods_id=#{goodsId}") 16 | public SecondOrder getSecondOrderByUserIdandGoodsId(@Param("userId")long userId, @Param("goodsId")long goodsId); 17 | 18 | @Insert("insert into order_info(user_id, goods_id, goods_name, goods_count, goods_price, order_channel, status, create_date)values(" 19 | + "#{userId}, #{goodsId}, #{goodsName}, #{goodsCount}, #{goodsPrice}, #{orderChannel},#{status},#{createDate} )") 20 | @SelectKey(keyColumn="id", keyProperty="id", resultType=long.class, before=false, statement="select last_insert_id()") 21 | public long insert(OrderInfo orderInfo); 22 | 23 | @Insert("insert into second_order (user_id, goods_id, order_id)values(#{userId}, #{goodsId}, #{orderId})") 24 | public int insertSecondOrder(SecondOrder secondOrder); 25 | 26 | @Select("select * from order_info where id = #{orderId}") 27 | public OrderInfo getOrderById(@Param("orderId")long orderId); 28 | 29 | @Delete("delete from order_info") 30 | public void deleteOrders(); 31 | 32 | @Delete("delete from second_order") 33 | public void deleteMiaoshaOrders(); 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/nian/shop/dao/SecondUserDao.java: -------------------------------------------------------------------------------- 1 | package nian.shop.dao; 2 | 3 | import java.util.List; 4 | 5 | import org.apache.ibatis.annotations.Mapper; 6 | import org.apache.ibatis.annotations.Param; 7 | import org.apache.ibatis.annotations.Select; 8 | import org.apache.ibatis.annotations.Update; 9 | 10 | import nian.shop.entity.SecondUser; 11 | 12 | @Mapper 13 | public interface SecondUserDao { 14 | @Select("select * from second_user where id = #{id}") 15 | public SecondUser getById(@Param("id")long id); 16 | 17 | @Update("update second_user set password = #{password} where id = #{id}") 18 | public void update(SecondUser toBeUpdate); 19 | 20 | @Select("select * from second_user") 21 | public List queryAllSecondUser(); 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/nian/shop/dao/UserDao.java: -------------------------------------------------------------------------------- 1 | package nian.shop.dao; 2 | 3 | import org.apache.ibatis.annotations.Insert; 4 | import org.apache.ibatis.annotations.Mapper; 5 | import org.apache.ibatis.annotations.Param; 6 | import org.apache.ibatis.annotations.Select; 7 | 8 | import nian.shop.entity.User; 9 | 10 | /** 11 | * @author Niantianlei 12 | * @date 2018年5月17日 下午2:16:20 13 | */ 14 | @Mapper 15 | public interface UserDao { 16 | 17 | @Select("select * from user where id = #{id}") 18 | public User getById(@Param("id")int id); 19 | 20 | @Insert("insert into user(id,name)values(#{id}, #{name})") 21 | public int insert(User user); 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/nian/shop/entity/Goods.java: -------------------------------------------------------------------------------- 1 | package nian.shop.entity; 2 | 3 | import lombok.Data; 4 | 5 | @Data 6 | public class Goods { 7 | private Long id; 8 | private String goodsName; 9 | private String goodsTitle; 10 | private String goodsImg; 11 | private String goodsDetail; 12 | private Double goodsPrice; 13 | private Integer goodsStock; 14 | 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/nian/shop/entity/OrderInfo.java: -------------------------------------------------------------------------------- 1 | package nian.shop.entity; 2 | 3 | import java.util.Date; 4 | 5 | import lombok.Data; 6 | 7 | @Data 8 | public class OrderInfo { 9 | private Long id; 10 | private Long userId; 11 | private Long goodsId; 12 | private Long deliveryAddrId; 13 | private String goodsName; 14 | private Integer goodsCount; 15 | private Double goodsPrice; 16 | private Integer orderChannel; 17 | private Integer status; 18 | private Date createDate; 19 | private Date payDate; 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/nian/shop/entity/SecondGoods.java: -------------------------------------------------------------------------------- 1 | package nian.shop.entity; 2 | 3 | import java.util.Date; 4 | 5 | import lombok.Data; 6 | 7 | @Data 8 | public class SecondGoods { 9 | private Long id; 10 | private Long goodsId; 11 | private Integer stockCount; 12 | private Date startDate; 13 | private Date endDate; 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/nian/shop/entity/SecondOrder.java: -------------------------------------------------------------------------------- 1 | package nian.shop.entity; 2 | 3 | import lombok.Data; 4 | 5 | @Data 6 | public class SecondOrder { 7 | private Long id; 8 | private Long userId; 9 | private Long orderId; 10 | private Long goodsId; 11 | 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/nian/shop/entity/SecondUser.java: -------------------------------------------------------------------------------- 1 | package nian.shop.entity; 2 | 3 | import java.util.Date; 4 | 5 | import lombok.Data; 6 | 7 | @Data 8 | public class SecondUser { 9 | private Long id; 10 | private String nickname; 11 | private String password; 12 | private String salt; 13 | private String head; 14 | private Date registerDate; 15 | private Date lastLoginDate; 16 | private Integer loginCount; 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/nian/shop/entity/User.java: -------------------------------------------------------------------------------- 1 | package nian.shop.entity; 2 | 3 | import lombok.Data; 4 | 5 | @Data 6 | public class User { 7 | int id; 8 | String name; 9 | } 10 | -------------------------------------------------------------------------------- /src/main/java/nian/shop/exception/GlobalExceptionHandler.java: -------------------------------------------------------------------------------- 1 | package nian.shop.exception; 2 | 3 | import java.util.List; 4 | 5 | import javax.servlet.http.HttpServletRequest; 6 | 7 | import org.springframework.validation.BindException; 8 | import org.springframework.validation.ObjectError; 9 | import org.springframework.web.bind.annotation.ControllerAdvice; 10 | import org.springframework.web.bind.annotation.ExceptionHandler; 11 | import org.springframework.web.bind.annotation.ResponseBody; 12 | 13 | import nian.shop.DTO.ResultDTO; 14 | import nian.shop.utils.ResultCode; 15 | 16 | 17 | 18 | @ControllerAdvice 19 | @ResponseBody 20 | public class GlobalExceptionHandler { 21 | //拦截所有exception 22 | @ExceptionHandler(value=Exception.class) 23 | public ResultDTO exceptionHandler(HttpServletRequest request, Exception e){ 24 | e.printStackTrace(); 25 | if(e instanceof SecondException) { 26 | SecondException ex = (SecondException)e; 27 | return ResultDTO.error(ex.getResultDTO().getCode(), ex.getResultDTO().getMsg()); 28 | } else if(e instanceof BindException) { 29 | BindException ex = (BindException)e; 30 | List errors = ex.getAllErrors(); 31 | ObjectError error = errors.get(0); 32 | String msg = error.getDefaultMessage(); 33 | return ResultDTO.error(ResultCode.REQUEST_ERROR.getCode(), msg); 34 | } else { 35 | return ResultDTO.error(ResultCode.SERVER_ERROR.getCode(), ""); 36 | } 37 | } 38 | } -------------------------------------------------------------------------------- /src/main/java/nian/shop/exception/SecondException.java: -------------------------------------------------------------------------------- 1 | package nian.shop.exception; 2 | 3 | import nian.shop.DTO.ResultDTO; 4 | 5 | public class SecondException extends RuntimeException { 6 | 7 | private static final long serialVersionUID = 1L; 8 | 9 | private ResultDTO resultDTO; 10 | 11 | public SecondException(ResultDTO res) { 12 | super(res.getMsg()); 13 | resultDTO = res; 14 | } 15 | 16 | public ResultDTO getResultDTO() { 17 | return resultDTO; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/nian/shop/redis/AccessKey.java: -------------------------------------------------------------------------------- 1 | package nian.shop.redis; 2 | /** 3 | * @author created by NianTianlei 4 | * @createDate on 2018年6月4日 下午9:26:39 5 | */ 6 | public class AccessKey extends BasePrefix{ 7 | 8 | public static AccessKey access = new AccessKey(5, "access"); 9 | 10 | private AccessKey(int expireSeconds, String prefix) { 11 | super(expireSeconds, prefix); 12 | } 13 | 14 | public static AccessKey withExpire(int expireSeconds) { 15 | return new AccessKey(expireSeconds, "access"); 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/nian/shop/redis/BasePrefix.java: -------------------------------------------------------------------------------- 1 | package nian.shop.redis; 2 | 3 | import java.util.Random; 4 | 5 | public abstract class BasePrefix implements KeyPrefix{ 6 | 7 | private int expireSeconds; 8 | 9 | private String prefix; 10 | 11 | public BasePrefix(String prefix) {//0代表永不过期 12 | this(0, prefix); 13 | } 14 | 15 | public BasePrefix(int expireSeconds, String prefix) { 16 | this.expireSeconds = expireSeconds; 17 | this.prefix = prefix; 18 | } 19 | 20 | public BasePrefix(int expireSeconds, boolean addRandom, String prefix) { 21 | if(addRandom) { 22 | Random random = new Random(System.currentTimeMillis()); 23 | int extend = expireSeconds / 5; 24 | int ran = random.nextInt(extend); 25 | int finalExtend = extend / 2 - ran; 26 | this.expireSeconds = expireSeconds + finalExtend; 27 | } else { 28 | this.expireSeconds = expireSeconds; 29 | } 30 | this.prefix = prefix; 31 | } 32 | 33 | public int expireSeconds() {//默认0代表永不过期 34 | return expireSeconds; 35 | } 36 | 37 | public String getPrefix() { 38 | String className = getClass().getSimpleName(); 39 | return className+":" + prefix; //类名:prefix 40 | } 41 | 42 | } 43 | -------------------------------------------------------------------------------- /src/main/java/nian/shop/redis/GoodsKey.java: -------------------------------------------------------------------------------- 1 | package nian.shop.redis; 2 | 3 | public class GoodsKey extends BasePrefix { 4 | 5 | private GoodsKey(int expireSeconds, String prefix) { 6 | super(expireSeconds, prefix); 7 | } 8 | 9 | private GoodsKey(String prefix) { 10 | super(prefix); 11 | } 12 | 13 | public GoodsKey(int expireSeconds, boolean addRandom, String prefix) { 14 | 15 | super(expireSeconds, addRandom, prefix); 16 | } 17 | 18 | public static GoodsKey getGoodsList = new GoodsKey(30, "gl"); 19 | public static GoodsKey getGoodsDetail1 = new GoodsKey(60, "gd"); 20 | public static GoodsKey getSecondKillGoodsStock = new GoodsKey("gs"); 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/nian/shop/redis/KeyPrefix.java: -------------------------------------------------------------------------------- 1 | package nian.shop.redis; 2 | 3 | public interface KeyPrefix { 4 | 5 | public int expireSeconds(); 6 | 7 | public String getPrefix(); 8 | 9 | } 10 | -------------------------------------------------------------------------------- /src/main/java/nian/shop/redis/OrderKey.java: -------------------------------------------------------------------------------- 1 | package nian.shop.redis; 2 | 3 | public class OrderKey extends BasePrefix { 4 | 5 | public OrderKey(int expireSeconds, String prefix) { 6 | super(expireSeconds, prefix); 7 | } 8 | public static OrderKey getMiaoshaOrderByUidGid = new OrderKey(0, "moug"); 9 | } 10 | -------------------------------------------------------------------------------- /src/main/java/nian/shop/redis/RedisConfig.java: -------------------------------------------------------------------------------- 1 | package nian.shop.redis; 2 | 3 | import org.springframework.boot.context.properties.ConfigurationProperties; 4 | import org.springframework.stereotype.Component; 5 | 6 | import lombok.Data; 7 | 8 | @Component 9 | @ConfigurationProperties(prefix="redis") 10 | @Data 11 | public class RedisConfig { 12 | private String host; 13 | private int port; 14 | private int timeout; 15 | private int poolMaxTotal; 16 | private int poolMaxIdle; 17 | private int poolMaxWait; 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/nian/shop/redis/RedisPoolFactory.java: -------------------------------------------------------------------------------- 1 | package nian.shop.redis; 2 | 3 | import org.springframework.beans.factory.annotation.Autowired; 4 | import org.springframework.context.annotation.Bean; 5 | import org.springframework.stereotype.Service; 6 | 7 | import redis.clients.jedis.JedisPool; 8 | import redis.clients.jedis.JedisPoolConfig; 9 | 10 | @Service 11 | public class RedisPoolFactory { 12 | @Autowired 13 | RedisConfig redisConfig; 14 | 15 | @Bean 16 | public JedisPool JedisPoolFactory() { 17 | JedisPoolConfig jedispoolConfig = new JedisPoolConfig(); 18 | jedispoolConfig.setMaxIdle(redisConfig.getPoolMaxIdle()); 19 | jedispoolConfig.setMaxTotal(redisConfig.getPoolMaxTotal()); 20 | jedispoolConfig.setMaxWaitMillis(redisConfig.getPoolMaxWait() * 1000); 21 | JedisPool jedisPool = new JedisPool(jedispoolConfig, redisConfig.getHost(), redisConfig.getPort(), 22 | redisConfig.getTimeout() * 1000); 23 | return jedisPool; 24 | 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/nian/shop/redis/SecondKey.java: -------------------------------------------------------------------------------- 1 | package nian.shop.redis; 2 | 3 | public class SecondKey extends BasePrefix{ 4 | 5 | private SecondKey(String prefix) { 6 | super(prefix); 7 | } 8 | private SecondKey(int expireSeconds, String prefix) { 9 | super(expireSeconds, prefix); 10 | } 11 | public static SecondKey isGoodsOver = new SecondKey("go"); 12 | public static SecondKey secondKillPath = new SecondKey(60, "skp"); 13 | public static SecondKey secondKillVerifyCode = new SecondKey(300, "skvc"); 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/nian/shop/redis/SecondUserKey.java: -------------------------------------------------------------------------------- 1 | package nian.shop.redis; 2 | 3 | public class SecondUserKey extends BasePrefix{ 4 | 5 | private static final int TOKEN_EXPIRE_TIME = 3600*24 * 2; 6 | private SecondUserKey(int expireSeconds, String prefix) { 7 | super(expireSeconds, prefix); 8 | } 9 | public static SecondUserKey token = new SecondUserKey(TOKEN_EXPIRE_TIME, "tk"); 10 | public static SecondUserKey getById = new SecondUserKey(TOKEN_EXPIRE_TIME, "id"); 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/nian/shop/redis/UserKey.java: -------------------------------------------------------------------------------- 1 | package nian.shop.redis; 2 | 3 | public class UserKey extends BasePrefix{ 4 | 5 | private UserKey(String prefix) { 6 | super(prefix); 7 | } 8 | public static UserKey getById = new UserKey("id"); 9 | public static UserKey getByName = new UserKey("name"); 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/nian/shop/rocketmq/ConsumerDemo.java: -------------------------------------------------------------------------------- 1 | package nian.shop.rocketmq; 2 | 3 | import java.util.List; 4 | 5 | import com.alibaba.rocketmq.client.consumer.DefaultMQPushConsumer; 6 | import com.alibaba.rocketmq.client.consumer.listener.ConsumeConcurrentlyContext; 7 | import com.alibaba.rocketmq.client.consumer.listener.ConsumeConcurrentlyStatus; 8 | import com.alibaba.rocketmq.client.consumer.listener.MessageListenerConcurrently; 9 | import com.alibaba.rocketmq.client.exception.MQClientException; 10 | import com.alibaba.rocketmq.common.message.MessageExt; 11 | 12 | /** 13 | * @author created by NianTianlei 14 | * @createDate on 2018年6月10日 下午8:09:04 15 | */ 16 | public class ConsumerDemo { 17 | public static void main(String[] args) throws MQClientException { 18 | DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("second_group"); 19 | 20 | consumer.setNamesrvAddr("127.0.0.1:9876"); 21 | consumer.setInstanceName("consumer"); 22 | consumer.subscribe("TopicD", "TagD"); 23 | System.out.println("开始接收数据"); 24 | consumer.registerMessageListener(new MessageListenerConcurrently() { 25 | @Override 26 | public ConsumeConcurrentlyStatus consumeMessage( 27 | List msgs, ConsumeConcurrentlyContext context) { 28 | for (MessageExt msg : msgs) { 29 | System.out.println(new String(msg.getBody())); 30 | } 31 | return ConsumeConcurrentlyStatus.CONSUME_SUCCESS; 32 | } 33 | }); 34 | consumer.start(); 35 | System.out.println("Consumer Started."); 36 | } 37 | } 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /src/main/java/nian/shop/rocketmq/ProducerDemo.java: -------------------------------------------------------------------------------- 1 | package nian.shop.rocketmq; 2 | 3 | import com.alibaba.rocketmq.client.producer.DefaultMQProducer; 4 | import com.alibaba.rocketmq.client.producer.SendCallback; 5 | import com.alibaba.rocketmq.client.producer.SendResult; 6 | import com.alibaba.rocketmq.common.message.Message; 7 | import com.alibaba.rocketmq.remoting.common.RemotingHelper; 8 | 9 | /** 10 | * @author created by NianTianlei 11 | * @createDate on 2018年6月10日 下午8:08:31 12 | */ 13 | public class ProducerDemo { 14 | public static void main(String[] args) throws Exception { 15 | //Instantiate with a producer group name. 16 | DefaultMQProducer producer = new DefaultMQProducer("second_group"); 17 | producer.setNamesrvAddr("127.0.0.1:9876"); 18 | producer.setInstanceName("producer"); 19 | //Launch the instance. 20 | producer.start(); 21 | producer.setRetryTimesWhenSendAsyncFailed(0); 22 | System.out.println("开始发送数据"); 23 | try { 24 | //Create a message instance, specifying topic, tag and message body. 25 | Message msg = new Message("TopicD",// topic 26 | "TagD", 27 | "Hello Hello world Hello world Hello world Hello world".getBytes(RemotingHelper.DEFAULT_CHARSET));// body 28 | 29 | producer.send(msg, new SendCallback() { 30 | @Override 31 | public void onSuccess(SendResult sendResult) { 32 | System.out.printf("%-10d OK %s %n", "成功", 33 | sendResult.getMsgId()); 34 | } 35 | @Override 36 | public void onException(Throwable e) { 37 | System.out.printf("%-10d Exception %s %n", "异常", e); 38 | e.printStackTrace(); 39 | } 40 | }); 41 | } catch (Exception e) { 42 | e.printStackTrace(); 43 | } 44 | System.out.println("全部发送完成"); 45 | producer.shutdown(); 46 | } 47 | } -------------------------------------------------------------------------------- /src/main/java/nian/shop/rocketmq/RocketMQConfig.java: -------------------------------------------------------------------------------- 1 | package nian.shop.rocketmq; 2 | 3 | import org.springframework.context.annotation.Bean; 4 | import org.springframework.context.annotation.Configuration; 5 | 6 | import com.alibaba.rocketmq.client.exception.MQClientException; 7 | import com.alibaba.rocketmq.client.producer.DefaultMQProducer; 8 | 9 | /** 10 | * @author created by NianTianlei 11 | * @createDate on 2018年6月11日 上午7:50:01 12 | */ 13 | @Configuration 14 | public class RocketMQConfig { 15 | 16 | public static final String SECOND_TOPIC = "secondKilling_topic"; 17 | 18 | public static final String SECOND_GROUP = "secondKilling_group"; 19 | 20 | public static final String namesrvAddr = "127.0.0.1:9876"; 21 | 22 | @Bean 23 | public DefaultMQProducer defaultMQProducer(){ 24 | DefaultMQProducer defaultMQProducer = new DefaultMQProducer(RocketMQConfig.SECOND_GROUP); 25 | defaultMQProducer.setNamesrvAddr(namesrvAddr); 26 | defaultMQProducer.setRetryTimesWhenSendAsyncFailed(0); 27 | try { 28 | defaultMQProducer.start(); 29 | } catch (MQClientException e) { 30 | e.printStackTrace(); 31 | } 32 | return defaultMQProducer; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/nian/shop/rocketmq/RocketMQReceiver.java: -------------------------------------------------------------------------------- 1 | package nian.shop.rocketmq; 2 | 3 | import java.util.List; 4 | 5 | import javax.annotation.PostConstruct; 6 | 7 | import org.slf4j.Logger; 8 | import org.slf4j.LoggerFactory; 9 | import org.springframework.beans.factory.annotation.Autowired; 10 | import org.springframework.context.annotation.Configuration; 11 | 12 | import com.alibaba.rocketmq.client.consumer.DefaultMQPushConsumer; 13 | import com.alibaba.rocketmq.client.consumer.listener.ConsumeConcurrentlyContext; 14 | import com.alibaba.rocketmq.client.consumer.listener.ConsumeConcurrentlyStatus; 15 | import com.alibaba.rocketmq.client.consumer.listener.MessageListenerConcurrently; 16 | import com.alibaba.rocketmq.client.exception.MQClientException; 17 | import com.alibaba.rocketmq.common.consumer.ConsumeFromWhere; 18 | import com.alibaba.rocketmq.common.message.MessageExt; 19 | import com.nian.rabbitmq.SecondKillMessage; 20 | 21 | import nian.shop.VO.GoodsVo; 22 | import nian.shop.entity.SecondOrder; 23 | import nian.shop.entity.SecondUser; 24 | import nian.shop.service.GoodsService; 25 | import nian.shop.service.MqReceiver; 26 | import nian.shop.service.OrderService; 27 | import nian.shop.service.RedisService; 28 | import nian.shop.service.SecondKillService; 29 | 30 | /** 31 | * @author created by NianTianlei 32 | * @createDate on 2018年6月11日 上午8:06:26 33 | */ 34 | @Configuration 35 | public class RocketMQReceiver { 36 | private static Logger log = LoggerFactory.getLogger(MqReceiver.class); 37 | 38 | @Autowired 39 | GoodsService goodsService; 40 | @Autowired 41 | OrderService orderService; 42 | @Autowired 43 | SecondKillService secondKillService; 44 | 45 | /* public void receive() { 46 | DefaultMQPushConsumer consumer = new DefaultMQPushConsumer(RocketMQConfig.SECOND_GROUP); 47 | //指定NameServer地址,多个地址以 ; 隔开 48 | consumer.setNamesrvAddr(RocketMQConfig.namesrvAddr); 49 | 50 | try { 51 | consumer.subscribe(RocketMQConfig.SECOND_TOPIC, "push"); 52 | //设置Consumer第一次启动是从队列头部开始消费还是队列尾部开始消费 53 | //如果非第一次启动,那么按照上次消费的位置继续消费 54 | consumer.setConsumeFromWhere(ConsumeFromWhere.CONSUME_FROM_FIRST_OFFSET); 55 | 56 | 57 | 58 | 59 | consumer.registerMessageListener(new MessageListenerConcurrently() { 60 | @Override 61 | public ConsumeConcurrentlyStatus consumeMessage(List msgs, ConsumeConcurrentlyContext context) { 62 | System.out.println(JSON.toJSONString(msgs)); 63 | for(MessageExt messageExt : msgs){ 64 | byte[] bytes = messageExt.getBody(); 65 | String string = new String(bytes); 66 | log.info("receive message: " + string); 67 | } 68 | return ConsumeConcurrentlyStatus.CONSUME_SUCCESS; 69 | } 70 | }); 71 | } catch (MQClientException e) { 72 | e.printStackTrace(); 73 | } 74 | } 75 | */ 76 | @PostConstruct 77 | public void miaoShaConsumer(){ 78 | DefaultMQPushConsumer consumer = new DefaultMQPushConsumer(RocketMQConfig.SECOND_GROUP); 79 | //可以设置多个地址,以;隔开 80 | consumer.setNamesrvAddr(RocketMQConfig.namesrvAddr); 81 | try { 82 | consumer.subscribe(RocketMQConfig.SECOND_TOPIC, "push"); 83 | //设置Consumer第一次启动是从队列头部开始消费还是队列尾部开始消费 84 | //如果非第一次启动,那么按照上次消费的位置继续消费 85 | consumer.setConsumeFromWhere(ConsumeFromWhere.CONSUME_FROM_FIRST_OFFSET); 86 | 87 | consumer.registerMessageListener(new MessageListenerConcurrently() { 88 | @Override 89 | public ConsumeConcurrentlyStatus consumeMessage(List msgs, ConsumeConcurrentlyContext context) { 90 | for(MessageExt messageExt : msgs){ 91 | byte[] bytes = messageExt.getBody(); 92 | String string = new String(bytes); 93 | log.info("receive message: " + string); 94 | //至此我们已经获取到了秒杀用户的信息 95 | SecondKillMessage secondKillMessage = RedisService.stringToBean(string, SecondKillMessage.class); 96 | SecondUser secondUser = secondKillMessage.getUser(); 97 | long goodsId = secondKillMessage.getGoodsId(); 98 | GoodsVo goods = goodsService.getGoodsVoByGoodsId(goodsId); 99 | int stock = goods.getStockCount(); 100 | if(stock <= 0) { 101 | break; 102 | } 103 | 104 | //根据用户和id查看当前用户是否秒杀到 105 | SecondOrder order = orderService.getSecondOrderByUserIdandGoodsId(secondUser.getId(), goodsId); 106 | if(order != null) { 107 | continue; 108 | } 109 | //减库存 下订单 写入秒杀订单 110 | secondKillService.secondKill(secondUser, goods); 111 | } 112 | return ConsumeConcurrentlyStatus.CONSUME_SUCCESS; 113 | } 114 | }); 115 | consumer.start(); 116 | } catch (MQClientException e) { 117 | e.printStackTrace(); 118 | } 119 | } 120 | } 121 | -------------------------------------------------------------------------------- /src/main/java/nian/shop/rocketmq/RocketMQSender.java: -------------------------------------------------------------------------------- 1 | package nian.shop.rocketmq; 2 | 3 | import java.io.UnsupportedEncodingException; 4 | 5 | import org.slf4j.Logger; 6 | import org.slf4j.LoggerFactory; 7 | import org.springframework.beans.factory.annotation.Autowired; 8 | import org.springframework.stereotype.Service; 9 | 10 | import com.alibaba.rocketmq.client.exception.MQBrokerException; 11 | import com.alibaba.rocketmq.client.exception.MQClientException; 12 | import com.alibaba.rocketmq.client.producer.DefaultMQProducer; 13 | import com.alibaba.rocketmq.client.producer.SendCallback; 14 | import com.alibaba.rocketmq.client.producer.SendResult; 15 | import com.alibaba.rocketmq.common.message.Message; 16 | import com.alibaba.rocketmq.remoting.common.RemotingHelper; 17 | import com.alibaba.rocketmq.remoting.exception.RemotingException; 18 | 19 | import nian.shop.controller.SecondController; 20 | import nian.shop.service.RedisService; 21 | 22 | /** 23 | * @author created by NianTianlei 24 | * @createDate on 2018年6月11日 上午7:57:54 25 | */ 26 | @Service 27 | public class RocketMQSender { 28 | private static Logger log = LoggerFactory.getLogger(SecondController.class); 29 | 30 | @Autowired 31 | DefaultMQProducer defaultMQProducer; 32 | 33 | public void sendSecondKillMessage(Object value) throws InterruptedException, RemotingException, MQClientException, MQBrokerException, UnsupportedEncodingException { 34 | byte[] bytes = RedisService.beanToString(value).getBytes(RemotingHelper.DEFAULT_CHARSET); 35 | log.info("发送的消息是: " + new String(bytes)); 36 | Message message = new Message(RocketMQConfig.SECOND_TOPIC, "push", bytes); 37 | defaultMQProducer.send(message, new SendCallback() { 38 | @Override 39 | public void onSuccess(SendResult sendResult) { 40 | log.info("成功了》》" + "消息码为: " + sendResult.getMsgId()); 41 | } 42 | @Override 43 | public void onException(Throwable e) { 44 | log.info("异常" + e); 45 | e.printStackTrace(); 46 | } 47 | }); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/main/java/nian/shop/service/GoodsService.java: -------------------------------------------------------------------------------- 1 | package nian.shop.service; 2 | 3 | import java.util.List; 4 | 5 | import org.springframework.beans.factory.annotation.Autowired; 6 | import org.springframework.stereotype.Service; 7 | 8 | import nian.shop.VO.GoodsVo; 9 | import nian.shop.dao.GoodsDao; 10 | import nian.shop.entity.SecondGoods; 11 | 12 | 13 | @Service 14 | public class GoodsService { 15 | 16 | @Autowired 17 | GoodsDao goodsDao; 18 | 19 | public List listGoodsVo(){ 20 | return goodsDao.listGoodsVo(); 21 | } 22 | 23 | public GoodsVo getGoodsVoByGoodsId(long goodsId) { 24 | return goodsDao.getGoodsVoByGoodsId(goodsId); 25 | } 26 | 27 | public boolean reduceStock(GoodsVo goods) { 28 | SecondGoods g = new SecondGoods(); 29 | g.setGoodsId(goods.getId()); 30 | int res = goodsDao.reduceStock(g); 31 | return res > 0; 32 | } 33 | 34 | public void resetStock(List goodsList) { 35 | for(GoodsVo goods : goodsList ) { 36 | SecondGoods g = new SecondGoods(); 37 | g.setGoodsId(goods.getId()); 38 | g.setStockCount(goods.getStockCount()); 39 | goodsDao.resetStock(g); 40 | } 41 | } 42 | 43 | } 44 | -------------------------------------------------------------------------------- /src/main/java/nian/shop/service/MqReceiver.java: -------------------------------------------------------------------------------- 1 | package nian.shop.service; 2 | 3 | import org.slf4j.Logger; 4 | import org.slf4j.LoggerFactory; 5 | import org.springframework.amqp.rabbit.annotation.RabbitListener; 6 | import org.springframework.beans.factory.annotation.Autowired; 7 | import org.springframework.stereotype.Service; 8 | 9 | import com.nian.rabbitmq.MQConfig; 10 | import com.nian.rabbitmq.SecondKillMessage; 11 | 12 | import nian.shop.VO.GoodsVo; 13 | import nian.shop.entity.SecondOrder; 14 | import nian.shop.entity.SecondUser; 15 | 16 | /** 17 | * @author created by NianTianlei 18 | * @createDate on 2018年5月29日 下午1:08:52 19 | */ 20 | @Service 21 | public class MqReceiver { 22 | private static Logger log = LoggerFactory.getLogger(MqReceiver.class); 23 | 24 | @Autowired 25 | RedisService redisService; 26 | 27 | @Autowired 28 | GoodsService goodsService; 29 | 30 | @Autowired 31 | OrderService orderService; 32 | 33 | @Autowired 34 | SecondKillService secondKillService; 35 | 36 | @RabbitListener(queues=MQConfig.MIAOSHA_QUEUE) 37 | public void receive(String message) { 38 | log.info("receive message: " + message); 39 | SecondKillMessage sm = RedisService.stringToBean(message, SecondKillMessage.class); 40 | SecondUser user = sm.getUser(); 41 | long goodsId = sm.getGoodsId(); 42 | 43 | GoodsVo goods = goodsService.getGoodsVoByGoodsId(goodsId); 44 | int stock = goods.getStockCount(); 45 | if(stock <= 0) { 46 | return; 47 | } 48 | 49 | //判断是否已经秒杀到了 50 | SecondOrder order = orderService.getSecondOrderByUserIdandGoodsId(user.getId(), goodsId); 51 | if(order != null) { 52 | return; 53 | } 54 | //减库存 下订单 写入秒杀订单 55 | secondKillService.secondKill(user, goods); 56 | } 57 | 58 | // @RabbitListener(queues=MQConfig.QUEUE) 59 | // public void receive(String msg) { 60 | // log.info("receive message: " + msg); 61 | // } 62 | // @RabbitListener(queues=MQConfig.TOPIC_QUEUE1) 63 | // public void receiveTopic1(String message) { 64 | // log.info(" topic queue1 message:" + message); 65 | // } 66 | // 67 | // @RabbitListener(queues=MQConfig.TOPIC_QUEUE2) 68 | // public void receiveTopic2(String message) { 69 | // log.info(" topic queue2 message:" + message); 70 | // } 71 | // @RabbitListener(queues=MQConfig.HEADER_QUEUE) 72 | // public void receiveHeaderQueue(byte[] message) { 73 | // log.info(" header queue message:" + new String(message)); 74 | // } 75 | } 76 | -------------------------------------------------------------------------------- /src/main/java/nian/shop/service/MqSender.java: -------------------------------------------------------------------------------- 1 | package nian.shop.service; 2 | 3 | import org.slf4j.Logger; 4 | import org.slf4j.LoggerFactory; 5 | import org.springframework.amqp.core.AmqpTemplate; 6 | import org.springframework.beans.factory.annotation.Autowired; 7 | import org.springframework.stereotype.Service; 8 | 9 | import com.nian.rabbitmq.MQConfig; 10 | import com.nian.rabbitmq.SecondKillMessage; 11 | 12 | /** 13 | * @author created by NianTianlei 14 | * @createDate on 2018年5月29日 上午10:05:43 15 | */ 16 | @Service 17 | public class MqSender { 18 | private static Logger log = LoggerFactory.getLogger(MqSender.class); 19 | 20 | @Autowired 21 | AmqpTemplate amqpTemplate; 22 | 23 | /*public void sendMiaoshaMessage(MiaoshaMessage mm) { 24 | String msg = RedisService.beanToString(mm); 25 | log.info("send message:"+msg); 26 | amqpTemplate.convertAndSend(MQConfig.MIAOSHA_QUEUE, msg); 27 | }*/ 28 | // public void send(Object message) { 29 | // String msg = RedisService.beanToString(message); 30 | // log.info("send message: " + message); 31 | // amqpTemplate.convertAndSend(MQConfig.QUEUE, msg); 32 | // } 33 | // public void sendTopic(Object message) { 34 | // String msg = RedisService.beanToString(message); 35 | // log.info("send topic message:" + msg); 36 | // amqpTemplate.convertAndSend(MQConfig.TOPIC_EXCHANGE, "topic.key1", msg + "1"); 37 | // amqpTemplate.convertAndSend(MQConfig.TOPIC_EXCHANGE, "topic.key2", msg + "2"); 38 | // } 39 | // public void sendFanout(Object message) { 40 | // String msg = RedisService.beanToString(message); 41 | // log.info("send fanout message:" + msg); 42 | // amqpTemplate.convertAndSend(MQConfig.FANOUT_EXCHANGE, "", msg); 43 | // } 44 | // public void sendHeader(Object message) { 45 | // String msg = RedisService.beanToString(message); 46 | // log.info("send fanout message:" + msg); 47 | // MessageProperties properties = new MessageProperties(); 48 | // properties.setHeader("header1", "value1"); 49 | // properties.setHeader("header2", "value2"); 50 | // Message obj = new Message(msg.getBytes(), properties); 51 | // amqpTemplate.convertAndSend(MQConfig.HEADERS_EXCHANGE, "", obj); 52 | // } 53 | 54 | public void sendSecondKillMessage(SecondKillMessage sm) { 55 | String msg = RedisService.beanToString(sm); 56 | log.info("send message:" + msg); 57 | amqpTemplate.convertAndSend(MQConfig.MIAOSHA_QUEUE, msg); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/main/java/nian/shop/service/OrderService.java: -------------------------------------------------------------------------------- 1 | package nian.shop.service; 2 | 3 | import java.util.Date; 4 | 5 | import org.springframework.beans.factory.annotation.Autowired; 6 | import org.springframework.stereotype.Service; 7 | import org.springframework.transaction.annotation.Isolation; 8 | import org.springframework.transaction.annotation.Propagation; 9 | import org.springframework.transaction.annotation.Transactional; 10 | 11 | import nian.shop.VO.GoodsVo; 12 | import nian.shop.dao.OrderDao; 13 | import nian.shop.entity.OrderInfo; 14 | import nian.shop.entity.SecondOrder; 15 | import nian.shop.entity.SecondUser; 16 | import nian.shop.redis.OrderKey; 17 | import nian.shop.utils.SecondStatusEnum; 18 | 19 | @Service 20 | public class OrderService { 21 | @Autowired 22 | OrderDao orderDao; 23 | @Autowired 24 | RedisService redisService; 25 | 26 | public SecondOrder getSecondOrderByUserIdandGoodsId(long userId, long goodsId) { 27 | // return orderDao.getSecondOrderByUserIdandGoodsId(userId, goodsId); 28 | //查缓存 29 | return redisService.get(OrderKey.getMiaoshaOrderByUidGid, "" + userId + "_" + goodsId, SecondOrder.class); 30 | } 31 | @Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.DEFAULT) 32 | public OrderInfo createOrder(SecondUser user, GoodsVo goods) { 33 | OrderInfo orderInfo = new OrderInfo(); 34 | orderInfo.setCreateDate(new Date()); 35 | orderInfo.setDeliveryAddrId(0L); 36 | orderInfo.setGoodsCount(1); 37 | orderInfo.setGoodsId(goods.getId()); 38 | orderInfo.setGoodsName(goods.getGoodsName()); 39 | orderInfo.setGoodsPrice(goods.getSecondPrice()); 40 | orderInfo.setOrderChannel(1); 41 | orderInfo.setStatus(SecondStatusEnum.NO_PAY.getStatus()); 42 | orderInfo.setUserId(user.getId()); 43 | orderDao.insert(orderInfo); 44 | SecondOrder secondOrder = new SecondOrder(); 45 | secondOrder.setGoodsId(goods.getId()); 46 | secondOrder.setOrderId(orderInfo.getId()); 47 | secondOrder.setUserId(user.getId()); 48 | orderDao.insertSecondOrder(secondOrder); 49 | //写缓存 50 | redisService.set(OrderKey.getMiaoshaOrderByUidGid, "" + user.getId() + "_" + goods.getId(), secondOrder); 51 | return orderInfo; 52 | } 53 | 54 | 55 | public OrderInfo getOrderById(long orderId) { 56 | return orderDao.getOrderById(orderId); 57 | } 58 | public void deleteOrders() { 59 | orderDao.deleteOrders(); 60 | orderDao.deleteMiaoshaOrders(); 61 | } 62 | 63 | } 64 | -------------------------------------------------------------------------------- /src/main/java/nian/shop/service/SecondUserService.java: -------------------------------------------------------------------------------- 1 | package nian.shop.service; 2 | 3 | import javax.servlet.http.Cookie; 4 | import javax.servlet.http.HttpServletResponse; 5 | 6 | import org.slf4j.Logger; 7 | import org.slf4j.LoggerFactory; 8 | import org.springframework.beans.factory.annotation.Autowired; 9 | import org.springframework.stereotype.Service; 10 | 11 | import com.alibaba.rocketmq.shade.com.alibaba.fastjson.JSON; 12 | 13 | import nian.shop.DTO.ResultDTO; 14 | import nian.shop.VO.LoginVO; 15 | import nian.shop.bloomFilter.BloomFilterCache; 16 | import nian.shop.dao.SecondUserDao; 17 | import nian.shop.entity.SecondUser; 18 | import nian.shop.exception.SecondException; 19 | import nian.shop.redis.SecondUserKey; 20 | import nian.shop.utils.MD5Util; 21 | import nian.shop.utils.ResultCode; 22 | import nian.shop.utils.UUIDUtil; 23 | import nian.shop.utils.ValidatorUtil; 24 | 25 | /** 26 | * 27 | * @author Niantianlei 28 | * @date 2018年5月19日 下午4:45:17 29 | */ 30 | @Service 31 | public class SecondUserService { 32 | private static Logger log = LoggerFactory.getLogger(SecondUserService.class); 33 | public static final String COOKIE_NAME_TOKEN = "token"; 34 | 35 | @Autowired 36 | SecondUserDao secondUserDao; 37 | 38 | @Autowired 39 | RedisService redisService; 40 | 41 | public SecondUser getById(long id) { 42 | //缓存优化 43 | /*SecondUser user = redisService.get(SecondUserKey.getById, "" + id, SecondUser.class); 44 | if(user != null) { 45 | return user; 46 | } 47 | user = secondUserDao.getById(id); 48 | if(user != null) { 49 | redisService.set(SecondUserKey.getById, "" + id, SecondUser.class); 50 | }*/ 51 | SecondUser user = secondUserDao.getById(id); 52 | return user; 53 | } 54 | 55 | public boolean updatePassword(String token, long id, String newPassword) { 56 | SecondUser user = getById(id); 57 | if(user == null) { 58 | throw new SecondException(ResultDTO.error("user不存在")); 59 | } 60 | //更新数据库 61 | SecondUser toBeUpdate = new SecondUser(); 62 | toBeUpdate.setId(id); 63 | toBeUpdate.setPassword(MD5Util.constructDBPassword(newPassword, user.getSalt())); 64 | secondUserDao.update(toBeUpdate); 65 | /** 66 | * 处理缓存 67 | */ 68 | //删user 69 | redisService.delete(SecondUserKey.getById, "" + id); 70 | //更新token 71 | user.setPassword(toBeUpdate.getPassword()); 72 | redisService.set(SecondUserKey.token, token, user); 73 | return true; 74 | } 75 | 76 | public SecondUser getByToken(HttpServletResponse response, String token) { 77 | if(ValidatorUtil.isEmpty(token)) { 78 | return null; 79 | } 80 | SecondUser user = redisService.get(SecondUserKey.token, token, SecondUser.class); 81 | //刷新有效时间 82 | if(user != null) addCookie(response, token, user); 83 | return user; 84 | } 85 | 86 | public String login(HttpServletResponse response, LoginVO loginVO) { 87 | log.info("登陸信息: " + JSON.toJSONString(loginVO)); 88 | if(loginVO == null) { 89 | throw new SecondException(ResultDTO.error(ResultCode.SERVER_ERROR.getCode(), "服务端异常")); 90 | } 91 | 92 | //首先要过布隆过滤器 93 | if(!BloomFilterCache.bloomFilter.check(loginVO.getMobile())) { 94 | throw new SecondException(ResultDTO.fail("该用户不存在(未通过布隆过滤器)")); 95 | } 96 | 97 | String mobile = loginVO.getMobile(); 98 | String formPassword = loginVO.getPassword(); 99 | //判断手机号是否存在 100 | SecondUser user = getById(Long.parseLong(mobile)); 101 | if(user == null) { 102 | throw new SecondException(ResultDTO.error(ResultCode.REQUEST_ERROR.getCode(), "手机号码不存在")); 103 | } 104 | //验证密码 105 | String dbPassword = user.getPassword(); 106 | String saltDB = user.getSalt(); 107 | String afterProcessPassword = MD5Util.constructDBPassword(formPassword, saltDB); 108 | if(!afterProcessPassword.equals(dbPassword)) { 109 | throw new SecondException(ResultDTO.error(ResultCode.REQUEST_ERROR.getCode(), "密码错误")); 110 | } 111 | String token = UUIDUtil.uuid(); 112 | addCookie(response, token, user); 113 | return token; 114 | } 115 | //生成cookie 116 | private void addCookie(HttpServletResponse response, String token, SecondUser user) { 117 | redisService.set(SecondUserKey.token, token, user); 118 | Cookie cookie = new Cookie(COOKIE_NAME_TOKEN, token); 119 | cookie.setMaxAge(SecondUserKey.token.expireSeconds()); 120 | cookie.setPath("/"); 121 | response.addCookie(cookie); 122 | } 123 | 124 | } 125 | -------------------------------------------------------------------------------- /src/main/java/nian/shop/service/UserService.java: -------------------------------------------------------------------------------- 1 | package nian.shop.service; 2 | 3 | 4 | import org.springframework.beans.factory.annotation.Autowired; 5 | import org.springframework.stereotype.Service; 6 | import org.springframework.transaction.annotation.Transactional; 7 | 8 | import nian.shop.dao.UserDao; 9 | import nian.shop.entity.User; 10 | 11 | @Service 12 | public class UserService { 13 | 14 | @Autowired 15 | UserDao userDao; 16 | 17 | public User getUserById(int id) { 18 | return userDao.getById(id); 19 | } 20 | 21 | @Transactional 22 | public boolean tx() { 23 | // TODO Auto-generated method stub 24 | User u1 = new User(); 25 | u1.setId(2); 26 | u1.setName("123"); 27 | userDao.insert(u1); 28 | 29 | User u2 = new User(); 30 | u2.setId(1); 31 | u2.setName("u1"); 32 | userDao.insert(u2); 33 | return true; 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/nian/shop/task/BloomFilterTask.java: -------------------------------------------------------------------------------- 1 | package nian.shop.task; 2 | 3 | import java.util.List; 4 | 5 | import javax.annotation.PostConstruct; 6 | 7 | import org.slf4j.Logger; 8 | import org.slf4j.LoggerFactory; 9 | import org.springframework.beans.factory.annotation.Autowired; 10 | import org.springframework.stereotype.Component; 11 | 12 | import nian.shop.bloomFilter.BloomFilter; 13 | import nian.shop.bloomFilter.BloomFilterCache; 14 | import nian.shop.dao.SecondUserDao; 15 | import nian.shop.entity.SecondUser; 16 | 17 | /** 18 | * @author created by NianTianlei 19 | * @createDate on 2018年6月24日 下午7:59:09 20 | */ 21 | @Component 22 | public class BloomFilterTask { 23 | private static Logger log = LoggerFactory.getLogger(BloomFilterTask.class); 24 | @Autowired 25 | SecondUserDao secondUserDao; 26 | 27 | @PostConstruct 28 | public void initBloomFilterCache() { 29 | log.info("初始化bloomFilter"); 30 | List list = secondUserDao.queryAllSecondUser(); 31 | BloomFilter bloomFilter = new BloomFilter(); 32 | list.forEach(secondUser -> { 33 | bloomFilter.add(secondUser.getId().toString()); 34 | }); 35 | BloomFilterCache.bloomFilter = bloomFilter; 36 | // log.info("bloomFilter初始化完毕!"); 37 | // System.out.println("测试结果1:" + BloomFilterCache.bloomFilter.check("13000000981")); 38 | // Long phoneTest = 33000000981l; 39 | // System.out.println("测试结果2:" + BloomFilterCache.bloomFilter.check(phoneTest.toString())); 40 | 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/main/java/nian/shop/task/UserDataProduct.java: -------------------------------------------------------------------------------- 1 | package nian.shop.task; 2 | 3 | import java.io.ByteArrayOutputStream; 4 | import java.io.File; 5 | import java.io.InputStream; 6 | import java.io.OutputStream; 7 | import java.io.RandomAccessFile; 8 | import java.net.HttpURLConnection; 9 | import java.net.URL; 10 | import java.util.ArrayList; 11 | import java.util.Date; 12 | import java.util.List; 13 | 14 | import com.alibaba.fastjson.JSON; 15 | import com.alibaba.fastjson.JSONObject; 16 | 17 | import nian.shop.entity.SecondUser; 18 | import nian.shop.utils.MD5Util; 19 | 20 | /** 21 | * @author created by NianTianlei 22 | * @createDate on 2018年5月24日 上午11:20:18 23 | */ 24 | public class UserDataProduct { 25 | private static void createUser(int count) throws Exception{ 26 | List users = new ArrayList<>(count); 27 | //生成用户 28 | for(int i = 0; i < count; i++) { 29 | SecondUser user = new SecondUser(); 30 | user.setId(13000000000L+i); 31 | user.setLoginCount(1); 32 | user.setNickname("user"+i); 33 | user.setRegisterDate(new Date()); 34 | user.setSalt("f9064abc"); 35 | user.setPassword(MD5Util.FromInputToOutput("123456", user.getSalt())); 36 | users.add(user); 37 | } 38 | System.out.println("create user"); 39 | //插入数据库 40 | /* Connection conn = DBUtil.getConn(); 41 | String sql = "insert into second_user(login_count, nickname, register_date, salt, password, id)values(?,?,?,?,?,?)"; 42 | PreparedStatement pstmt = conn.prepareStatement(sql); 43 | for(int i = 0; i < users.size(); i++) { 44 | SecondUser user = users.get(i); 45 | pstmt.setInt(1, user.getLoginCount()); 46 | pstmt.setString(2, user.getNickname()); 47 | pstmt.setTimestamp(3, new Timestamp(user.getRegisterDate().getTime())); 48 | pstmt.setString(4, user.getSalt()); 49 | pstmt.setString(5, user.getPassword()); 50 | pstmt.setLong(6, user.getId()); 51 | pstmt.addBatch(); 52 | } 53 | pstmt.executeBatch(); 54 | pstmt.close(); 55 | conn.close(); 56 | System.out.println("insert to db");*/ 57 | //登录,生成token 58 | String urlString = "http://localhost:8080/login/do_login"; 59 | File file = new File("D:/tokens.txt"); 60 | if(file.exists()) { 61 | file.delete(); 62 | } 63 | RandomAccessFile raf = new RandomAccessFile(file, "rw"); 64 | file.createNewFile(); 65 | raf.seek(0); 66 | for(int i=0;i= 0) { 81 | bout.write(buff, 0 ,len); 82 | } 83 | inputStream.close(); 84 | bout.close(); 85 | String response = new String(bout.toByteArray()); 86 | JSONObject jo = JSON.parseObject(response); 87 | String token = jo.getString("data"); 88 | System.out.println("create token : " + user.getId()); 89 | 90 | String row = user.getId()+","+token; 91 | raf.seek(raf.length()); 92 | raf.write(row.getBytes()); 93 | raf.write("\r\n".getBytes()); 94 | System.out.println("write to file : " + user.getId()); 95 | } 96 | raf.close(); 97 | 98 | System.out.println("over"); 99 | } 100 | 101 | public static void main(String[] args)throws Exception { 102 | createUser(5000); 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /src/main/java/nian/shop/utils/DBUtil.java: -------------------------------------------------------------------------------- 1 | package nian.shop.utils; 2 | 3 | import java.io.InputStream; 4 | import java.sql.Connection; 5 | import java.sql.DriverManager; 6 | import java.util.Properties; 7 | 8 | /** 9 | * @author created by NianTianlei 10 | * @createDate on 2018年5月24日 上午11:47:20 11 | */ 12 | public class DBUtil { 13 | 14 | private static Properties props; 15 | 16 | static { 17 | try { 18 | InputStream in = DBUtil.class.getClassLoader().getResourceAsStream("application.properties"); 19 | props = new Properties(); 20 | props.load(in); 21 | in.close(); 22 | }catch(Exception e) { 23 | e.printStackTrace(); 24 | } 25 | } 26 | 27 | public static Connection getConn() throws Exception{ 28 | String url = props.getProperty("spring.datasource.url"); 29 | String username = props.getProperty("spring.datasource.username"); 30 | String password = props.getProperty("spring.datasource.password"); 31 | String driver = props.getProperty("spring.datasource.driver-class-name"); 32 | Class.forName(driver); 33 | return DriverManager.getConnection(url,username, password); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/nian/shop/utils/MD5Util.java: -------------------------------------------------------------------------------- 1 | package nian.shop.utils; 2 | 3 | import java.util.UUID; 4 | 5 | import org.apache.commons.codec.digest.DigestUtils; 6 | /** 7 | * 8 | * @author Niantianlei 9 | * @date 2018年5月18日 下午3:13:59 10 | */ 11 | public class MD5Util { 12 | public static String md5(String input) { 13 | return DigestUtils.md5Hex(input); 14 | } 15 | 16 | private static final String SALT = "f9064abc"; 17 | 18 | //第一次md5 19 | public static String addSaltProcess(String input) { 20 | String output = "" + SALT.substring(0, 2) + input + SALT.charAt(6) + SALT.charAt(4); 21 | return md5(output); 22 | } 23 | //第二次md5 24 | public static String constructDBPassword(String input, String salt) { 25 | String output = "" + salt.substring(0, 2) + input + salt.charAt(6) + salt.charAt(4); 26 | return md5(output); 27 | } 28 | 29 | 30 | public static String FromInputToOutput(String input, String saltInDB) { 31 | String str = addSaltProcess(input); 32 | String output = constructDBPassword(str, saltInDB); 33 | return output; 34 | } 35 | public static void main(String[] args) { 36 | //产生salt 37 | String uuuid = UUID.randomUUID().toString().substring(0, 8); 38 | System.out.println(uuuid); 39 | 40 | System.out.println(addSaltProcess("123456")); //4672d95aab2010d7501dee60f1ef1ee9 41 | System.out.println(constructDBPassword(addSaltProcess("123456"), "32165498")); 42 | } 43 | 44 | } 45 | -------------------------------------------------------------------------------- /src/main/java/nian/shop/utils/ResultCode.java: -------------------------------------------------------------------------------- 1 | package nian.shop.utils; 2 | 3 | public enum ResultCode { 4 | SUCCESS(0, "success"), 5 | FAIL(1, "fail"), 6 | REQUEST_ERROR(400, "客户端错误"), 7 | SERVER_ERROR(500, "服务端错误"),; 8 | 9 | private int code; 10 | private String msg; 11 | 12 | private ResultCode(int code, String msg) { 13 | this.code = code; 14 | this.msg = msg; 15 | } 16 | 17 | public int getCode() { 18 | return code; 19 | } 20 | public String getMsg() { 21 | return msg; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/nian/shop/utils/SecondResEnum.java: -------------------------------------------------------------------------------- 1 | package nian.shop.utils; 2 | 3 | public enum SecondResEnum { 4 | SECOND_KILL_OVER("库存不足"), 5 | SECOND_KILL_REPEAT("禁止重复秒杀"), 6 | ; 7 | private String msg; 8 | private SecondResEnum(String msg) { 9 | this.msg = msg; 10 | } 11 | public String getMsg() { 12 | return msg; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/nian/shop/utils/SecondStatusEnum.java: -------------------------------------------------------------------------------- 1 | package nian.shop.utils; 2 | /** 3 | * @author created by NianTianlei 4 | * @createDate on 2018年5月23日 下午9:08:54 5 | */ 6 | public enum SecondStatusEnum { 7 | NO_PAY(0, "新建未支付"), 8 | PAID(1, "已支付"), 9 | NO_SHIP(2, "未发货"), 10 | SHIPPED(3, "已发货"), 11 | RECEIVED(4, "已收货"), 12 | SIGNED(5, "已签收"), 13 | REFUNDED(6, "已退款"), 14 | FINISHED(7, "已完成"), 15 | ; 16 | private int status; 17 | private String info; 18 | private SecondStatusEnum(int status, String info) { 19 | this.info = info; 20 | this.status = status; 21 | } 22 | public int getStatus() { 23 | return status; 24 | } 25 | 26 | public String getInfo() { 27 | return info; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/nian/shop/utils/UUIDUtil.java: -------------------------------------------------------------------------------- 1 | package nian.shop.utils; 2 | 3 | import java.util.UUID; 4 | 5 | public class UUIDUtil { 6 | public static String uuid() { 7 | return UUID.randomUUID().toString().replace("-", ""); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/main/java/nian/shop/utils/ValidatorUtil.java: -------------------------------------------------------------------------------- 1 | package nian.shop.utils; 2 | 3 | import java.util.regex.Matcher; 4 | import java.util.regex.Pattern; 5 | 6 | public class ValidatorUtil { 7 | 8 | private static final Pattern mobile_pattern = Pattern.compile("1\\d{10}"); 9 | 10 | public static boolean isMobile(String src) { 11 | if(src == null || src.length() == 0) { 12 | return false; 13 | } 14 | Matcher m = mobile_pattern.matcher(src); 15 | return m.matches(); 16 | } 17 | 18 | public static boolean isEmpty(final CharSequence cs) { 19 | return cs == null || cs.length() == 0; 20 | } 21 | /*public static void main(String[] args) { 22 | System.out.println(isMobile("13812345678")); 23 | System.out.println(isMobile("1381234567")); 24 | }*/ 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/nian/shop/validator/IsMobile.java: -------------------------------------------------------------------------------- 1 | package nian.shop.validator; 2 | 3 | import static java.lang.annotation.ElementType.ANNOTATION_TYPE; 4 | import static java.lang.annotation.ElementType.CONSTRUCTOR; 5 | import static java.lang.annotation.ElementType.FIELD; 6 | import static java.lang.annotation.ElementType.METHOD; 7 | import static java.lang.annotation.ElementType.PARAMETER; 8 | import static java.lang.annotation.RetentionPolicy.RUNTIME; 9 | 10 | import java.lang.annotation.Documented; 11 | import java.lang.annotation.Retention; 12 | import java.lang.annotation.Target; 13 | 14 | import javax.validation.Constraint; 15 | import javax.validation.Payload; 16 | 17 | @Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER }) 18 | @Retention(RUNTIME) 19 | @Documented 20 | @Constraint(validatedBy = {IsMobileValidator.class }) 21 | public @interface IsMobile { 22 | 23 | boolean required() default true;//是否需要传 24 | 25 | String message() default "手机号码格式错误";//提示信息 26 | 27 | Class[] groups() default { }; 28 | 29 | Class[] payload() default { }; 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/nian/shop/validator/IsMobileValidator.java: -------------------------------------------------------------------------------- 1 | package nian.shop.validator; 2 | import javax.validation.ConstraintValidator; 3 | import javax.validation.ConstraintValidatorContext; 4 | 5 | import nian.shop.utils.ValidatorUtil; 6 | 7 | public class IsMobileValidator implements ConstraintValidator { 8 | 9 | private boolean required = false; 10 | 11 | public void initialize(IsMobile constraintAnnotation) { 12 | required = constraintAnnotation.required(); 13 | } 14 | 15 | //校验逻辑 16 | public boolean isValid(String value, ConstraintValidatorContext context) { 17 | if(required) { 18 | return ValidatorUtil.isMobile(value); 19 | }else { 20 | if(value == null || value.length() == 0) { 21 | return true; 22 | }else { 23 | return ValidatorUtil.isMobile(value); 24 | } 25 | } 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | # thymeleaf 2 | spring.thymeleaf.cache=false 3 | spring.thymeleaf.enabled=true 4 | spring.thymeleaf.content-type=text/html 5 | spring.thymeleaf.prefix=classpath:/templates/ 6 | spring.thymeleaf.suffix=.html 7 | spring.thymeleaf.encoding=UTF-8 8 | spring.thymeleaf.mode=HTML5 9 | # mybatis 10 | mybatis.type-aliases-package=nian.shop.entity 11 | mybatis.configuration.map-underscore-to-camel-case=true 12 | mybatis.configuration.default-fetch-size=100 13 | mybatis.configuration.default-statement-timeout=3000 14 | mybatis.mapperLocations = classpath:nian/shop/dao/*.xml 15 | # druid 16 | spring.datasource.url=jdbc:mysql://localhost:3306/second?useUnicode=true&characterEncoding=utf-8&allowMultiQueries=true&useSSL=false 17 | spring.datasource.username=root 18 | spring.datasource.password=admin 19 | spring.datasource.driver-class-name=com.mysql.jdbc.Driver 20 | spring.datasource.type=com.alibaba.druid.pool.DruidDataSource 21 | spring.datasource.filters=stat 22 | spring.datasource.maxActive=40 23 | spring.datasource.initialSize=20 24 | spring.datasource.maxWait=6000 25 | spring.datasource.minIdle=500 26 | spring.datasource.timeBetweenEvictionRunsMillis=60000 27 | spring.datasource.minEvictableIdleTimeMillis=300000 28 | spring.datasource.validationQuery=select 'x' 29 | spring.datasource.testWhileIdle=true 30 | spring.datasource.testOnBorrow=false 31 | spring.datasource.testOnReturn=false 32 | spring.datasource.poolPreparedStatements=true 33 | spring.datasource.maxOpenPreparedStatements=20 34 | #redis 35 | redis.host=127.0.0.1 36 | redis.port=6379 37 | redis.timeout=10 38 | redis.poolMaxTotal=40 39 | redis.poolMaxIdle=20 40 | redis.poolMaxWait=20 41 | #static 42 | spring.resources.add-mappings=true 43 | spring.resources.cache-period= 3600 44 | spring.resources.chain.cache=true 45 | spring.resources.chain.enabled=true 46 | spring.resources.chain.gzipped=true 47 | spring.resources.chain.html-application-cache=true 48 | spring.resources.static-locations=classpath:/static/ 49 | #rabbitmq 50 | spring.rabbitmq.host=127.0.0.1 51 | spring.rabbitmq.port=5672 52 | spring.rabbitmq.username=guest 53 | spring.rabbitmq.password=guest 54 | spring.rabbitmq.virtual-host=/ 55 | #consumer number 56 | spring.rabbitmq.listener.simple.concurrency= 10 57 | spring.rabbitmq.listener.simple.max-concurrency= 10 58 | #take number 59 | spring.rabbitmq.listener.simple.prefetch= 1 60 | #consumer 61 | spring.rabbitmq.listener.simple.auto-startup=true 62 | #consume fail 63 | spring.rabbitmq.listener.simple.default-requeue-rejected= true 64 | #retry 65 | spring.rabbitmq.template.retry.enabled=true 66 | spring.rabbitmq.template.retry.initial-interval=1000 67 | spring.rabbitmq.template.retry.max-attempts=3 68 | spring.rabbitmq.template.retry.max-interval=10000 69 | spring.rabbitmq.template.retry.multiplier=1.0 70 | -------------------------------------------------------------------------------- /src/main/resources/static/bootstrap/fonts/glyphicons-halflings-regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niantianlei/second/62537ce95b44a1288cd46d88f57eaede6d162461/src/main/resources/static/bootstrap/fonts/glyphicons-halflings-regular.eot -------------------------------------------------------------------------------- /src/main/resources/static/bootstrap/fonts/glyphicons-halflings-regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niantianlei/second/62537ce95b44a1288cd46d88f57eaede6d162461/src/main/resources/static/bootstrap/fonts/glyphicons-halflings-regular.ttf -------------------------------------------------------------------------------- /src/main/resources/static/bootstrap/fonts/glyphicons-halflings-regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niantianlei/second/62537ce95b44a1288cd46d88f57eaede6d162461/src/main/resources/static/bootstrap/fonts/glyphicons-halflings-regular.woff -------------------------------------------------------------------------------- /src/main/resources/static/bootstrap/fonts/glyphicons-halflings-regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niantianlei/second/62537ce95b44a1288cd46d88f57eaede6d162461/src/main/resources/static/bootstrap/fonts/glyphicons-halflings-regular.woff2 -------------------------------------------------------------------------------- /src/main/resources/static/bootstrap/js/npm.js: -------------------------------------------------------------------------------- 1 | // This file is autogenerated via the `commonjs` Grunt task. You can require() this file in a CommonJS environment. 2 | require('../../js/transition.js') 3 | require('../../js/alert.js') 4 | require('../../js/button.js') 5 | require('../../js/carousel.js') 6 | require('../../js/collapse.js') 7 | require('../../js/dropdown.js') 8 | require('../../js/modal.js') 9 | require('../../js/tooltip.js') 10 | require('../../js/popover.js') 11 | require('../../js/scrollspy.js') 12 | require('../../js/tab.js') 13 | require('../../js/affix.js') -------------------------------------------------------------------------------- /src/main/resources/static/img/iphone8p.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niantianlei/second/62537ce95b44a1288cd46d88f57eaede6d162461/src/main/resources/static/img/iphone8p.png -------------------------------------------------------------------------------- /src/main/resources/static/img/iphonex.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niantianlei/second/62537ce95b44a1288cd46d88f57eaede6d162461/src/main/resources/static/img/iphonex.png -------------------------------------------------------------------------------- /src/main/resources/static/img/meta10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niantianlei/second/62537ce95b44a1288cd46d88f57eaede6d162461/src/main/resources/static/img/meta10.png -------------------------------------------------------------------------------- /src/main/resources/static/jquery-validation/localization/messages_zh.min.js: -------------------------------------------------------------------------------- 1 | /*! jQuery Validation Plugin - v1.14.0 - 6/30/2015 2 | * http://jqueryvalidation.org/ 3 | * Copyright (c) 2015 Jörn Zaefferer; Licensed MIT */ 4 | !function(a){"function"==typeof define&&define.amd?define(["jquery","../jquery.validate.min"],a):a(jQuery)}(function(a){a.extend(a.validator.messages,{required:"这是必填字段",remote:"请修正此字段",email:"请输入有效的电子邮件地址",url:"请输入有效的网址",date:"请输入有效的日期",dateISO:"请输入有效的日期 (YYYY-MM-DD)",number:"请输入有效的数字",digits:"只能输入数字",creditcard:"请输入有效的信用卡号码",equalTo:"你的输入不相同",extension:"请输入有效的后缀",maxlength:a.validator.format("最多可以输入 {0} 个字符"),minlength:a.validator.format("最少要输入 {0} 个字符"),rangelength:a.validator.format("请输入长度在 {0} 到 {1} 之间的字符串"),range:a.validator.format("请输入范围在 {0} 到 {1} 之间的数值"),max:a.validator.format("请输入不大于 {0} 的数值"),min:a.validator.format("请输入不小于 {0} 的数值")})}); -------------------------------------------------------------------------------- /src/main/resources/static/js/common.js: -------------------------------------------------------------------------------- 1 | //展示loading 2 | function g_showLoading(){ 3 | var idx = layer.msg('处理中...', {icon: 16,shade: [0.5, '#f5f5f5'],scrollbar: false,offset: '0px', time:100000}) ; 4 | return idx; 5 | } 6 | //salt 7 | var g_passsword_salt="f9064abc" 8 | 9 | // 获取url参数 10 | function g_getQueryString(name) { 11 | var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)"); 12 | var r = window.location.search.substr(1).match(reg); 13 | if(r != null) return unescape(r[2]); 14 | return null; 15 | }; 16 | //设定时间格式化函数,使用new Date().format("yyyyMMddhhmmss"); 17 | Date.prototype.format = function (format) { 18 | var args = { 19 | "M+": this.getMonth() + 1, 20 | "d+": this.getDate(), 21 | "h+": this.getHours(), 22 | "m+": this.getMinutes(), 23 | "s+": this.getSeconds(), 24 | }; 25 | if (/(y+)/.test(format)) 26 | format = format.replace(RegExp.$1, (this.getFullYear() + "").substr(4 - RegExp.$1.length)); 27 | for (var i in args) { 28 | var n = args[i]; 29 | if (new RegExp("(" + i + ")").test(format)) 30 | format = format.replace(RegExp.$1, RegExp.$1.length == 1 ? n : ("00" + n).substr(("" + n).length)); 31 | } 32 | return format; 33 | }; 34 | -------------------------------------------------------------------------------- /src/main/resources/static/layer/mobile/layer.js: -------------------------------------------------------------------------------- 1 | /*! layer mobile-v2.0.0 Web弹层组件 MIT License http://layer.layui.com/mobile By 贤心 */ 2 | ;!function(e){"use strict";var t=document,n="querySelectorAll",i="getElementsByClassName",a=function(e){return t[n](e)},s={type:0,shade:!0,shadeClose:!0,fixed:!0,anim:"scale"},l={extend:function(e){var t=JSON.parse(JSON.stringify(s));for(var n in e)t[n]=e[n];return t},timer:{},end:{}};l.touch=function(e,t){e.addEventListener("click",function(e){t.call(this,e)},!1)};var r=0,o=["layui-m-layer"],c=function(e){var t=this;t.config=l.extend(e),t.view()};c.prototype.view=function(){var e=this,n=e.config,s=t.createElement("div");e.id=s.id=o[0]+r,s.setAttribute("class",o[0]+" "+o[0]+(n.type||0)),s.setAttribute("index",r);var l=function(){var e="object"==typeof n.title;return n.title?'

'+(e?n.title[0]:n.title)+"

":""}(),c=function(){"string"==typeof n.btn&&(n.btn=[n.btn]);var e,t=(n.btn||[]).length;return 0!==t&&n.btn?(e=''+n.btn[0]+"",2===t&&(e=''+n.btn[1]+""+e),'
'+e+"
"):""}();if(n.fixed||(n.top=n.hasOwnProperty("top")?n.top:100,n.style=n.style||"",n.style+=" top:"+(t.body.scrollTop+n.top)+"px"),2===n.type&&(n.content='

'+(n.content||"")+"

"),n.skin&&(n.anim="up"),"msg"===n.skin&&(n.shade=!1),s.innerHTML=(n.shade?"
':"")+'
"+l+'
'+n.content+"
"+c+"
",!n.type||2===n.type){var d=t[i](o[0]+n.type),y=d.length;y>=1&&layer.close(d[0].getAttribute("index"))}document.body.appendChild(s);var u=e.elem=a("#"+e.id)[0];n.success&&n.success(u),e.index=r++,e.action(n,u)},c.prototype.action=function(e,t){var n=this;e.time&&(l.timer[n.index]=setTimeout(function(){layer.close(n.index)},1e3*e.time));var a=function(){var t=this.getAttribute("type");0==t?(e.no&&e.no(),layer.close(n.index)):e.yes?e.yes(n.index):layer.close(n.index)};if(e.btn)for(var s=t[i]("layui-m-layerbtn")[0].children,r=s.length,o=0;odiv{line-height:22px;padding-top:7px;margin-bottom:20px;font-size:14px}.layui-m-layerbtn{display:box;display:-moz-box;display:-webkit-box;width:100%;height:50px;line-height:50px;font-size:0;border-top:1px solid #D0D0D0;background-color:#F2F2F2}.layui-m-layerbtn span{display:block;-moz-box-flex:1;box-flex:1;-webkit-box-flex:1;font-size:14px;cursor:pointer}.layui-m-layerbtn span[yes]{color:#40AFFE}.layui-m-layerbtn span[no]{border-right:1px solid #D0D0D0;border-radius:0 0 0 5px}.layui-m-layerbtn span:active{background-color:#F6F6F6}.layui-m-layerend{position:absolute;right:7px;top:10px;width:30px;height:30px;border:0;font-weight:400;background:0 0;cursor:pointer;-webkit-appearance:none;font-size:30px}.layui-m-layerend::after,.layui-m-layerend::before{position:absolute;left:5px;top:15px;content:'';width:18px;height:1px;background-color:#999;transform:rotate(45deg);-webkit-transform:rotate(45deg);border-radius:3px}.layui-m-layerend::after{transform:rotate(-45deg);-webkit-transform:rotate(-45deg)}body .layui-m-layer .layui-m-layer-footer{position:fixed;width:95%;max-width:100%;margin:0 auto;left:0;right:0;bottom:10px;background:0 0}.layui-m-layer-footer .layui-m-layercont{padding:20px;border-radius:5px 5px 0 0;background-color:rgba(255,255,255,.8)}.layui-m-layer-footer .layui-m-layerbtn{display:block;height:auto;background:0 0;border-top:none}.layui-m-layer-footer .layui-m-layerbtn span{background-color:rgba(255,255,255,.8)}.layui-m-layer-footer .layui-m-layerbtn span[no]{color:#FD482C;border-top:1px solid #c2c2c2;border-radius:0 0 5px 5px}.layui-m-layer-footer .layui-m-layerbtn span[yes]{margin-top:10px;border-radius:5px}body .layui-m-layer .layui-m-layer-msg{width:auto;max-width:90%;margin:0 auto;bottom:-150px;background-color:rgba(0,0,0,.7);color:#fff}.layui-m-layer-msg .layui-m-layercont{padding:10px 20px} -------------------------------------------------------------------------------- /src/main/resources/static/layer/skin/default/icon-ext.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niantianlei/second/62537ce95b44a1288cd46d88f57eaede6d162461/src/main/resources/static/layer/skin/default/icon-ext.png -------------------------------------------------------------------------------- /src/main/resources/static/layer/skin/default/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niantianlei/second/62537ce95b44a1288cd46d88f57eaede6d162461/src/main/resources/static/layer/skin/default/icon.png -------------------------------------------------------------------------------- /src/main/resources/static/layer/skin/default/loading-0.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niantianlei/second/62537ce95b44a1288cd46d88f57eaede6d162461/src/main/resources/static/layer/skin/default/loading-0.gif -------------------------------------------------------------------------------- /src/main/resources/static/layer/skin/default/loading-1.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niantianlei/second/62537ce95b44a1288cd46d88f57eaede6d162461/src/main/resources/static/layer/skin/default/loading-1.gif -------------------------------------------------------------------------------- /src/main/resources/static/layer/skin/default/loading-2.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niantianlei/second/62537ce95b44a1288cd46d88f57eaede6d162461/src/main/resources/static/layer/skin/default/loading-2.gif -------------------------------------------------------------------------------- /src/main/resources/static/order_detail.htm: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 订单详情 5 | 6 | 7 | 8 | 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 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 45 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 |
商品名称
商品图片
订单价格
下单时间
订单状态 44 | 46 | 47 |
收货人XXX 18812341234
收货地址北京市海淀区软件园
58 |
59 | 60 | 61 | 105 | 106 | -------------------------------------------------------------------------------- /src/main/resources/static/sql.markdown: -------------------------------------------------------------------------------- 1 | #商品表 2 | CREATE TABLE `goods`( 3 | `id` BIGINT(20) not null auto_increment COMMENT '商品id', 4 | `goods_name` varchar(16) DEFAULT null COMMENT '商品名称', 5 | `goods_title` varchar(64) DEFAULT null COMMENT '商品标题', 6 | `goods_img` varchar(64) DEFAULT NULL COMMENT '商品图片', 7 | `goods_detail` longtext COMMENT '商品的详情介绍', 8 | `goods_price` DECIMAL(10,2) DEFAULT '0.00' comment '商品单价', 9 | `goods_stock` int(11) DEFAULT '0' COMMENT '商品库存,-1表示无限', 10 | PRIMARY KEY(`id`) 11 | )ENGINE=INNODB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4; 12 | 13 | # 秒杀商品表 14 | CREATE TABLE `second_goods` ( 15 | `id` bigint(20) not null auto_increment comment '秒杀的商品', 16 | `goods_id` bigint(20) default null comment '商品id', 17 | `second_price` decimal(10,2) default '0.00' comment '秒杀价', 18 | `stock_count` int(11) default null comment '库存数量', 19 | `start_date` datetime default null comment '秒杀开始时间', 20 | `end_date` datetime default null comment '秒杀结束时间', 21 | primary key(id) 22 | )ENGINE=InnoDB AUTO_INCREMENT=3 default charset=utf8mb4; 23 | 24 | insert into `second_goods` values(1,1,0.01,4,'2018-05-23 10:00:00','2018-06-10 20:00:00'),(2,2,0.01,10,'2018-05-25 10:00:00','2018-06-10 20:00:00'); 25 | insert into `second_goods` values(3,3,0.01,20,'2018-06-23 10:00:00','2018-06-25 20:00:00') 26 | # 订单表 27 | create table `order_info`( 28 | `id` bigint(20) not null auto_increment, 29 | `user_id` bigint(20) default null comment '用户id', 30 | `goods_id` bigint(20) default null comment '商品id', 31 | `delivery_addr_id` bigint(20) default null comment '收货地址id', 32 | `goods_name` varchar(16) default null comment '冗余商品名称', 33 | `goods_count` int(11) default '0' comment '商品数量', 34 | `goods_price` decimal(10,2) default '0.00' comment '商品单价', 35 | `order_channel` tinyint(4) default '0' comment '1pc, 2android, 3ioS', 36 | `status` tinyint(4) default '0' comment '订单状态,0新建未支付,1已支付,2已发货,3已收货,4已退款,5已完成', 37 | `create_date` datetime default null comment '订单创建时间', 38 | `pay_date` datetime default null comment '支付时间', 39 | primary key(`id`) 40 | )ENGINE=InnoDB auto_increment=12 default charset=utf8mb4; 41 | 42 | # 秒杀表 43 | create table `second_order`( 44 | `id` bigint(20) not null auto_increment, 45 | `user_id` bigint(20) default null comment '用户id', 46 | `order_id` bigint(20) default null comment '订单id', 47 | `goods_id` bigint(20) default null comment '商品id', 48 | primary key(`id`) 49 | )ENGINE=InnoDB auto_increment=3 default charset=utf8mb4; 50 | 51 | -------------------------------------------------------------------------------- /src/main/resources/templates/goods_detail.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 商品详情 5 | 6 | 7 | 8 | 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 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 47 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 |
商品名称
商品图片
秒杀开始时间 42 | 43 | 秒杀倒计时: 44 | 秒杀进行中 45 | 秒杀已结束 46 | 48 |
49 | 50 | 51 |
52 |
商品原价
秒杀价
库存数量
67 |
68 | 69 | 97 | 98 | -------------------------------------------------------------------------------- /src/main/resources/templates/goods_list.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 商品列表 5 | 6 | 7 | 8 | 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 | 34 |
商品名称商品图片商品原价秒杀价库存数量详情
详情
35 |
36 | 37 | 38 | -------------------------------------------------------------------------------- /src/main/resources/templates/hello.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | hello 5 | 6 | 7 | 8 |

9 | 10 | -------------------------------------------------------------------------------- /src/main/resources/templates/login.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 登录 5 | 6 | 7 | 8 | 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 | 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 | 98 | -------------------------------------------------------------------------------- /src/main/resources/templates/order_detail.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 订单详情 5 | 6 | 7 | 8 | 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 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 53 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 |
商品名称
商品图片
订单价格
下单时间
订单状态 44 | 未支付 45 | 已支付 46 | 未发货 47 | 已发货 48 | 已收货 49 | 已签收 50 | 已退款 51 | 已完成 52 | 54 | 55 |
收货人 XXX
电话XXX
收货地址北京市海淀区软件园xxx
70 |
71 | 72 | 73 | 74 | -------------------------------------------------------------------------------- /src/main/resources/templates/secondKill_fail.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 秒杀失败 5 | 6 | 7 | 8 | 秒杀失败:

9 | 10 | 11 | -------------------------------------------------------------------------------- /src/main/test/second/TestService.java: -------------------------------------------------------------------------------- 1 | package second; 2 | 3 | import org.apache.commons.lang3.StringUtils; 4 | import org.junit.Test; 5 | import org.junit.runner.RunWith; 6 | import org.springframework.beans.factory.annotation.Autowired; 7 | import org.springframework.boot.autoconfigure.EnableAutoConfiguration; 8 | import org.springframework.boot.test.context.SpringBootTest; 9 | import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; 10 | 11 | import nian.shop.App; 12 | import nian.shop.VO.GoodsVo; 13 | import nian.shop.entity.SecondUser; 14 | import nian.shop.service.GoodsService; 15 | import nian.shop.service.OrderService; 16 | 17 | /** 18 | * @author created by NianTianlei 19 | * @createDate on 2018年5月29日 上午9:36:47 20 | */ 21 | @RunWith(SpringJUnit4ClassRunner.class) 22 | @SpringBootTest(classes = App.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) 23 | @EnableAutoConfiguration 24 | public class TestService { 25 | @Autowired 26 | GoodsService goodsService; 27 | @Autowired 28 | OrderService orderService; 29 | 30 | 31 | @Test 32 | public void test() { 33 | /*//秒杀逻辑 34 | SecondUser user = new SecondUser(); 35 | user.setId(13812345678l); 36 | user.setPassword("30c07928a3d6539c2367dd664179644b"); 37 | GoodsVo goods = new GoodsVo(); 38 | goods.setId(1L); 39 | goods.setSecondPrice(0.1); 40 | goodsService.reduceStock(goods);*/ 41 | 42 | //common-lang3版本冲突? 43 | String s = ""; 44 | System.out.println(StringUtils.isEmpty(s)); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /target/classes/META-INF/MANIFEST.MF: -------------------------------------------------------------------------------- 1 | Manifest-Version: 1.0 2 | Implementation-Title: second 3 | Implementation-Version: 0.0.1-SNAPSHOT 4 | Built-By: Niantianlei 5 | Implementation-Vendor-Id: nian.login 6 | Build-Jdk: 1.8.0_101 7 | Implementation-URL: http://maven.apache.org 8 | Created-By: Maven Integration for Eclipse 9 | Implementation-Vendor: Pivotal Software, Inc. 10 | 11 | -------------------------------------------------------------------------------- /target/classes/META-INF/maven/nian.login/second/pom.properties: -------------------------------------------------------------------------------- 1 | #Generated by Maven Integration for Eclipse 2 | #Sun Jul 22 00:15:09 CST 2018 3 | version=0.0.1-SNAPSHOT 4 | groupId=nian.login 5 | m2e.projectName=second 6 | m2e.projectLocation=E\:\\java\\workspace2\\second 7 | artifactId=second 8 | -------------------------------------------------------------------------------- /target/classes/META-INF/maven/nian.login/second/pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4.0.0 4 | 5 | nian.login 6 | second 7 | 0.0.1-SNAPSHOT 8 | jar 9 | 10 | second 11 | http://maven.apache.org 12 | 13 | 14 | UTF-8 15 | 16 | 17 | org.springframework.boot 18 | spring-boot-starter-parent 19 | 1.5.8.RELEASE 20 | 21 | 22 | 23 | 24 | 25 | org.springframework.boot 26 | spring-boot-starter-aop 27 | 28 | 29 | org.springframework.boot 30 | spring-boot-starter-web 31 | 32 | 33 | org.springframework.boot 34 | spring-boot-starter-test 35 | test 36 | 37 | 38 | org.springframework.boot 39 | spring-boot-starter-thymeleaf 40 | 41 | 42 | org.mybatis.spring.boot 43 | mybatis-spring-boot-starter 44 | 1.3.2 45 | 46 | 47 | mysql 48 | mysql-connector-java 49 | 50 | 51 | 52 | com.alibaba 53 | druid 54 | 1.0.5 55 | 56 | 57 | 58 | com.google.guava 59 | guava 60 | 19.0 61 | 62 | 63 | org.projectlombok 64 | lombok 65 | provided 66 | 67 | 68 | redis.clients 69 | jedis 70 | 71 | 72 | com.alibaba 73 | fastjson 74 | 1.2.38 75 | 76 | 77 | 78 | commons-codec 79 | commons-codec 80 | 81 | 82 | org.apache.commons 83 | commons-lang3 84 | 3.7 85 | 86 | 87 | org.springframework.boot 88 | spring-boot-starter-validation 89 | 90 | 91 | 92 | org.springframework.boot 93 | spring-boot-starter-amqp 94 | 95 | 96 | 97 | 98 | com.alibaba.rocketmq 99 | rocketmq-client 100 | 3.6.2.Final 101 | 102 | 103 | 104 | com.alibaba.rocketmq 105 | rocketmq-all 106 | 3.2.6 107 | pom 108 | 109 | 110 | 111 | 112 | 113 | ${project.artifactId} 114 | 115 | 116 | org.springframework.boot 117 | spring-boot-maven-plugin 118 | 119 | 120 | 121 | 122 | -------------------------------------------------------------------------------- /target/classes/application.properties: -------------------------------------------------------------------------------- 1 | # thymeleaf 2 | spring.thymeleaf.cache=false 3 | spring.thymeleaf.enabled=true 4 | spring.thymeleaf.content-type=text/html 5 | spring.thymeleaf.prefix=classpath:/templates/ 6 | spring.thymeleaf.suffix=.html 7 | spring.thymeleaf.encoding=UTF-8 8 | spring.thymeleaf.mode=HTML5 9 | # mybatis 10 | mybatis.type-aliases-package=nian.shop.entity 11 | mybatis.configuration.map-underscore-to-camel-case=true 12 | mybatis.configuration.default-fetch-size=100 13 | mybatis.configuration.default-statement-timeout=3000 14 | mybatis.mapperLocations = classpath:nian/shop/dao/*.xml 15 | # druid 16 | spring.datasource.url=jdbc:mysql://localhost:3306/second?useUnicode=true&characterEncoding=utf-8&allowMultiQueries=true&useSSL=false 17 | spring.datasource.username=root 18 | spring.datasource.password=admin 19 | spring.datasource.driver-class-name=com.mysql.jdbc.Driver 20 | spring.datasource.type=com.alibaba.druid.pool.DruidDataSource 21 | spring.datasource.filters=stat 22 | spring.datasource.maxActive=40 23 | spring.datasource.initialSize=20 24 | spring.datasource.maxWait=6000 25 | spring.datasource.minIdle=500 26 | spring.datasource.timeBetweenEvictionRunsMillis=60000 27 | spring.datasource.minEvictableIdleTimeMillis=300000 28 | spring.datasource.validationQuery=select 'x' 29 | spring.datasource.testWhileIdle=true 30 | spring.datasource.testOnBorrow=false 31 | spring.datasource.testOnReturn=false 32 | spring.datasource.poolPreparedStatements=true 33 | spring.datasource.maxOpenPreparedStatements=20 34 | #redis 35 | redis.host=127.0.0.1 36 | redis.port=6379 37 | redis.timeout=10 38 | redis.poolMaxTotal=40 39 | redis.poolMaxIdle=20 40 | redis.poolMaxWait=20 41 | #static 42 | spring.resources.add-mappings=true 43 | spring.resources.cache-period= 3600 44 | spring.resources.chain.cache=true 45 | spring.resources.chain.enabled=true 46 | spring.resources.chain.gzipped=true 47 | spring.resources.chain.html-application-cache=true 48 | spring.resources.static-locations=classpath:/static/ 49 | #rabbitmq 50 | spring.rabbitmq.host=127.0.0.1 51 | spring.rabbitmq.port=5672 52 | spring.rabbitmq.username=guest 53 | spring.rabbitmq.password=guest 54 | spring.rabbitmq.virtual-host=/ 55 | #consumer number 56 | spring.rabbitmq.listener.simple.concurrency= 10 57 | spring.rabbitmq.listener.simple.max-concurrency= 10 58 | #take number 59 | spring.rabbitmq.listener.simple.prefetch= 1 60 | #consumer 61 | spring.rabbitmq.listener.simple.auto-startup=true 62 | #consume fail 63 | spring.rabbitmq.listener.simple.default-requeue-rejected= true 64 | #retry 65 | spring.rabbitmq.template.retry.enabled=true 66 | spring.rabbitmq.template.retry.initial-interval=1000 67 | spring.rabbitmq.template.retry.max-attempts=3 68 | spring.rabbitmq.template.retry.max-interval=10000 69 | spring.rabbitmq.template.retry.multiplier=1.0 70 | -------------------------------------------------------------------------------- /target/classes/com/nian/LogTools/ExtElement.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niantianlei/second/62537ce95b44a1288cd46d88f57eaede6d162461/target/classes/com/nian/LogTools/ExtElement.class -------------------------------------------------------------------------------- /target/classes/com/nian/LogTools/LogKV.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niantianlei/second/62537ce95b44a1288cd46d88f57eaede6d162461/target/classes/com/nian/LogTools/LogKV.class -------------------------------------------------------------------------------- /target/classes/com/nian/LogTools/LogMessage$1.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niantianlei/second/62537ce95b44a1288cd46d88f57eaede6d162461/target/classes/com/nian/LogTools/LogMessage$1.class -------------------------------------------------------------------------------- /target/classes/com/nian/LogTools/LogMessage.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niantianlei/second/62537ce95b44a1288cd46d88f57eaede6d162461/target/classes/com/nian/LogTools/LogMessage.class -------------------------------------------------------------------------------- /target/classes/com/nian/LogTools/SpanIdGenerator.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niantianlei/second/62537ce95b44a1288cd46d88f57eaede6d162461/target/classes/com/nian/LogTools/SpanIdGenerator.class -------------------------------------------------------------------------------- /target/classes/com/nian/rabbitmq/MQConfig.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niantianlei/second/62537ce95b44a1288cd46d88f57eaede6d162461/target/classes/com/nian/rabbitmq/MQConfig.class -------------------------------------------------------------------------------- /target/classes/com/nian/rabbitmq/SecondKillMessage.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niantianlei/second/62537ce95b44a1288cd46d88f57eaede6d162461/target/classes/com/nian/rabbitmq/SecondKillMessage.class -------------------------------------------------------------------------------- /target/classes/nian/shop/App.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niantianlei/second/62537ce95b44a1288cd46d88f57eaede6d162461/target/classes/nian/shop/App.class -------------------------------------------------------------------------------- /target/classes/nian/shop/DTO/ResultDTO.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niantianlei/second/62537ce95b44a1288cd46d88f57eaede6d162461/target/classes/nian/shop/DTO/ResultDTO.class -------------------------------------------------------------------------------- /target/classes/nian/shop/VO/GoodsDetailVo.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niantianlei/second/62537ce95b44a1288cd46d88f57eaede6d162461/target/classes/nian/shop/VO/GoodsDetailVo.class -------------------------------------------------------------------------------- /target/classes/nian/shop/VO/GoodsVo.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niantianlei/second/62537ce95b44a1288cd46d88f57eaede6d162461/target/classes/nian/shop/VO/GoodsVo.class -------------------------------------------------------------------------------- /target/classes/nian/shop/VO/LoginVO.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niantianlei/second/62537ce95b44a1288cd46d88f57eaede6d162461/target/classes/nian/shop/VO/LoginVO.class -------------------------------------------------------------------------------- /target/classes/nian/shop/VO/OrderDetailVo.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niantianlei/second/62537ce95b44a1288cd46d88f57eaede6d162461/target/classes/nian/shop/VO/OrderDetailVo.class -------------------------------------------------------------------------------- /target/classes/nian/shop/access/AccessInterceptor.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niantianlei/second/62537ce95b44a1288cd46d88f57eaede6d162461/target/classes/nian/shop/access/AccessInterceptor.class -------------------------------------------------------------------------------- /target/classes/nian/shop/access/AccessLimit.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niantianlei/second/62537ce95b44a1288cd46d88f57eaede6d162461/target/classes/nian/shop/access/AccessLimit.class -------------------------------------------------------------------------------- /target/classes/nian/shop/access/UserContext.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niantianlei/second/62537ce95b44a1288cd46d88f57eaede6d162461/target/classes/nian/shop/access/UserContext.class -------------------------------------------------------------------------------- /target/classes/nian/shop/aspect/LogAspect.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niantianlei/second/62537ce95b44a1288cd46d88f57eaede6d162461/target/classes/nian/shop/aspect/LogAspect.class -------------------------------------------------------------------------------- /target/classes/nian/shop/bloomFilter/BloomFilter$MisjudgmentRate.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niantianlei/second/62537ce95b44a1288cd46d88f57eaede6d162461/target/classes/nian/shop/bloomFilter/BloomFilter$MisjudgmentRate.class -------------------------------------------------------------------------------- /target/classes/nian/shop/bloomFilter/BloomFilter.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niantianlei/second/62537ce95b44a1288cd46d88f57eaede6d162461/target/classes/nian/shop/bloomFilter/BloomFilter.class -------------------------------------------------------------------------------- /target/classes/nian/shop/bloomFilter/BloomFilterCache.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niantianlei/second/62537ce95b44a1288cd46d88f57eaede6d162461/target/classes/nian/shop/bloomFilter/BloomFilterCache.class -------------------------------------------------------------------------------- /target/classes/nian/shop/common/CommonValidator.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niantianlei/second/62537ce95b44a1288cd46d88f57eaede6d162461/target/classes/nian/shop/common/CommonValidator.class -------------------------------------------------------------------------------- /target/classes/nian/shop/config/UserArgumentResolver.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niantianlei/second/62537ce95b44a1288cd46d88f57eaede6d162461/target/classes/nian/shop/config/UserArgumentResolver.class -------------------------------------------------------------------------------- /target/classes/nian/shop/config/WebConfig.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niantianlei/second/62537ce95b44a1288cd46d88f57eaede6d162461/target/classes/nian/shop/config/WebConfig.class -------------------------------------------------------------------------------- /target/classes/nian/shop/controller/DemoController.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niantianlei/second/62537ce95b44a1288cd46d88f57eaede6d162461/target/classes/nian/shop/controller/DemoController.class -------------------------------------------------------------------------------- /target/classes/nian/shop/controller/GoodsController.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niantianlei/second/62537ce95b44a1288cd46d88f57eaede6d162461/target/classes/nian/shop/controller/GoodsController.class -------------------------------------------------------------------------------- /target/classes/nian/shop/controller/LoginController.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niantianlei/second/62537ce95b44a1288cd46d88f57eaede6d162461/target/classes/nian/shop/controller/LoginController.class -------------------------------------------------------------------------------- /target/classes/nian/shop/controller/OrderController.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niantianlei/second/62537ce95b44a1288cd46d88f57eaede6d162461/target/classes/nian/shop/controller/OrderController.class -------------------------------------------------------------------------------- /target/classes/nian/shop/controller/SecondController.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niantianlei/second/62537ce95b44a1288cd46d88f57eaede6d162461/target/classes/nian/shop/controller/SecondController.class -------------------------------------------------------------------------------- /target/classes/nian/shop/controller/UserController.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niantianlei/second/62537ce95b44a1288cd46d88f57eaede6d162461/target/classes/nian/shop/controller/UserController.class -------------------------------------------------------------------------------- /target/classes/nian/shop/dao/GoodsDao.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niantianlei/second/62537ce95b44a1288cd46d88f57eaede6d162461/target/classes/nian/shop/dao/GoodsDao.class -------------------------------------------------------------------------------- /target/classes/nian/shop/dao/OrderDao.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niantianlei/second/62537ce95b44a1288cd46d88f57eaede6d162461/target/classes/nian/shop/dao/OrderDao.class -------------------------------------------------------------------------------- /target/classes/nian/shop/dao/SecondUserDao.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niantianlei/second/62537ce95b44a1288cd46d88f57eaede6d162461/target/classes/nian/shop/dao/SecondUserDao.class -------------------------------------------------------------------------------- /target/classes/nian/shop/dao/UserDao.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niantianlei/second/62537ce95b44a1288cd46d88f57eaede6d162461/target/classes/nian/shop/dao/UserDao.class -------------------------------------------------------------------------------- /target/classes/nian/shop/entity/Goods.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niantianlei/second/62537ce95b44a1288cd46d88f57eaede6d162461/target/classes/nian/shop/entity/Goods.class -------------------------------------------------------------------------------- /target/classes/nian/shop/entity/OrderInfo.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niantianlei/second/62537ce95b44a1288cd46d88f57eaede6d162461/target/classes/nian/shop/entity/OrderInfo.class -------------------------------------------------------------------------------- /target/classes/nian/shop/entity/SecondGoods.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niantianlei/second/62537ce95b44a1288cd46d88f57eaede6d162461/target/classes/nian/shop/entity/SecondGoods.class -------------------------------------------------------------------------------- /target/classes/nian/shop/entity/SecondOrder.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niantianlei/second/62537ce95b44a1288cd46d88f57eaede6d162461/target/classes/nian/shop/entity/SecondOrder.class -------------------------------------------------------------------------------- /target/classes/nian/shop/entity/SecondUser.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niantianlei/second/62537ce95b44a1288cd46d88f57eaede6d162461/target/classes/nian/shop/entity/SecondUser.class -------------------------------------------------------------------------------- /target/classes/nian/shop/entity/User.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niantianlei/second/62537ce95b44a1288cd46d88f57eaede6d162461/target/classes/nian/shop/entity/User.class -------------------------------------------------------------------------------- /target/classes/nian/shop/exception/GlobalExceptionHandler.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niantianlei/second/62537ce95b44a1288cd46d88f57eaede6d162461/target/classes/nian/shop/exception/GlobalExceptionHandler.class -------------------------------------------------------------------------------- /target/classes/nian/shop/exception/SecondException.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niantianlei/second/62537ce95b44a1288cd46d88f57eaede6d162461/target/classes/nian/shop/exception/SecondException.class -------------------------------------------------------------------------------- /target/classes/nian/shop/redis/AccessKey.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niantianlei/second/62537ce95b44a1288cd46d88f57eaede6d162461/target/classes/nian/shop/redis/AccessKey.class -------------------------------------------------------------------------------- /target/classes/nian/shop/redis/BasePrefix.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niantianlei/second/62537ce95b44a1288cd46d88f57eaede6d162461/target/classes/nian/shop/redis/BasePrefix.class -------------------------------------------------------------------------------- /target/classes/nian/shop/redis/GoodsKey.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niantianlei/second/62537ce95b44a1288cd46d88f57eaede6d162461/target/classes/nian/shop/redis/GoodsKey.class -------------------------------------------------------------------------------- /target/classes/nian/shop/redis/KeyPrefix.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niantianlei/second/62537ce95b44a1288cd46d88f57eaede6d162461/target/classes/nian/shop/redis/KeyPrefix.class -------------------------------------------------------------------------------- /target/classes/nian/shop/redis/OrderKey.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niantianlei/second/62537ce95b44a1288cd46d88f57eaede6d162461/target/classes/nian/shop/redis/OrderKey.class -------------------------------------------------------------------------------- /target/classes/nian/shop/redis/RedisConfig.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niantianlei/second/62537ce95b44a1288cd46d88f57eaede6d162461/target/classes/nian/shop/redis/RedisConfig.class -------------------------------------------------------------------------------- /target/classes/nian/shop/redis/RedisPoolFactory.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niantianlei/second/62537ce95b44a1288cd46d88f57eaede6d162461/target/classes/nian/shop/redis/RedisPoolFactory.class -------------------------------------------------------------------------------- /target/classes/nian/shop/redis/SecondKey.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niantianlei/second/62537ce95b44a1288cd46d88f57eaede6d162461/target/classes/nian/shop/redis/SecondKey.class -------------------------------------------------------------------------------- /target/classes/nian/shop/redis/SecondUserKey.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niantianlei/second/62537ce95b44a1288cd46d88f57eaede6d162461/target/classes/nian/shop/redis/SecondUserKey.class -------------------------------------------------------------------------------- /target/classes/nian/shop/redis/UserKey.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niantianlei/second/62537ce95b44a1288cd46d88f57eaede6d162461/target/classes/nian/shop/redis/UserKey.class -------------------------------------------------------------------------------- /target/classes/nian/shop/rocketmq/ConsumerDemo$1.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niantianlei/second/62537ce95b44a1288cd46d88f57eaede6d162461/target/classes/nian/shop/rocketmq/ConsumerDemo$1.class -------------------------------------------------------------------------------- /target/classes/nian/shop/rocketmq/ConsumerDemo.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niantianlei/second/62537ce95b44a1288cd46d88f57eaede6d162461/target/classes/nian/shop/rocketmq/ConsumerDemo.class -------------------------------------------------------------------------------- /target/classes/nian/shop/rocketmq/ProducerDemo$1.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niantianlei/second/62537ce95b44a1288cd46d88f57eaede6d162461/target/classes/nian/shop/rocketmq/ProducerDemo$1.class -------------------------------------------------------------------------------- /target/classes/nian/shop/rocketmq/ProducerDemo.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niantianlei/second/62537ce95b44a1288cd46d88f57eaede6d162461/target/classes/nian/shop/rocketmq/ProducerDemo.class -------------------------------------------------------------------------------- /target/classes/nian/shop/rocketmq/RocketMQConfig.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niantianlei/second/62537ce95b44a1288cd46d88f57eaede6d162461/target/classes/nian/shop/rocketmq/RocketMQConfig.class -------------------------------------------------------------------------------- /target/classes/nian/shop/rocketmq/RocketMQReceiver$1.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niantianlei/second/62537ce95b44a1288cd46d88f57eaede6d162461/target/classes/nian/shop/rocketmq/RocketMQReceiver$1.class -------------------------------------------------------------------------------- /target/classes/nian/shop/rocketmq/RocketMQReceiver.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niantianlei/second/62537ce95b44a1288cd46d88f57eaede6d162461/target/classes/nian/shop/rocketmq/RocketMQReceiver.class -------------------------------------------------------------------------------- /target/classes/nian/shop/rocketmq/RocketMQSender$1.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niantianlei/second/62537ce95b44a1288cd46d88f57eaede6d162461/target/classes/nian/shop/rocketmq/RocketMQSender$1.class -------------------------------------------------------------------------------- /target/classes/nian/shop/rocketmq/RocketMQSender.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niantianlei/second/62537ce95b44a1288cd46d88f57eaede6d162461/target/classes/nian/shop/rocketmq/RocketMQSender.class -------------------------------------------------------------------------------- /target/classes/nian/shop/service/GoodsService.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niantianlei/second/62537ce95b44a1288cd46d88f57eaede6d162461/target/classes/nian/shop/service/GoodsService.class -------------------------------------------------------------------------------- /target/classes/nian/shop/service/MqReceiver.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niantianlei/second/62537ce95b44a1288cd46d88f57eaede6d162461/target/classes/nian/shop/service/MqReceiver.class -------------------------------------------------------------------------------- /target/classes/nian/shop/service/MqSender.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niantianlei/second/62537ce95b44a1288cd46d88f57eaede6d162461/target/classes/nian/shop/service/MqSender.class -------------------------------------------------------------------------------- /target/classes/nian/shop/service/OrderService.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niantianlei/second/62537ce95b44a1288cd46d88f57eaede6d162461/target/classes/nian/shop/service/OrderService.class -------------------------------------------------------------------------------- /target/classes/nian/shop/service/RedisService.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niantianlei/second/62537ce95b44a1288cd46d88f57eaede6d162461/target/classes/nian/shop/service/RedisService.class -------------------------------------------------------------------------------- /target/classes/nian/shop/service/SecondKillService.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niantianlei/second/62537ce95b44a1288cd46d88f57eaede6d162461/target/classes/nian/shop/service/SecondKillService.class -------------------------------------------------------------------------------- /target/classes/nian/shop/service/SecondUserService.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niantianlei/second/62537ce95b44a1288cd46d88f57eaede6d162461/target/classes/nian/shop/service/SecondUserService.class -------------------------------------------------------------------------------- /target/classes/nian/shop/service/UserService.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niantianlei/second/62537ce95b44a1288cd46d88f57eaede6d162461/target/classes/nian/shop/service/UserService.class -------------------------------------------------------------------------------- /target/classes/nian/shop/task/BloomFilterTask.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niantianlei/second/62537ce95b44a1288cd46d88f57eaede6d162461/target/classes/nian/shop/task/BloomFilterTask.class -------------------------------------------------------------------------------- /target/classes/nian/shop/task/UserDataProduct.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niantianlei/second/62537ce95b44a1288cd46d88f57eaede6d162461/target/classes/nian/shop/task/UserDataProduct.class -------------------------------------------------------------------------------- /target/classes/nian/shop/utils/DBUtil.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niantianlei/second/62537ce95b44a1288cd46d88f57eaede6d162461/target/classes/nian/shop/utils/DBUtil.class -------------------------------------------------------------------------------- /target/classes/nian/shop/utils/MD5Util.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niantianlei/second/62537ce95b44a1288cd46d88f57eaede6d162461/target/classes/nian/shop/utils/MD5Util.class -------------------------------------------------------------------------------- /target/classes/nian/shop/utils/ResultCode.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niantianlei/second/62537ce95b44a1288cd46d88f57eaede6d162461/target/classes/nian/shop/utils/ResultCode.class -------------------------------------------------------------------------------- /target/classes/nian/shop/utils/SecondResEnum.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niantianlei/second/62537ce95b44a1288cd46d88f57eaede6d162461/target/classes/nian/shop/utils/SecondResEnum.class -------------------------------------------------------------------------------- /target/classes/nian/shop/utils/SecondStatusEnum.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niantianlei/second/62537ce95b44a1288cd46d88f57eaede6d162461/target/classes/nian/shop/utils/SecondStatusEnum.class -------------------------------------------------------------------------------- /target/classes/nian/shop/utils/UUIDUtil.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niantianlei/second/62537ce95b44a1288cd46d88f57eaede6d162461/target/classes/nian/shop/utils/UUIDUtil.class -------------------------------------------------------------------------------- /target/classes/nian/shop/utils/ValidatorUtil.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niantianlei/second/62537ce95b44a1288cd46d88f57eaede6d162461/target/classes/nian/shop/utils/ValidatorUtil.class -------------------------------------------------------------------------------- /target/classes/nian/shop/validator/IsMobile.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niantianlei/second/62537ce95b44a1288cd46d88f57eaede6d162461/target/classes/nian/shop/validator/IsMobile.class -------------------------------------------------------------------------------- /target/classes/nian/shop/validator/IsMobileValidator.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niantianlei/second/62537ce95b44a1288cd46d88f57eaede6d162461/target/classes/nian/shop/validator/IsMobileValidator.class -------------------------------------------------------------------------------- /target/classes/second/TestService.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niantianlei/second/62537ce95b44a1288cd46d88f57eaede6d162461/target/classes/second/TestService.class -------------------------------------------------------------------------------- /target/classes/static/bootstrap/fonts/glyphicons-halflings-regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niantianlei/second/62537ce95b44a1288cd46d88f57eaede6d162461/target/classes/static/bootstrap/fonts/glyphicons-halflings-regular.eot -------------------------------------------------------------------------------- /target/classes/static/bootstrap/fonts/glyphicons-halflings-regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niantianlei/second/62537ce95b44a1288cd46d88f57eaede6d162461/target/classes/static/bootstrap/fonts/glyphicons-halflings-regular.ttf -------------------------------------------------------------------------------- /target/classes/static/bootstrap/fonts/glyphicons-halflings-regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niantianlei/second/62537ce95b44a1288cd46d88f57eaede6d162461/target/classes/static/bootstrap/fonts/glyphicons-halflings-regular.woff -------------------------------------------------------------------------------- /target/classes/static/bootstrap/fonts/glyphicons-halflings-regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niantianlei/second/62537ce95b44a1288cd46d88f57eaede6d162461/target/classes/static/bootstrap/fonts/glyphicons-halflings-regular.woff2 -------------------------------------------------------------------------------- /target/classes/static/bootstrap/js/npm.js: -------------------------------------------------------------------------------- 1 | // This file is autogenerated via the `commonjs` Grunt task. You can require() this file in a CommonJS environment. 2 | require('../../js/transition.js') 3 | require('../../js/alert.js') 4 | require('../../js/button.js') 5 | require('../../js/carousel.js') 6 | require('../../js/collapse.js') 7 | require('../../js/dropdown.js') 8 | require('../../js/modal.js') 9 | require('../../js/tooltip.js') 10 | require('../../js/popover.js') 11 | require('../../js/scrollspy.js') 12 | require('../../js/tab.js') 13 | require('../../js/affix.js') -------------------------------------------------------------------------------- /target/classes/static/img/iphone8p.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niantianlei/second/62537ce95b44a1288cd46d88f57eaede6d162461/target/classes/static/img/iphone8p.png -------------------------------------------------------------------------------- /target/classes/static/img/iphonex.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niantianlei/second/62537ce95b44a1288cd46d88f57eaede6d162461/target/classes/static/img/iphonex.png -------------------------------------------------------------------------------- /target/classes/static/img/meta10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niantianlei/second/62537ce95b44a1288cd46d88f57eaede6d162461/target/classes/static/img/meta10.png -------------------------------------------------------------------------------- /target/classes/static/jquery-validation/localization/messages_zh.min.js: -------------------------------------------------------------------------------- 1 | /*! jQuery Validation Plugin - v1.14.0 - 6/30/2015 2 | * http://jqueryvalidation.org/ 3 | * Copyright (c) 2015 Jörn Zaefferer; Licensed MIT */ 4 | !function(a){"function"==typeof define&&define.amd?define(["jquery","../jquery.validate.min"],a):a(jQuery)}(function(a){a.extend(a.validator.messages,{required:"这是必填字段",remote:"请修正此字段",email:"请输入有效的电子邮件地址",url:"请输入有效的网址",date:"请输入有效的日期",dateISO:"请输入有效的日期 (YYYY-MM-DD)",number:"请输入有效的数字",digits:"只能输入数字",creditcard:"请输入有效的信用卡号码",equalTo:"你的输入不相同",extension:"请输入有效的后缀",maxlength:a.validator.format("最多可以输入 {0} 个字符"),minlength:a.validator.format("最少要输入 {0} 个字符"),rangelength:a.validator.format("请输入长度在 {0} 到 {1} 之间的字符串"),range:a.validator.format("请输入范围在 {0} 到 {1} 之间的数值"),max:a.validator.format("请输入不大于 {0} 的数值"),min:a.validator.format("请输入不小于 {0} 的数值")})}); -------------------------------------------------------------------------------- /target/classes/static/js/common.js: -------------------------------------------------------------------------------- 1 | //展示loading 2 | function g_showLoading(){ 3 | var idx = layer.msg('处理中...', {icon: 16,shade: [0.5, '#f5f5f5'],scrollbar: false,offset: '0px', time:100000}) ; 4 | return idx; 5 | } 6 | //salt 7 | var g_passsword_salt="f9064abc" 8 | 9 | // 获取url参数 10 | function g_getQueryString(name) { 11 | var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)"); 12 | var r = window.location.search.substr(1).match(reg); 13 | if(r != null) return unescape(r[2]); 14 | return null; 15 | }; 16 | //设定时间格式化函数,使用new Date().format("yyyyMMddhhmmss"); 17 | Date.prototype.format = function (format) { 18 | var args = { 19 | "M+": this.getMonth() + 1, 20 | "d+": this.getDate(), 21 | "h+": this.getHours(), 22 | "m+": this.getMinutes(), 23 | "s+": this.getSeconds(), 24 | }; 25 | if (/(y+)/.test(format)) 26 | format = format.replace(RegExp.$1, (this.getFullYear() + "").substr(4 - RegExp.$1.length)); 27 | for (var i in args) { 28 | var n = args[i]; 29 | if (new RegExp("(" + i + ")").test(format)) 30 | format = format.replace(RegExp.$1, RegExp.$1.length == 1 ? n : ("00" + n).substr(("" + n).length)); 31 | } 32 | return format; 33 | }; 34 | -------------------------------------------------------------------------------- /target/classes/static/layer/mobile/layer.js: -------------------------------------------------------------------------------- 1 | /*! layer mobile-v2.0.0 Web弹层组件 MIT License http://layer.layui.com/mobile By 贤心 */ 2 | ;!function(e){"use strict";var t=document,n="querySelectorAll",i="getElementsByClassName",a=function(e){return t[n](e)},s={type:0,shade:!0,shadeClose:!0,fixed:!0,anim:"scale"},l={extend:function(e){var t=JSON.parse(JSON.stringify(s));for(var n in e)t[n]=e[n];return t},timer:{},end:{}};l.touch=function(e,t){e.addEventListener("click",function(e){t.call(this,e)},!1)};var r=0,o=["layui-m-layer"],c=function(e){var t=this;t.config=l.extend(e),t.view()};c.prototype.view=function(){var e=this,n=e.config,s=t.createElement("div");e.id=s.id=o[0]+r,s.setAttribute("class",o[0]+" "+o[0]+(n.type||0)),s.setAttribute("index",r);var l=function(){var e="object"==typeof n.title;return n.title?'

'+(e?n.title[0]:n.title)+"

":""}(),c=function(){"string"==typeof n.btn&&(n.btn=[n.btn]);var e,t=(n.btn||[]).length;return 0!==t&&n.btn?(e=''+n.btn[0]+"",2===t&&(e=''+n.btn[1]+""+e),'
'+e+"
"):""}();if(n.fixed||(n.top=n.hasOwnProperty("top")?n.top:100,n.style=n.style||"",n.style+=" top:"+(t.body.scrollTop+n.top)+"px"),2===n.type&&(n.content='

'+(n.content||"")+"

"),n.skin&&(n.anim="up"),"msg"===n.skin&&(n.shade=!1),s.innerHTML=(n.shade?"
':"")+'
"+l+'
'+n.content+"
"+c+"
",!n.type||2===n.type){var d=t[i](o[0]+n.type),y=d.length;y>=1&&layer.close(d[0].getAttribute("index"))}document.body.appendChild(s);var u=e.elem=a("#"+e.id)[0];n.success&&n.success(u),e.index=r++,e.action(n,u)},c.prototype.action=function(e,t){var n=this;e.time&&(l.timer[n.index]=setTimeout(function(){layer.close(n.index)},1e3*e.time));var a=function(){var t=this.getAttribute("type");0==t?(e.no&&e.no(),layer.close(n.index)):e.yes?e.yes(n.index):layer.close(n.index)};if(e.btn)for(var s=t[i]("layui-m-layerbtn")[0].children,r=s.length,o=0;odiv{line-height:22px;padding-top:7px;margin-bottom:20px;font-size:14px}.layui-m-layerbtn{display:box;display:-moz-box;display:-webkit-box;width:100%;height:50px;line-height:50px;font-size:0;border-top:1px solid #D0D0D0;background-color:#F2F2F2}.layui-m-layerbtn span{display:block;-moz-box-flex:1;box-flex:1;-webkit-box-flex:1;font-size:14px;cursor:pointer}.layui-m-layerbtn span[yes]{color:#40AFFE}.layui-m-layerbtn span[no]{border-right:1px solid #D0D0D0;border-radius:0 0 0 5px}.layui-m-layerbtn span:active{background-color:#F6F6F6}.layui-m-layerend{position:absolute;right:7px;top:10px;width:30px;height:30px;border:0;font-weight:400;background:0 0;cursor:pointer;-webkit-appearance:none;font-size:30px}.layui-m-layerend::after,.layui-m-layerend::before{position:absolute;left:5px;top:15px;content:'';width:18px;height:1px;background-color:#999;transform:rotate(45deg);-webkit-transform:rotate(45deg);border-radius:3px}.layui-m-layerend::after{transform:rotate(-45deg);-webkit-transform:rotate(-45deg)}body .layui-m-layer .layui-m-layer-footer{position:fixed;width:95%;max-width:100%;margin:0 auto;left:0;right:0;bottom:10px;background:0 0}.layui-m-layer-footer .layui-m-layercont{padding:20px;border-radius:5px 5px 0 0;background-color:rgba(255,255,255,.8)}.layui-m-layer-footer .layui-m-layerbtn{display:block;height:auto;background:0 0;border-top:none}.layui-m-layer-footer .layui-m-layerbtn span{background-color:rgba(255,255,255,.8)}.layui-m-layer-footer .layui-m-layerbtn span[no]{color:#FD482C;border-top:1px solid #c2c2c2;border-radius:0 0 5px 5px}.layui-m-layer-footer .layui-m-layerbtn span[yes]{margin-top:10px;border-radius:5px}body .layui-m-layer .layui-m-layer-msg{width:auto;max-width:90%;margin:0 auto;bottom:-150px;background-color:rgba(0,0,0,.7);color:#fff}.layui-m-layer-msg .layui-m-layercont{padding:10px 20px} -------------------------------------------------------------------------------- /target/classes/static/layer/skin/default/icon-ext.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niantianlei/second/62537ce95b44a1288cd46d88f57eaede6d162461/target/classes/static/layer/skin/default/icon-ext.png -------------------------------------------------------------------------------- /target/classes/static/layer/skin/default/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niantianlei/second/62537ce95b44a1288cd46d88f57eaede6d162461/target/classes/static/layer/skin/default/icon.png -------------------------------------------------------------------------------- /target/classes/static/layer/skin/default/loading-0.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niantianlei/second/62537ce95b44a1288cd46d88f57eaede6d162461/target/classes/static/layer/skin/default/loading-0.gif -------------------------------------------------------------------------------- /target/classes/static/layer/skin/default/loading-1.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niantianlei/second/62537ce95b44a1288cd46d88f57eaede6d162461/target/classes/static/layer/skin/default/loading-1.gif -------------------------------------------------------------------------------- /target/classes/static/layer/skin/default/loading-2.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niantianlei/second/62537ce95b44a1288cd46d88f57eaede6d162461/target/classes/static/layer/skin/default/loading-2.gif -------------------------------------------------------------------------------- /target/classes/static/order_detail.htm: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 订单详情 5 | 6 | 7 | 8 | 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 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 45 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 |
商品名称
商品图片
订单价格
下单时间
订单状态 44 | 46 | 47 |
收货人XXX 18812341234
收货地址北京市海淀区软件园
58 |
59 | 60 | 61 | 105 | 106 | -------------------------------------------------------------------------------- /target/classes/static/sql.markdown: -------------------------------------------------------------------------------- 1 | #商品表 2 | CREATE TABLE `goods`( 3 | `id` BIGINT(20) not null auto_increment COMMENT '商品id', 4 | `goods_name` varchar(16) DEFAULT null COMMENT '商品名称', 5 | `goods_title` varchar(64) DEFAULT null COMMENT '商品标题', 6 | `goods_img` varchar(64) DEFAULT NULL COMMENT '商品图片', 7 | `goods_detail` longtext COMMENT '商品的详情介绍', 8 | `goods_price` DECIMAL(10,2) DEFAULT '0.00' comment '商品单价', 9 | `goods_stock` int(11) DEFAULT '0' COMMENT '商品库存,-1表示无限', 10 | PRIMARY KEY(`id`) 11 | )ENGINE=INNODB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4; 12 | 13 | # 秒杀商品表 14 | CREATE TABLE `second_goods` ( 15 | `id` bigint(20) not null auto_increment comment '秒杀的商品', 16 | `goods_id` bigint(20) default null comment '商品id', 17 | `second_price` decimal(10,2) default '0.00' comment '秒杀价', 18 | `stock_count` int(11) default null comment '库存数量', 19 | `start_date` datetime default null comment '秒杀开始时间', 20 | `end_date` datetime default null comment '秒杀结束时间', 21 | primary key(id) 22 | )ENGINE=InnoDB AUTO_INCREMENT=3 default charset=utf8mb4; 23 | 24 | insert into `second_goods` values(1,1,0.01,4,'2018-05-23 10:00:00','2018-06-10 20:00:00'),(2,2,0.01,10,'2018-05-25 10:00:00','2018-06-10 20:00:00'); 25 | insert into `second_goods` values(3,3,0.01,20,'2018-06-23 10:00:00','2018-06-25 20:00:00') 26 | # 订单表 27 | create table `order_info`( 28 | `id` bigint(20) not null auto_increment, 29 | `user_id` bigint(20) default null comment '用户id', 30 | `goods_id` bigint(20) default null comment '商品id', 31 | `delivery_addr_id` bigint(20) default null comment '收货地址id', 32 | `goods_name` varchar(16) default null comment '冗余商品名称', 33 | `goods_count` int(11) default '0' comment '商品数量', 34 | `goods_price` decimal(10,2) default '0.00' comment '商品单价', 35 | `order_channel` tinyint(4) default '0' comment '1pc, 2android, 3ioS', 36 | `status` tinyint(4) default '0' comment '订单状态,0新建未支付,1已支付,2已发货,3已收货,4已退款,5已完成', 37 | `create_date` datetime default null comment '订单创建时间', 38 | `pay_date` datetime default null comment '支付时间', 39 | primary key(`id`) 40 | )ENGINE=InnoDB auto_increment=12 default charset=utf8mb4; 41 | 42 | # 秒杀表 43 | create table `second_order`( 44 | `id` bigint(20) not null auto_increment, 45 | `user_id` bigint(20) default null comment '用户id', 46 | `order_id` bigint(20) default null comment '订单id', 47 | `goods_id` bigint(20) default null comment '商品id', 48 | primary key(`id`) 49 | )ENGINE=InnoDB auto_increment=3 default charset=utf8mb4; 50 | 51 | -------------------------------------------------------------------------------- /target/classes/templates/goods_detail.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 商品详情 5 | 6 | 7 | 8 | 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 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 47 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 |
商品名称
商品图片
秒杀开始时间 42 | 43 | 秒杀倒计时: 44 | 秒杀进行中 45 | 秒杀已结束 46 | 48 |
49 | 50 | 51 |
52 |
商品原价
秒杀价
库存数量
67 |
68 | 69 | 97 | 98 | -------------------------------------------------------------------------------- /target/classes/templates/goods_list.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 商品列表 5 | 6 | 7 | 8 | 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 | 34 |
商品名称商品图片商品原价秒杀价库存数量详情
详情
35 |
36 | 37 | 38 | -------------------------------------------------------------------------------- /target/classes/templates/hello.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | hello 5 | 6 | 7 | 8 |

9 | 10 | -------------------------------------------------------------------------------- /target/classes/templates/login.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 登录 5 | 6 | 7 | 8 | 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 | 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 | 98 | -------------------------------------------------------------------------------- /target/classes/templates/order_detail.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 订单详情 5 | 6 | 7 | 8 | 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 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 53 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 |
商品名称
商品图片
订单价格
下单时间
订单状态 44 | 未支付 45 | 已支付 46 | 未发货 47 | 已发货 48 | 已收货 49 | 已签收 50 | 已退款 51 | 已完成 52 | 54 | 55 |
收货人 XXX
电话XXX
收货地址北京市海淀区软件园xxx
70 |
71 | 72 | 73 | 74 | -------------------------------------------------------------------------------- /target/classes/templates/secondKill_fail.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 秒杀失败 5 | 6 | 7 | 8 | 秒杀失败:

9 | 10 | 11 | -------------------------------------------------------------------------------- /target/maven-archiver/pom.properties: -------------------------------------------------------------------------------- 1 | #Created by Apache Maven 3.5.0 2 | version=0.0.1-SNAPSHOT 3 | groupId=nian.login 4 | artifactId=second 5 | -------------------------------------------------------------------------------- /target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst: -------------------------------------------------------------------------------- 1 | nian\shop\redis\BasePrefix.class 2 | nian\shop\controller\UserController.class 3 | nian\shop\service\SecondKillService.class 4 | nian\shop\App.class 5 | nian\shop\redis\RedisConfig.class 6 | nian\shop\entity\SecondOrder.class 7 | nian\shop\service\UserService.class 8 | nian\shop\config\UserArgumentResolver.class 9 | nian\shop\service\GoodsService.class 10 | nian\shop\entity\OrderInfo.class 11 | nian\shop\DTO\ResultDTO.class 12 | nian\shop\utils\UUIDUtil.class 13 | nian\shop\service\SecondUserService.class 14 | nian\shop\utils\ResultCode.class 15 | nian\shop\entity\Goods.class 16 | nian\shop\controller\GoodsController.class 17 | nian\shop\service\OrderService.class 18 | nian\shop\exception\GlobalExceptionHandler.class 19 | nian\shop\redis\SecondUserKey.class 20 | nian\shop\VO\GoodsVo.class 21 | nian\shop\dao\OrderDao.class 22 | nian\shop\redis\OrderKey.class 23 | nian\shop\dao\UserDao.class 24 | nian\shop\entity\User.class 25 | nian\shop\redis\RedisPoolFactory.class 26 | nian\shop\validator\IsMobileValidator.class 27 | nian\shop\dao\GoodsDao.class 28 | nian\shop\redis\UserKey.class 29 | nian\shop\VO\LoginVO.class 30 | nian\shop\utils\SecondResEnum.class 31 | nian\shop\exception\SecondException.class 32 | nian\shop\utils\MD5Util.class 33 | nian\shop\config\WebConfig.class 34 | nian\shop\entity\SecondGoods.class 35 | nian\shop\dao\SecondUserDao.class 36 | nian\shop\controller\DemoController.class 37 | nian\shop\validator\IsMobile.class 38 | nian\shop\utils\SecondStatusEnum.class 39 | nian\shop\utils\ValidatorUtil.class 40 | nian\shop\entity\SecondUser.class 41 | nian\shop\controller\LoginController.class 42 | nian\shop\redis\KeyPrefix.class 43 | nian\shop\controller\SecondController.class 44 | nian\shop\service\RedisService.class 45 | -------------------------------------------------------------------------------- /target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst: -------------------------------------------------------------------------------- 1 | E:\java\workspace2\second\src\main\java\nian\shop\redis\RedisPoolFactory.java 2 | E:\java\workspace2\second\src\main\java\nian\shop\config\UserArgumentResolver.java 3 | E:\java\workspace2\second\src\main\java\nian\shop\entity\SecondOrder.java 4 | E:\java\workspace2\second\src\main\java\nian\shop\redis\BasePrefix.java 5 | E:\java\workspace2\second\src\main\java\nian\shop\exception\GlobalExceptionHandler.java 6 | E:\java\workspace2\second\src\main\java\nian\shop\dao\OrderDao.java 7 | E:\java\workspace2\second\src\main\java\nian\shop\entity\User.java 8 | E:\java\workspace2\second\src\main\java\nian\shop\dao\SecondUserDao.java 9 | E:\java\workspace2\second\src\main\java\nian\shop\redis\KeyPrefix.java 10 | E:\java\workspace2\second\src\main\java\nian\shop\controller\SecondController.java 11 | E:\java\workspace2\second\src\main\java\nian\shop\entity\SecondUser.java 12 | E:\java\workspace2\second\src\main\java\nian\shop\redis\UserKey.java 13 | E:\java\workspace2\second\src\main\java\nian\shop\utils\ValidatorUtil.java 14 | E:\java\workspace2\second\src\main\java\nian\shop\exception\SecondException.java 15 | E:\java\workspace2\second\src\main\java\nian\shop\utils\SecondStatusEnum.java 16 | E:\java\workspace2\second\src\main\java\nian\shop\service\OrderService.java 17 | E:\java\workspace2\second\src\main\java\nian\shop\service\UserService.java 18 | E:\java\workspace2\second\src\main\java\nian\shop\VO\GoodsVo.java 19 | E:\java\workspace2\second\src\main\java\nian\shop\controller\DemoController.java 20 | E:\java\workspace2\second\src\main\java\nian\shop\service\SecondKillService.java 21 | E:\java\workspace2\second\src\main\java\nian\shop\redis\OrderKey.java 22 | E:\java\workspace2\second\src\main\java\nian\shop\utils\MD5Util.java 23 | E:\java\workspace2\second\src\main\java\nian\shop\DTO\ResultDTO.java 24 | E:\java\workspace2\second\src\main\java\nian\shop\entity\OrderInfo.java 25 | E:\java\workspace2\second\src\main\java\nian\shop\redis\SecondUserKey.java 26 | E:\java\workspace2\second\src\main\java\nian\shop\service\RedisService.java 27 | E:\java\workspace2\second\src\main\java\nian\shop\validator\IsMobileValidator.java 28 | E:\java\workspace2\second\src\main\java\nian\shop\dao\GoodsDao.java 29 | E:\java\workspace2\second\src\main\java\nian\shop\service\GoodsService.java 30 | E:\java\workspace2\second\src\main\java\nian\shop\validator\IsMobile.java 31 | E:\java\workspace2\second\src\main\java\nian\shop\config\WebConfig.java 32 | E:\java\workspace2\second\src\main\java\nian\shop\controller\GoodsController.java 33 | E:\java\workspace2\second\src\main\java\nian\shop\utils\ResultCode.java 34 | E:\java\workspace2\second\src\main\java\nian\shop\controller\UserController.java 35 | E:\java\workspace2\second\src\main\java\nian\shop\VO\LoginVO.java 36 | E:\java\workspace2\second\src\main\java\nian\shop\utils\SecondResEnum.java 37 | E:\java\workspace2\second\src\main\java\nian\shop\utils\UUIDUtil.java 38 | E:\java\workspace2\second\src\main\java\nian\shop\entity\Goods.java 39 | E:\java\workspace2\second\src\main\java\nian\shop\service\SecondUserService.java 40 | E:\java\workspace2\second\src\main\java\nian\shop\redis\RedisConfig.java 41 | E:\java\workspace2\second\src\main\java\nian\shop\dao\UserDao.java 42 | E:\java\workspace2\second\src\main\java\nian\shop\App.java 43 | E:\java\workspace2\second\src\main\java\nian\shop\controller\LoginController.java 44 | E:\java\workspace2\second\src\main\java\nian\shop\entity\SecondGoods.java 45 | -------------------------------------------------------------------------------- /target/second.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niantianlei/second/62537ce95b44a1288cd46d88f57eaede6d162461/target/second.jar -------------------------------------------------------------------------------- /target/second.jar.original: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niantianlei/second/62537ce95b44a1288cd46d88f57eaede6d162461/target/second.jar.original -------------------------------------------------------------------------------- /target/test-classes/nian/shop/AppTest.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niantianlei/second/62537ce95b44a1288cd46d88f57eaede6d162461/target/test-classes/nian/shop/AppTest.class --------------------------------------------------------------------------------