lua+redis

This commit is contained in:
qiurunze 2019-02-21 19:02:45 +08:00
parent 42d4bb2bd0
commit 0f92dcce51
43 changed files with 1518 additions and 114 deletions

View File

@ -82,7 +82,7 @@
| 028 |项目进行dubbo + zk 改造 (已完成dubbo嵌入--springboot 与dubbo结合xml版本)|[解决思路](/docs/code-solve.md) |
| 029 |dubbo客户端 dubbo-admin管理平台 搭建安装|[解决思路](/docs/dubbo-admin.md) |
| 030 |如何利用dubbo 的mock 来进行服务降级本地伪装 ?? (有更好的方式进群@我)|[解决思路](/docs/dubbo-zk.md) |
| 027 |*** 如何利用lua + redis 取代 nigix + lua 脚本进行分布式限流 *** |[解决思路](/docs/redis-good.md) |
| 027 |*** 如何利用lua + redis 取代 nigix + lua 脚本进行分布式限流 (请看miaosha-2version) *** |[解决思路](/docs/redis-good.md) |
#### [分布式系统发展历程(已更新)](/docs/fenbushi.md)

View File

@ -8,6 +8,7 @@ public class AbstractResult {
private int code;
private String message;
AbstractResult() {}
protected AbstractResult(ResultStatus status, String message) {
this.code = status.getCode();
this.status = status;

View File

@ -10,6 +10,8 @@ public class ResultGeekQ<T> extends AbstractResult implements Serializable {
private T data;
private Integer count;
protected ResultGeekQ() {
}
protected ResultGeekQ(ResultStatus status, String message) {
super(status, message);
}

View File

@ -1,5 +1,6 @@
package com.geekq.miasha.vo;
import com.geekq.api.entity.GoodsVoOrder;
import com.geekq.miasha.entity.MiaoshaUser;
import lombok.AllArgsConstructor;
import lombok.Getter;
@ -14,7 +15,7 @@ import lombok.Setter;
public class GoodsDetailVo {
private int miaoshaStatus = 0;
private int remainSeconds = 0;
private GoodsVo goods ;
private GoodsVoOrder goods ;
private MiaoshaUser user;
}

View File

@ -35,5 +35,12 @@
</build>
<dependencies>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.6</version>
</dependency>
</dependencies>
</project>

View File

@ -16,6 +16,6 @@ public interface MiaoShaUserMapper {
public void insertMiaoShaUser(MiaoshaUser miaoshaUser);
public int getCountByUserName(@Param("userName")String userName , @Param("userType")int userType);
public int getCountByUserName(@Param("userName") String userName, @Param("userType") int userType);
}

View File

@ -1,24 +1,22 @@
package com.geekq.miaosha.rabbitmq;
import com.geekq.api.entity.GoodsVoOrder;
import com.geekq.api.utils.AbstractResultOrder;
import com.geekq.api.utils.ResultGeekQOrder;
import com.geekq.miaosha.redis.RedisService;
import com.geekq.miaosha.service.GoodsService;
import com.geekq.miaosha.service.MiaoShaMessageService;
import com.geekq.miaosha.service.MiaoshaService;
import com.geekq.miaosha.service.OrderService;
import com.geekq.miasha.entity.MiaoshaOrder;
import com.geekq.miasha.entity.MiaoshaUser;
import com.geekq.miasha.vo.GoodsVo;
import com.geekq.miasha.vo.MiaoShaMessageVo;
import com.rabbitmq.client.Channel;
import com.geekq.miasha.enums.enums.ResultStatus;
import com.geekq.miasha.exception.GlobleException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.io.IOException;
@Service
public class MQReceiver {
@ -36,6 +34,9 @@ public class MQReceiver {
@Autowired
MiaoshaService miaoshaService;
@Autowired
private com.geekq.api.service.GoodsService goodsServiceRpc;
// @Autowired
// MiaoShaMessageService messageService ;
@ -46,7 +47,13 @@ public class MQReceiver {
MiaoshaUser user = mm.getUser();
long goodsId = mm.getGoodsId();
GoodsVo goods = goodsService.getGoodsVoByGoodsId(goodsId);
// GoodsVo goods = goodsService.getGoodsVoByGoodsId(goodsId);
ResultGeekQOrder<GoodsVoOrder> goodsVoOrderResultGeekQOrder = goodsServiceRpc.getGoodsVoByGoodsId(goodsId);
if(!AbstractResultOrder.isSuccess(goodsVoOrderResultGeekQOrder)){
throw new GlobleException(ResultStatus.SESSION_ERROR);
}
GoodsVoOrder goods= goodsVoOrderResultGeekQOrder.getData();
int stock = goods.getStockCount();
if(stock <= 0) {
return;

View File

@ -0,0 +1,58 @@
package com.geekq.miaosha.redis.redismanager;
import redis.clients.jedis.Jedis;
import java.io.IOException;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CountDownLatch;
public class RedisLimitRateWithLUA {
public static void main(String[] args) {
final CountDownLatch latch = new CountDownLatch(1);
for (int i = 0; i < 20; i++) {
new Thread(new Runnable() {
public void run() {
try {
latch.await();
System.out.println("请求是否被执行:"+accquire());
} catch (Exception e) {
e.printStackTrace();
}
}
}).start();
}
latch.countDown();
}
public static boolean accquire() throws IOException, URISyntaxException {
Jedis jedis = new Jedis("39.107.245.253");
String lua =
"local key = KEYS[1] " +
" local limit = tonumber(ARGV[1]) " +
" local current = tonumber(redis.call('get', key) or '0')" +
" if current + 1 > limit " +
" then return 0 " +
" else "+
" redis.call('INCRBY', key,'1')" +
" redis.call('expire', key,'2') " +
" end return 1 ";
String key = "ip:" + System.currentTimeMillis()/1000; // 当前秒
String limit = "3"; // 最大限制
List<String> keys = new ArrayList<String>();
keys.add(key);
List<String> args = new ArrayList<String>();
args.add(limit);
jedis.auth("youxin11");
String luaScript = jedis.scriptLoad(lua);
Long result = (Long)jedis.evalsha(luaScript, keys, args);
return result == 1;
}
}

View File

@ -7,6 +7,8 @@ import redis.clients.jedis.Jedis;
import java.util.ArrayList;
import java.util.List;
import static redis.clients.jedis.Protocol.Command.INCRBY;
/**
* lua脚本使用
*/
@ -92,4 +94,37 @@ public class RedisLua {
logger.error("统计访问次数失败!!!",e);
}
}
public static void currentlimitMinute() {
Jedis jedis = null;
try {
jedis = RedisManager.getJedis();
} catch (Exception e) {
e.printStackTrace();
}
String lua =
"local key = KEYS[1] " +
"local limit = tonumber(ARGV[1]) " +
"local current = tonumber(redis.call('get', key) or '0') " +
"if current + 1 > limit then return 0 " +
"else redis.call('INCRBY', key,'1')" +
" redis.call('expire', key,'2') " +
"end return 1";
List<String> keys = new ArrayList<String>();
keys.add("ip:limit:127.0.0.1");
List<String> argves = new ArrayList<String>();
argves.add("6000");
argves.add("5");
jedis.auth("xxxx");
// Object evalSha = jedis.evalsha(lua);
String luaScript = jedis.scriptLoad(lua);
System.out.println(luaScript);
Object object = jedis.evalsha(luaScript, keys, argves);
System.out.println(object);
}
}

View File

@ -0,0 +1,32 @@
local key = KEYS[1] --限流KEY一秒一个
local limit = tonumber(ARGV[1]) --限流大小
local current = tonumber(redis.call('get', key) or "0")
if current + 1 > limit then --如果超出限流大小
return 0
else --请求数+1并设置2秒过期
redis.call("INCRBY", key,"1")
redis.call("expire", key,"2")
end
return 1
-- ip限流
local key = "rate.limit:" .. KEYS[1]
local limit = tonumber(ARGV[1])
local expire_time = ARGV[2]
local is_exists = redis.call("EXISTS", key)
if is_exists == 1 then
if redis.call("INCR", key) > limit then
return 0
else
return 1
end
else
redis.call("SET", key, 1)
redis.call("EXPIRE", key, expire_time)
return 1
end

View File

@ -1,5 +1,7 @@
package com.geekq.miaosha.service;
import com.alibaba.dubbo.config.annotation.Reference;
import com.geekq.api.entity.GoodsVoOrder;
import com.geekq.miaosha.redis.MiaoshaKey;
import com.geekq.miaosha.redis.RedisService;
import com.geekq.miasha.entity.MiaoshaOrder;
@ -29,10 +31,14 @@ public class MiaoshaService {
@Autowired
RedisService redisService;
@Reference(version = "${demo.service.version}",retries = 3,timeout = 6000)
private com.geekq.api.service.GoodsService goodsServiceRpc;
@Transactional
public OrderInfo miaosha(MiaoshaUser user, GoodsVo goods) {
public OrderInfo miaosha(MiaoshaUser user, GoodsVoOrder goods) {
//减库存 下订单 写入秒杀订单
boolean success = goodsService.reduceStock(goods);
// boolean success = goodsService.reduceStock(goods);
boolean success =goodsServiceRpc.reduceStock(goods);
if(success){
return orderService.createOrder(user,goods) ;
}else {

View File

@ -1,5 +1,6 @@
package com.geekq.miaosha.service;
import com.geekq.api.entity.GoodsVoOrder;
import com.geekq.miaosha.mapper.OrderMapper;
import com.geekq.miaosha.redis.OrderKey;
import com.geekq.miaosha.redis.RedisService;
@ -37,7 +38,7 @@ public class OrderService {
}
@Transactional
public OrderInfo createOrder(MiaoshaUser user, GoodsVo goods) {
public OrderInfo createOrder(MiaoshaUser user, GoodsVoOrder goods) {
OrderInfo orderInfo = new OrderInfo();
orderInfo.setCreateDate(new Date());
orderInfo.setDeliveryAddrId(0L);

View File

@ -0,0 +1,10 @@
local key = KEYS[1] --限流KEY一秒一个
local limit = tonumber(ARGV[1]) --限流大小
local current = tonumber(redis.call('get', key) or "0")
if current + 1 > limit then --如果超出限流大小
return 0
else --请求数+1并设置2秒过期
redis.call("INCRBY", key,"1")
redis.call("expire", key,"2")
end
return 1

View File

@ -1,16 +1,19 @@
package com.geekq.miaosha;
import com.alibaba.dubbo.config.spring.context.annotation.EnableDubbo;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ImportResource;
@EnableDubbo
@ImportResource(value={"classpath:consumer.xml"})
@SpringBootApplication
@MapperScan("com.geekq.miaosha.mapper")
public class GeekQMainApplication {
public static void main(String[] args) throws Exception {
// RegistryFactory registryFactory = ExtensionLoader.getExtensionLoader(RegistryFactory.class).getAdaptiveExtension();
// Registry registry = registryFactory.getRegistry(URL.valueOf("zookeeper://localhost:2181"));
// registry.register(URL.valueOf("override://0.0.0.0/com.geekq.api.service.GoodsService?category=configurators&dynamic=false&application=dubbo-consumer2.0&mock=fail:return+444"));
SpringApplication.run(GeekQMainApplication.class, args);
}

View File

@ -1,12 +1,17 @@
package com.geekq.miaosha.controller;
import com.alibaba.dubbo.config.annotation.Reference;
import com.geekq.api.entity.GoodsVoOrder;
import com.geekq.api.utils.AbstractResultOrder;
import com.geekq.api.utils.ResultGeekQOrder;
import com.geekq.miaosha.interceptor.RequireLogin;
import com.geekq.miaosha.redis.GoodsKey;
import com.geekq.miaosha.redis.RedisService;
import com.geekq.miaosha.service.GoodsService;
import com.geekq.miaosha.service.MiaoShaUserService;
import com.geekq.miasha.entity.MiaoshaUser;
import com.geekq.miasha.enums.enums.ResultStatus;
import com.geekq.miasha.enums.resultbean.ResultGeekQ;
import com.geekq.miasha.exception.GlobleException;
import com.geekq.miasha.vo.GoodsDetailVo;
import com.geekq.miasha.vo.GoodsVo;
import org.apache.commons.lang3.StringUtils;
@ -40,7 +45,7 @@ public class GoodsController extends BaseController {
@Autowired
private GoodsService goodsService;
@Reference(version = "${demo.service.version}")
@Autowired
private com.geekq.api.service.GoodsService goodsServiceRpc;
@Autowired
@ -54,12 +59,19 @@ public class GoodsController extends BaseController {
* 5000 * 10
* QPS:2884, load:5
* */
@RequireLogin(seconds = 5, maxCount = 5, needLogin = true)
@RequestMapping(value="/to_list", produces="text/html")
@ResponseBody
public String list(HttpServletRequest request, HttpServletResponse response, Model model, MiaoshaUser user) {
public String list(HttpServletRequest request, HttpServletResponse response, Model model, MiaoshaUser user) {
model.addAttribute("user", user);
// ResultGeekQ<List<com.geekq.api.entity.GoodsVo>> goodsList1 = goodsServiceRpc.listGoodsVo();
List<GoodsVo> goodsList = goodsService.listGoodsVo();
//订单服务化接口 miaosha-order
ResultGeekQOrder<List<GoodsVoOrder>> resultGoods = goodsServiceRpc.listGoodsVo();
if(!AbstractResultOrder.isSuccess(resultGoods)){
throw new GlobleException(ResultStatus.SYSTEM_ERROR);
}
List<GoodsVoOrder> goodsList = resultGoods.getData();
model.addAttribute("goodsList", goodsList);
return render(request,response,model,"goods_list", GoodsKey.getGoodsList,"");
}
@ -77,6 +89,13 @@ public class GoodsController extends BaseController {
}
//手动渲染
GoodsVo goods = goodsService.getGoodsVoByGoodsId(goodsId);
/**
* rpc服务化接口
*/
ResultGeekQOrder<GoodsVoOrder> goodsVoOrderResultGeekQOrder = goodsServiceRpc.getGoodsVoByGoodsId(goodsId);
if(!AbstractResultOrder.isSuccess(goodsVoOrderResultGeekQOrder)){
throw new GlobleException(ResultStatus.SESSION_ERROR);
}
model.addAttribute("goods", goods);
long startAt = goods.getStartDate().getTime();
@ -126,7 +145,16 @@ public class GoodsController extends BaseController {
public ResultGeekQ<GoodsDetailVo> detail(HttpServletRequest request, HttpServletResponse response, Model model, MiaoshaUser user,
@PathVariable("goodsId")long goodsId) {
ResultGeekQ<GoodsDetailVo> result = ResultGeekQ.build();
GoodsVo goods = goodsService.getGoodsVoByGoodsId(goodsId);
/**
* 服务化rpc接口
*/
ResultGeekQOrder<GoodsVoOrder> goodsVoOrderResultGeekQOrder = goodsServiceRpc.getGoodsVoByGoodsId(goodsId);
if(!AbstractResultOrder.isSuccess(goodsVoOrderResultGeekQOrder)){
throw new GlobleException(ResultStatus.SESSION_ERROR);
}
GoodsVoOrder goods = goodsVoOrderResultGeekQOrder.getData();
long startAt = goods.getStartDate().getTime();
long endAt = goods.getEndDate().getTime();
long now = System.currentTimeMillis();

View File

@ -30,21 +30,20 @@ public class LoginController {
@Autowired
private MiaoShaUserService userService;
@Reference(version = "${demo.service.version}")
@Reference(version = "${demo.service.version}",mock = "return null")
private DemoService demoService;
@RequestMapping("/sayHello/{name}")
@ResponseBody
public String sayHello(@PathVariable("name") String name) {
return demoService.sayHello(name);
@RequestMapping("/sayHello")
public String sayHello() throws Exception {
return "login222";
}
@RequestMapping("/to_login")
public String tologin(LoginVo loginVo, Model model) {
public String tologin(LoginVo loginVo, Model model) {
logger.info(loginVo.toString());
//未完成
RedisLua.vistorCount(COUNTLOGIN);
String count = RedisLua.getVistorCount(COUNTLOGIN).toString();

View File

@ -5,6 +5,7 @@ import com.geekq.miaosha.rabbitmq.MQSender;
import com.geekq.miaosha.rabbitmq.MiaoshaMessage;
import com.geekq.miaosha.redis.GoodsKey;
import com.geekq.miaosha.redis.RedisService;
import com.geekq.miaosha.redis.redismanager.RedisLimitRateWithLUA;
import com.geekq.miaosha.service.GoodsService;
import com.geekq.miaosha.service.MiaoShaUserService;
import com.geekq.miaosha.service.MiaoshaService;
@ -25,7 +26,9 @@ import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.OutputStream;
import java.net.URISyntaxException;
import java.util.HashMap;
import java.util.List;
@ -89,6 +92,19 @@ public class MiaoshaController implements InitializingBean {
//
// }
/**
* 分布式限流
*/
try {
RedisLimitRateWithLUA.accquire();
} catch (IOException e) {
result.withError(EXCEPTION.getCode(), REPEATE_MIAOSHA.getMessage());
return result;
} catch (URISyntaxException e) {
result.withError(EXCEPTION.getCode(), REPEATE_MIAOSHA.getMessage());
return result;
}
//是否已经秒杀到
MiaoshaOrder order = orderService.getMiaoshaOrderByUserIdGoodsId(Long.valueOf(user.getNickname()), goodsId);
if (order != null) {

View File

@ -68,18 +68,16 @@ spring.rabbitmq.publisher-confirms=true
spring.rabbitmq.listener.direct.acknowledge-mode=manual
spring.rabbitmq.listener.simple.acknowledge-mode=manual
spring.application.name = dubbo-consumer
server.port = 9091
dubbo.application.name = dubbo-consumer
demo.service.version = 1.0.0
dubbo.protocol.name = dubbo
dubbo.protocol.port = 20880
dubbo.registry.address = zookeeper://localhost:2181
dubbo.consumer.timeout = 5000
#spring.application.name = dubbo-consumer
#
#dubbo.application.name = dubbo-consumer
#demo.service.version = 1.0.0
#dubbo.protocol.name = dubbo
#dubbo.protocol.port = 20880
#dubbo.registry.address = zookeeper://localhost:2181
#dubbo.consumer.timeout = 5000
#dubbo.consumer.mock= true
## maven隔离
#spring.profiles.active=dev

View File

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd
http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd">
<!-- 为当前服务提供者取个名字,并且提供给注册中心 -->
<dubbo:application name="dubbo-consumer3"></dubbo:application>
<!-- 注册中心的配置,用于消费者的监听 -->
<dubbo:registry protocol="zookeeper" address="localhost:2181"></dubbo:registry>
<!--&lt;!&ndash; 监听服务,通过注册中心去进行查找,查找到后进行服务调用 &ndash;&gt;-->
<dubbo:reference id="goodsServiceRpc" interface="com.geekq.api.service.GoodsService"
retries="3" check="false" init="true" timeout="3000" group="goods2"></dubbo:reference>
</beans>

View File

@ -0,0 +1,117 @@
/*
www.coedq.net
www.xttblog.com
*/
#slider {
margin: 100px auto;
width: 300px;
height: 40px;
position: relative;
border-radius: 2px;
background-color: #dae2d0;
overflow: hidden;
text-align: center;
user-select: none;
-moz-user-select: none;
-webkit-user-select: none;
}
#slider_bg {
position: absolute;
left: 0;
top: 0;
height: 100%;
background-color: #7AC23C;
z-index: 1;
}
#label {
width: 46px;
position: absolute;
left: 0;
top: 0;
height: 38px;
line-height: 38px;
border: 1px solid #cccccc;
background: #fff;
z-index: 3;
cursor: move;
color: #ff9e77;
font-size: 16px;
font-weight: 900;
}
#labelTip {
position: absolute;
left: 0;
width: 100%;
height: 100%;
font-size: 13px;
font-family: 'Microsoft Yahei', serif;
color: #787878;
line-height: 38px;
text-align: center;
z-index: 2;
}
/*
www.coedq.net
www.xttblog.com
*/

View File

@ -0,0 +1,117 @@
/*
www.coedq.net
www.xttblog.com
*/
#slider {
margin: 100px auto;
width: 300px;
height: 40px;
position: relative;
border-radius: 2px;
background-color: #dae2d0;
overflow: hidden;
text-align: center;
user-select: none;
-moz-user-select: none;
-webkit-user-select: none;
}
#slider_bg {
position: absolute;
left: 0;
top: 0;
height: 100%;
background-color: #7AC23C;
z-index: 1;
}
#label {
width: 46px;
position: absolute;
left: 0;
top: 0;
height: 38px;
line-height: 38px;
border: 1px solid #cccccc;
background: #fff;
z-index: 3;
cursor: move;
color: #ff9e77;
font-size: 16px;
font-weight: 900;
}
#labelTip {
position: absolute;
left: 0;
width: 100%;
height: 100%;
font-size: 13px;
font-family: 'Microsoft Yahei', serif;
color: #787878;
line-height: 38px;
text-align: center;
z-index: 2;
}
/*
www.coedq.net
www.xttblog.com
*/

View File

@ -0,0 +1,64 @@
<!DOCTYPE html>
<html xmlns:th="http://www.w3.org/1999/xhtml">
<head>
<meta charset="utf-8">
<title>登录界面</title>
<link rel="stylesheet" href="css/reset.css" />
<link rel="stylesheet" href="css/common.css" />
<link rel="stylesheet" href="css/font-awesome.min.css" />
<script type="text/javascript" src="js/jquery.min.js" ></script>
<script type="text/javascript" src="js/common.js" ></script>
<script type="text/javascript" src="js/md5.min.js"></script>
<script type="text/javascript" src="jquery-validation/jquery.validate.min.js"></script>
<script type="text/javascript" src="layer/layer.js"></script>
<script type="text/javascript" src="js/jquery.min.js"></script>
<script type="text/javascript" src="bootstrap/js/bootstrap.min.js"></script>
<script type="text/javascript" src="layer/layer.js"></script>
<meta name="viewport" content="width=device-width,initial-scale=1">
<link rel="stylesheet" href="/css/slide-unlock.css" type="text/css" />
<script type="text/javascript" src="js/slideunlock/slideunlock.js"></script>
<script src="http://cdn.bootcss.com/jquery/1.11.2/jquery.min.js"></script>
<style>
html, body, h1 {
margin: 0;
padding: 0;
}
body {
background-color: #393939;
color: #d5d4ff;
overflow: hidden
}
#demo {
width: 600px;
margin: 150px auto;
padding: 10px;
border: 1px dashed #d5d4ff;
border-radius: 10px;
-moz-border-radius: 10px;
-webkit-border-radius: 10px;
text-align: left;
}
</style>
<script>
$(function () {
var slider = new SliderUnlock("#slider",{
successLabelTip : "欢迎访问业余草网站"
},function(){
alert("验证成功,即将跳转至业余草首页");
//window.location.href="http://www.xttblog.com"
});
slider.init();
})
</script>
</head>
<body>
<div id="demo">
<div id="slider">
<div id="slider_bg"></div>
<span id="label">>></span> <span id="labelTip">拖动滑块验证</span> </div>
</div>
</body>
</html>

View File

@ -0,0 +1,378 @@
;(function ($,window,document,undefined) {
function SliderUnlock(elm, options, success){
var me = this;
var $elm = me.checkElm(elm) ? $(elm) : $;
success = me.checkFn(success) ? success : function(){};
var opts = {
successLabelTip: "Successfully Verified",
duration: 200,
swipestart: false,
min: 0,
max: $elm.width(),
index: 0,
IsOk: false,
lableIndex: 0
};
opts = $.extend(opts, options||{});
//$elm
me.elm = $elm;
//opts
me.opts = opts;
//是否开始滑动
me.swipestart = opts.swipestart;
//最小值
me.min = opts.min;
//最大值
me.max = opts.max;
//当前滑动条所处的位置
me.index = opts.index;
//是否滑动成功
me.isOk = opts.isOk;
//滑块宽度
me.labelWidth = me.elm.find('#label').width();
//滑块背景
me.sliderBg = me.elm.find('#slider_bg');
//鼠标在滑动按钮的位置
me.lableIndex = opts.lableIndex;
//success
me.success = success;
}
SliderUnlock.prototype.init = function () {
var me = this;
me.updateView();
me.elm.find("#label").on("mousedown", function (event) {
var e = event || window.event;
me.lableIndex = e.clientX - this.offsetLeft;
me.handerIn();
}).on("mousemove", function (event) {
me.handerMove(event);
}).on("mouseup", function (event) {
me.handerOut();
}).on("mouseout", function (event) {
me.handerOut();
}).on("touchstart", function (event) {
var e = event || window.event;
me.lableIndex = e.originalEvent.touches[0].pageX - this.offsetLeft;
me.handerIn();
}).on("touchmove", function (event) {
me.handerMove(event, "mobile");
}).on("touchend", function (event) {
me.handerOut();
});
};
/**
* 鼠标/手指接触滑动按钮
*/
SliderUnlock.prototype.handerIn = function () {
var me = this;
me.swipestart = true;
me.min = 0;
me.max = me.elm.width();
};
/**
* 鼠标/手指移出
*/
SliderUnlock.prototype.handerOut = function () {
var me = this;
//停止
me.swipestart = false;
//me.move();
if (me.index < me.max) {
me.reset();
}
};
/**
* 鼠标/手指移动
* @param event
* @param type
*/
SliderUnlock.prototype.handerMove = function (event, type) {
var me = this;
if (me.swipestart) {
event.preventDefault();
event = event || window.event;
if (type == "mobile") {
me.index = event.originalEvent.touches[0].pageX - me.lableIndex;
} else {
me.index = event.clientX - me.lableIndex;
}
me.move();
}
};
/**
* 鼠标/手指移动过程
*/
SliderUnlock.prototype.move = function () {
var me = this;
if ((me.index + me.labelWidth) >= me.max) {
me.index = me.max - me.labelWidth -2;
//停止
me.swipestart = false;
//解锁
me.isOk = true;
}
if (me.index < 0) {
me.index = me.min;
//未解锁
me.isOk = false;
}
if (me.index+me.labelWidth+2 == me.max && me.max > 0 && me.isOk) {
//解锁默认操作
$('#label').unbind().next('#labelTip').
text(me.opts.successLabelTip).css({'color': '#fff'});
me.success();
}
me.updateView();
};
/**
* 更新视图
*/
SliderUnlock.prototype.updateView = function () {
var me = this;
me.sliderBg.css('width', me.index);
me.elm.find("#label").css("left", me.index + "px")
};
/**
* 重置slide的起点
*/
SliderUnlock.prototype.reset = function () {
var me = this;
me.index = 0;
me.sliderBg .animate({'width':0},me.opts.duration);
me.elm.find("#label").animate({left: me.index}, me.opts.duration)
.next("#lableTip").animate({opacity: 1}, me.opts.duration);
me.updateView();
};
/**
* 检测元素是否存在
* @param elm
* @returns {boolean}
*/
SliderUnlock.prototype.checkElm = function (elm) {
if($(elm).length > 0){
return true;
}else{
throw "this element does not exist.";
}
};
/**
* 检测传入参数是否是function
* @param fn
* @returns {boolean}
*/
SliderUnlock.prototype.checkFn = function (fn) {
if(typeof fn === "function"){
return true;
}else{
throw "the param is not a function.";
}
};
window['SliderUnlock'] = SliderUnlock;
})(jQuery, window, document);

View File

@ -0,0 +1,73 @@
<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>登录</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<link rel="stylesheet" href="css/reset.css" />
<link rel="stylesheet" href="css/common.css" />
<link rel="stylesheet" href="css/font-awesome.min.css" />
<!-- jquery -->
<script type="text/javascript" th:src="@{/js/jquery.min.js}"></script>
<!-- bootstrap -->
<link rel="stylesheet" type="text/css" th:href="@{/bootstrap/css/bootstrap.min.css}" />
<link rel="stylesheet" type="text/css" th:href="@{/js/bootstrap-3.3.2-dist/css/bootstrap.css}" />
<script type="text/javascript" th:src="@{/bootstrap/js/bootstrap.min.js}"></script>
<!-- jquery-validator -->
<script type="text/javascript" th:src="@{/jquery-validation/jquery.validate.min.js}"></script>
<script type="text/javascript" th:src="@{/jquery-validation/localization/messages_zh.min.js}"></script>
<!-- layer -->
<script type="text/javascript" th:src="@{/layer/layer.js}"></script>
<!-- md5.js -->
<script type="text/javascript" th:src="@{/js/md5.min.js}"></script>
<!-- common.js -->
<script type="text/javascript" th:src="@{/js/common.js}"></script>
<script type="text/javascript" th:src="@{/js/bootstrap-3.3.2-dist/js/bootstrap.js}"></script>
<script type="text/javascript" th:src="@{/js/plugins/jquery-validation/jquery.validate.js}"></script>
<script type="text/javascript" th:src="@{/js/plugins/jquery-validation/localization/messages_zh.js}"></script>
<script type="text/javascript" th:src="@{/js/plugins/jquery.form.js}"></script>
<script type="text/javascript" th:src="@{/js/jquery.bootstrap.min.js}"></script>
<link rel="stylesheet" type="text/css" th:href="@{/css/slide-unlock.css}" />
<script type="text/javascript" th:src="@{/js/slideunlock/slideunlock.js}"></script>
<style>
html, body, h1 {
margin: 0;
padding: 0;
}
body {
background-color: #393939;
color: #d5d4ff;
overflow: hidden
}
#demo {
width: 600px;
margin: 150px auto;
padding: 10px;
border: 1px dashed #d5d4ff;
border-radius: 10px;
-moz-border-radius: 10px;
-webkit-border-radius: 10px;
text-align: left;
}
</style>
</head>
<body>
<div id="demo">
<div id="slider">
<div id="slider_bg"></div>
<span id="label">>></span> <span id="labelTip">拖动滑块验证</span> </div>
</div>
</body>
<script>
$(function () {
var slider = new SliderUnlock("#slider",{
successLabelTip : "欢迎访问业余草网站"
},function(){
alert("验证成功,即将跳转至业余草首页");
//window.location.href="http://www.xttblog.com"
});
slider.init();
})
</script>
</html>

View File

@ -0,0 +1,53 @@
<!DOCTYPE html>
<html xmlns:th="http://www.w3.org/1999/xhtml">
<head>
<title>拖拽滑动验证码插件 slideunlock.js</title>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE-edge,chrome=1">
<meta name="viewport" content="width=device-width,initial-scale=1">
<link rel="stylesheet" href="/css/slide-unlock.css" type="text/css" />
<script type="text/javascript" src="js/slideunlock/slideunlock.js"></script>
<script src="http://cdn.bootcss.com/jquery/1.11.2/jquery.min.js"></script>
<style>
html, body, h1 {
margin: 0;
padding: 0;
}
body {
background-color: #393939;
color: #d5d4ff;
overflow: hidden
}
#demo {
width: 600px;
margin: 150px auto;
padding: 10px;
border: 1px dashed #d5d4ff;
border-radius: 10px;
-moz-border-radius: 10px;
-webkit-border-radius: 10px;
text-align: left;
}
</style>
</head>
<body>
<div id="demo">
<div id="slider">
<div id="slider_bg"></div>
<span id="label">>></span> <span id="labelTip">拖动滑块验证</span> </div>
<script>
$(function () {
var slider = new SliderUnlock("#slider",{
successLabelTip : "欢迎访问业余草网站"
},function(){
alert("验证成功,即将跳转至业余草首页");
//window.location.href="http://www.xttblog.com"
});
slider.init();
})
</script>
</div>
</body>
</html>

View File

@ -6,14 +6,15 @@ import lombok.NoArgsConstructor;
import lombok.Setter;
import org.apache.ibatis.type.Alias;
import java.io.Serializable;
import java.util.Date;
@Setter
@Getter
@AllArgsConstructor
@NoArgsConstructor
@Alias("goodsVo")
public class GoodsVo {
@Alias("goodsVoOrder")
public class GoodsVoOrder implements Serializable {
private Long id;
private String goodsName;
private String goodsTitle;

View File

@ -0,0 +1,23 @@
package com.geekq.api.entity;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import org.apache.ibatis.type.Alias;
import java.io.Serializable;
import java.util.Date;
@Setter
@Getter
@AllArgsConstructor
@NoArgsConstructor
@Alias("MiaoshaGoods")
public class MiaoshaGoods implements Serializable {
private Long id;
private Long goodsId;
private Integer stockCount;
private Date startDate;
private Date endDate;
}

View File

@ -1,13 +0,0 @@
package com.geekq.api.service;
/**
* DemoService
* 服务Api接口类
* @author geekq
* @date 2018/6/6
*/
public interface DemoService {
String sayHello(String name);
}

View File

@ -1,7 +1,7 @@
package com.geekq.api.service;
import com.geekq.api.entity.GoodsVo;
import com.geekq.common.utils.resultbean.ResultGeekQ;
import com.geekq.api.entity.GoodsVoOrder;
import com.geekq.api.utils.ResultGeekQOrder;
import java.util.List;
@ -10,5 +10,22 @@ import java.util.List;
*/
public interface GoodsService {
public ResultGeekQ<List<GoodsVo>> listGoodsVo();
/**
* 查询获取全部信息
* @return
*/
public ResultGeekQOrder<List<GoodsVoOrder>> listGoodsVo();
/**
* 根据商品id查询货物信息
* @param goodsId
* @return
*/
public ResultGeekQOrder<GoodsVoOrder> getGoodsVoByGoodsId(long goodsId);
/**
* 减库存
* @return
*/
public boolean reduceStock(GoodsVoOrder goods);
}

View File

@ -0,0 +1,33 @@
package com.geekq.api.service;
import com.geekq.api.entity.GoodsVoOrder;
import com.geekq.api.service.GoodsService;
import com.geekq.api.utils.ResultGeekQOrder;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.List;
/**
* @author 邱润泽
*/
@Service
public class GoodsServiceMock implements GoodsService {
@Override
public ResultGeekQOrder<List<GoodsVoOrder>> listGoodsVo() {
List<GoodsVoOrder> list1 = new ArrayList<>();
ResultGeekQOrder<List<GoodsVoOrder>> list = ResultGeekQOrder.build();
list.setData(list1);
return list;
}
@Override
public ResultGeekQOrder<GoodsVoOrder> getGoodsVoByGoodsId(long goodsId) {
return null;
}
@Override
public boolean reduceStock(GoodsVoOrder goods) {
return false;
}
}

View File

@ -0,0 +1,63 @@
package com.geekq.api.utils;
public class AbstractResultOrder {
private ResultStatusOrder status;
private int code;
private String message;
protected AbstractResultOrder() {
}
protected AbstractResultOrder(ResultStatusOrder status, String message) {
this.code = status.getCode();
this.status = status;
this.message = message;
}
protected AbstractResultOrder(ResultStatusOrder status) {
this.code = status.getCode();
this.message = status.getMessage();
this.status = status;
}
public static boolean isSuccess(AbstractResultOrder result) {
return result != null && result.status == ResultStatusOrder.SUCCESS && result.getCode() == ResultStatusOrder.SUCCESS.getCode();
}
public AbstractResultOrder withError(ResultStatusOrder status) {
this.status = status;
return this;
}
public AbstractResultOrder withError(String message) {
this.status = ResultStatusOrder.SYSTEM_ERROR;
this.message = message;
return this;
}
public AbstractResultOrder withError(int code, String message) {
this.code = code;
this.message = message;
return this;
}
public AbstractResultOrder success() {
this.status = ResultStatusOrder.SUCCESS;
return this;
}
public ResultStatusOrder getStatus() {
return this.status;
}
public String getMessage() {
return this.message == null ? this.status.getMessage() : this.message;
}
public int getCode() {
return this.code;
}
public void setCode(int code) {
this.code = code;
}
}

View File

@ -0,0 +1,53 @@
package com.geekq.api.utils;
import java.io.Serializable;
public class ResultGeekQOrder<T> extends AbstractResultOrder implements Serializable {
private static final long serialVersionUID = 867933019328199779L;
private T data;
private Integer count;
protected ResultGeekQOrder() {
}
protected ResultGeekQOrder(ResultStatusOrder status, String message) {
super(status, message);
}
protected ResultGeekQOrder(ResultStatusOrder status) {
super(status);
}
public static <T> ResultGeekQOrder<T> build() {
return new ResultGeekQOrder(ResultStatusOrder.SUCCESS, (String)null);
}
public static <T> ResultGeekQOrder<T> build(String message) {
return new ResultGeekQOrder(ResultStatusOrder.SUCCESS, message);
}
public static <T> ResultGeekQOrder<T> error(ResultStatusOrder status) {
return new ResultGeekQOrder<T>(status);
}
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
public Integer getCount() {
return this.count;
}
public void setCount(Integer count) {
this.count = count;
}
public void success(T value) {
this.success();
this.data = value;
this.count = 0;
}
}

View File

@ -0,0 +1,104 @@
package com.geekq.api.utils;
/**
* 普通返回类
* 1打头 系统系列错误
* 2 注册登录系列错误
* 3 check 系列错误
* 4 秒杀错误
* 5 商品错误
* 6 订单错误
* @author qiurunze
*/
public enum ResultStatusOrder {
SUCCESS(0, "成功"),
FAILD(-1, "失败"),
EXCEPTION(-1, "系统异常"),
PARAM_ERROR(10000, "参数错误"),
SYSTEM_ERROR(10001, "系统错误"),
FILE_NOT_EXIST(10002, "文件不存在"),
FILE_NOT_DOWNLOAD(10003, "文件没有下载"),
FILE_NOT_GENERATE(10004, "文件没有生成"),
FILE_NOT_STORAGE(10005, "文件没有入库"),
SYSTEM_DB_ERROR(10006, "数据库系统错误"),
FILE_ALREADY_DOWNLOAD(10007, "文件已经下载"),
DATA_ALREADY_PEXISTS(10008, "数据已经存在"),
/**
* 注册登录
*/
RESIGETR_SUCCESS(20000,"注册成功!"),
RESIGETER_FAIL(200001,"注册失败!"),
CODE_FAIL(200002,"验证码不一致!"),
/**
* check
*/
BIND_ERROR (30001,"参数校验异常:%s"),
ACCESS_LIMIT_REACHED (30002,"请求非法!"),
REQUEST_ILLEGAL (30004,"访问太频繁!"),
SESSION_ERROR (30005,"Session不存在或者已经失效!"),
PASSWORD_EMPTY (30006,"登录密码不能为空!"),
MOBILE_EMPTY (30007,"手机号不能为空!"),
MOBILE_ERROR (30008,"手机号格式错误!"),
MOBILE_NOT_EXIST (30009,"账号不存在!"),
PASSWORD_ERROR (30010,"密码错误!"),
USER_NOT_EXIST(30011,"用户不存在!"),
/**
* 订单模块
*/
ORDER_NOT_EXIST(60001,"订单不存在"),
/**
* 秒杀模块
*/
MIAO_SHA_OVER(40001,"商品已经秒杀完毕"),
REPEATE_MIAOSHA(40002,"不能重复秒杀"),
MIAOSHA_FAIL(40003,"秒杀失败"),
ORDER_GET_FAIL(40004,"订单获取失败");
/**
* 商品模块
*/
private int code;
private String message;
private ResultStatusOrder(int code, String message) {
this.code = code;
this.message = message;
}
public int getCode() {
return this.code;
}
public void setCode(int code) {
this.code = code;
}
public String getMessage() {
return this.message;
}
public void setMessage(String message) {
this.message = message;
}
public String getName() {
return this.name();
}
public String getOutputName() {
return this.name();
}
public String toString() {
return this.getName();
}
private ResultStatusOrder(Object... args) {
this.message = String.format(this.message, args);
}
}

View File

@ -38,7 +38,32 @@
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>true</filtering>
</resource>
<resource>
<directory>src/main/resources</directory>
<!--<includes>-->
<!--<include>**/*.properties</include>-->
<!--<include>**/*.xml</include>-->
<!--<include>**/*.ini</include>-->
<!--</includes>-->
<filtering>false</filtering>
</resource>
<resource> <!--配置文件路径 -->
<directory>src/main/resources</directory> <!--这里对应项目存放配置文件的目录--> <!--开启filtering功能 -->
<filtering>true</filtering>
<includes>
<!--<include>application-${activatedProperties}.properties</include>-->
<include>application.properties</include>
</includes>
</resource>
</resources>
</build>
</project>

View File

@ -1,9 +1,9 @@
package com.geekq.provider;
import com.alibaba.dubbo.config.spring.context.annotation.EnableDubbo;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ImportResource;
/**
* DubboProviderApplication
@ -11,7 +11,7 @@ import org.springframework.boot.autoconfigure.SpringBootApplication;
* @author geekq
* @date 2018/6/7
*/
@EnableDubbo
@ImportResource(value={"classpath:provider.xml"})
@SpringBootApplication
@MapperScan("com.geekq.provider.mapper")
public class DubboProviderApplication {

View File

@ -1,6 +1,7 @@
package com.geekq.provider.mapper;
import com.geekq.api.entity.GoodsVo;
import com.geekq.api.entity.GoodsVoOrder;
import com.geekq.api.entity.MiaoshaGoods;
import org.apache.ibatis.annotations.Param;
import java.util.List;
@ -10,9 +11,10 @@ import java.util.List;
*/
public interface GoodsMapper {
public List<GoodsVo> listGoodsVo();
public List<GoodsVoOrder> listGoodsVo();
public GoodsVo getGoodsVoByGoodsId(@Param("goodsId") long goodsId);
public GoodsVoOrder getGoodsVoByGoodsId(@Param("goodsId") long goodsId);
public int reduceStock(MiaoshaGoods g);
}

View File

@ -2,7 +2,7 @@
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.geekq.provider.mapper.GoodsMapper" >
<resultMap id="BaseResultMap" type="goodsVo" >
<resultMap id="BaseResultMap" type="goodsVoOrder" >
<id column="id" property="id" jdbcType="BIGINT" />
<result column="goods_name" property="goodsName" jdbcType="VARCHAR" />
<result column="goods_title" property="goodsTitle" jdbcType="VARCHAR" />
@ -32,4 +32,8 @@
WHERE miaosha_goods.goods_id = #{goodsId,jdbcType=BIGINT}
</select>
<update id="reduceStock" >
update miaosha_goods set stock_count = stock_count - 1
where goods_id = #{goodsId} and stock_count > 0
</update>
</mapper>

View File

@ -1,20 +0,0 @@
package com.geekq.provider.service.impl;
import com.alibaba.dubbo.config.annotation.Service;
import com.geekq.api.service.DemoService;
/**
* DemoServiceImpl
* 服务提供类
* @author geekq
* @date 2018/6/7
*/
@Service(version = "${demo.service.version}")
public class DemoServiceImpl implements DemoService {
@Override
public String sayHello(String name) {
System.out.println("2321121212312312");
return "Hello, " + name + " (from Spring Boot)";
}
}

View File

@ -0,0 +1,33 @@
package com.geekq.provider.service.impl;
import com.geekq.api.entity.GoodsVoOrder;
import com.geekq.api.service.GoodsService;
import com.geekq.api.utils.ResultGeekQOrder;
import org.springframework.stereotype.Service;
import java.util.List;
/**
* @author 邱润泽
*/
@Service("goodGroupService")
public class GoodsGroupServiceImpl implements GoodsService {
@Override
public ResultGeekQOrder<List<GoodsVoOrder>> listGoodsVo() {
System.out.println("测试 group!");
return null;
}
@Override
public ResultGeekQOrder<GoodsVoOrder> getGoodsVoByGoodsId(long goodsId) {
System.out.println("测试 group!");
return null;
}
@Override
public boolean reduceStock(GoodsVoOrder goods) {
System.out.println("测试 group!");
return false;
}
}

View File

@ -1,33 +1,64 @@
package com.geekq.provider.service.impl;
import com.alibaba.dubbo.config.annotation.Service;
import com.geekq.api.entity.GoodsVo;
import com.geekq.api.entity.GoodsVoOrder;
import com.geekq.api.entity.MiaoshaGoods;
import com.geekq.api.service.GoodsService;
import com.geekq.common.enums.ResultStatus;
import com.geekq.common.utils.resultbean.ResultGeekQ;
import com.geekq.api.utils.ResultGeekQOrder;
import com.geekq.api.utils.ResultStatusOrder;
import com.geekq.provider.mapper.GoodsMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
/**
* @author 邱润泽
*/
@Service(version = "${demo.service.version}")
@Service("goodsService")
public class GoodsServiceImpl implements GoodsService {
private static Logger logger = LoggerFactory.getLogger(GoodsServiceImpl.class);
@Autowired
GoodsMapper goodsMapper;
@Override
public ResultGeekQ<List<GoodsVo>> listGoodsVo() {
ResultGeekQ resultGeekQ = ResultGeekQ.build();
public ResultGeekQOrder<List<GoodsVoOrder>> listGoodsVo() {
ResultGeekQOrder<List<GoodsVoOrder>> resultGeekQ = ResultGeekQOrder.build();
try {
resultGeekQ.setData(goodsMapper.listGoodsVo());
} catch (Exception e) {
resultGeekQ.withError(ResultStatus.SYSTEM_ERROR);
logger.error("获取订单数据失败!",e);
resultGeekQ.withError(ResultStatusOrder.ORDER_GET_FAIL);
}
return resultGeekQ;
}
@Override
public ResultGeekQOrder<GoodsVoOrder> getGoodsVoByGoodsId(long goodsId) {
ResultGeekQOrder<GoodsVoOrder> resultGeekQ = ResultGeekQOrder.build();
try {
GoodsVoOrder goodsVoOrder = goodsMapper.getGoodsVoByGoodsId(goodsId);
resultGeekQ.setData(goodsVoOrder);
} catch (Exception e) {
logger.error("获取单个订单失败!",e);
resultGeekQ.withError(ResultStatusOrder.ORDER_GET_FAIL);
}
return resultGeekQ;
}
@Override
public boolean reduceStock(GoodsVoOrder goods) {
MiaoshaGoods g = new MiaoshaGoods();
g.setGoodsId(goods.getId());
int ret = goodsMapper.reduceStock(g);
return ret > 0;
}
}

View File

@ -1,16 +1,12 @@
spring.application.name = miaosha-order-provider
server.port = 9090
#spring.application.name = miaosha-order-provider
#server.port = 9090
#dubbo.application.name = miaosha-order-provider
#demo.service.version = 1.0.0
#dubbo.protocol.name = dubbo
#dubbo.protocol.port = 20880
#dubbo.registry.address = zookeeper://localhost:2181
#dubbo.provider.timeout = 1000
dubbo.application.name = miaosha-order-provider
demo.service.version = 1.0.0
dubbo.protocol.name = dubbo
dubbo.protocol.port = 20880
dubbo.registry.address = zookeeper://localhost:2181
dubbo.provider.timeout = 1000
mybatis.type-aliases-package=com.geekq.api.entity
@ -33,4 +29,6 @@ spring.datasource.testWhileIdle=true
spring.datasource.testOnBorrow=false
spring.datasource.testOnReturn=false
spring.datasource.poolPreparedStatements=true
spring.datasource.maxOpenPreparedStatements=20
spring.datasource.maxOpenPreparedStatements=20
server.port = 9090

View File

@ -0,0 +1,26 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd
http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd">
<!-- 为当前服务提供者取个名字,并且提供给注册中心 -->
<dubbo:application name="miaosha-order-service"></dubbo:application>
<!-- 注册中心的配置使用zk暴露服务 -->
<dubbo:registry protocol="zookeeper" address="localhost:2181"></dubbo:registry>
<!-- 定义暴露服务的端口号 -->
<dubbo:protocol name="dubbo" port="20880" ></dubbo:protocol>
<!-- 暴露具体的服务接口 本地伪装-->
<dubbo:service retries="3" interface="com.geekq.api.service.GoodsService"
ref="goodsService" group="goods2" timeout="6000" mock="true">
<dubbo:method name="listGoodsVo" timeout="3000" ></dubbo:method>
</dubbo:service>
<dubbo:service interface="com.geekq.api.service.GoodsService" ref="goodGroupService" group="goods1"></dubbo:service>
</beans>

View File

@ -47,17 +47,18 @@
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>${org.mybatis.version}</version>
</dependency>
<dependency>
<groupId>com.geekq</groupId>
<artifactId>miaosha-common</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<!--<dependency>-->
<!--<groupId>com.geekq</groupId>-->
<!--<artifactId>miaosha-common</artifactId>-->
<!--<version>0.0.1-SNAPSHOT</version>-->
<!--</dependency>-->
<dependency>
<groupId>com.alibaba.boot</groupId>