一个模拟秒杀的页面
失败情况:
成功情况:
页面代码:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<%
String basePath = request.getScheme()
+ "://"
+ request.getServerName()
+ ":"
+ request.getServerPort()
+ request.getContextPath()
+ "/";
pageContext.setAttribute("basePath",basePath);
%>
<base href="<%=basePath%>"/>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<script type="text/javascript" src="jquery/jquery-3.1.0.js"></script>
<script type="text/javascript">
$(function () {
$("#btn_ms").click(function () {
$.getJSON("${pageScope.basePath}SecKillServlet", "action=dosecKill&prodid=0101", function (data) {
if (data.isSuccess) {
alert("抢购成功");
}
else{
alert("抢购失败");
$("#btn_ms").attr("disabled", true);
}
});
});
})
</script>
<head>
<title>秒杀界面</title>
</head>
<body>
<h1 >商品秒杀</h1>
<input type="hidden" name="action" value="dosecKill"/>--%>
<input align="center" type="button" id="btn_ms" name="btn_seckillms" value="点击秒杀"/>
</body>
</html>
redis连接池设置:
public class JedisPoolUtil {
private static volatile JedisPool jedisPool = null;
private JedisPoolUtil() {
}
public static JedisPool getJedisPoolInstance() {
if (null == jedisPool) {
synchronized (JedisPoolUtil.class) {
if (null == jedisPool) {
JedisPoolConfig poolConfig = new JedisPoolConfig();
poolConfig.setMaxTotal(200);
poolConfig.setMaxIdle(32);
poolConfig.setMaxWaitMillis(10000);
poolConfig.setBlockWhenExhausted(true);
poolConfig.setTestOnBorrow(true); // ping PONG
jedisPool = new JedisPool(poolConfig, "192.168.233.128", 6379, 60000,"password" );
}
}
}
return jedisPool;
}
}
这里使用懒汉式单例模式是,保证线程安全,仅构造一个连接池
service层调用lua脚本,解决库存遗留问题
public class SecKillService {
private static final org.slf4j.Logger logger =LoggerFactory.getLogger(SecKillService.class) ;
static String secKillScript ="local userid=KEYS[1];\r\n" +
"local prodid=KEYS[2];\r\n" +
"local qtkey='sk:'..prodid..\":qt\";\r\n" +
"local usersKey='sk:'..prodid..\":usr\";\r\n" +
"local userExists=redis.call(\"sismember\",usersKey,userid);\r\n" +
"if tonumber(userExists)==1 then \r\n" +
" return 2;\r\n" +
"end\r\n" +
"local num= redis.call(\"get\" ,qtkey);\r\n" +
"if tonumber(num)<=0 then \r\n" +
" return 0;\r\n" +
"else \r\n" +
" redis.call(\"decr\",qtkey);\r\n" +
" redis.call(\"sadd\",usersKey,userid);\r\n" +
"end\r\n" +
"return 1" ;
static String secKillScript2 =
"local userExists=redis.call(\"sismember\",\"{sk}:0101:usr\",userid);\r\n" +
" return 1";
public static boolean doSeckill(String uid, String prodid) {
JedisPool jedisPool = JedisPoolUtil.getJedisPoolInstance();
Jedis jedis = jedisPool.getResource();
String sha1 = jedis.scriptLoad(secKillScript);
Object result = jedis.evalsha(sha1, 2, uid, prodid);
String reString = String.valueOf(result);
if ("0".equals(reString)) {
System.out.println("已抢空");
jedis.close();
return false;
} else if ("1".equals(reString)) {
System.out.println("抢购成功");
jedis.close();
return true;
} else if ("2".equals(reString)) {
System.out.println("该用户已抢过");
jedis.close();
return false;
} else {
System.out.println("抢购异常");
jedis.close();
return false;
}
}
}
web层使用反射调用需要调用的方法
public class BaseServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doPost(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.setCharacterEncoding("UTF-8");
resp.setContentType("text/html; charset=UTF-8");
String action = req.getParameter("action");
try{
Method method = this.getClass().getDeclaredMethod(action,HttpServletRequest.class,HttpServletResponse.class);
method.invoke(this,req,resp);
}catch(Exception e){
e.printStackTrace();
}
}
}
真正需要被调用的方法:
public class SecKillServlet extends BaseServlet {
private static final long serialVersionUID = 1L;
public void dosecKill(HttpServletRequest req, HttpServletResponse resp) throws IOException {
String userid = new Random().nextInt(50000) + "";
String prodid = req.getParameter("prodid");
boolean isSuccess = false;
// try {
isSuccess = SecKillService.doSeckill(userid, prodid);
// }catch(Exception e){
// }
Map<String,Object> resultMap = new HashMap();
resultMap.put("isSuccess",isSuccess);
Gson gson = new Gson();
String json = gson.toJson(resultMap);
resp.getWriter().write(json);
}
}
使用ajax处理请求,免去页面刷新