本文是针对jquery 实现抽奖转盘作者的一个补充(主要用java去实现转盘结果生成及存储,解决jquery 做法 非法用户采用模拟器实现改变转盘值的风险性),针对jQuery的具体实现,请看案例:http://www.cnblogs.com/mofish/archive/2013/01/24/2875516.html              本文就不一一细说了,那么现在就直入正题。

由于公司产品推广,最近要求实现一个邀请用户注册即可抽奖的转盘,页面展示如下:

java 实现方式如下:

构造实体类

WchatLotteryDomain.java

 package com.cy.dcts.domain.activity;

 import java.io.Serializable;

 /**
* 微信用户分享中奖基础数据类
* @author yanst 2016/4/23 9:36
*/
public class WchatLotteryDomain implements Serializable{
private static final long serialVersionUID = -1595371216905016135L; private Integer id; //中奖金额
private String prize; //中奖率
private Integer v; public WchatLotteryDomain(Integer id, String prize, Integer v){
this.id = id;
this.prize = prize;
this.v = v;
} public Integer getId() {
return id;
} public void setId(Integer id) {
this.id = id;
} public String getPrize() {
return prize;
} public void setPrize(String prize) {
this.prize = prize;
} public Integer getV() {
return v;
} public void setV(Integer v) {
this.v = v;
}
}

抽奖算法实现类:  

1.初始数据集合:initDrawList  。

  2.generateAward方法实现根据概率随机生成中奖对象WchatLotteryDomain 

BigWheelDrawUtil.java

 package com.cy.dcts.common.util;

 import com.alibaba.fastjson.JSON;
import com.cy.dcts.domain.activity.WchatLotteryDomain; import java.util.ArrayList;
import java.util.List; /**
*
* wchat大转盘抽奖活动
*
* @author yanst 2016/4/23 9:23
*/
public class BigWheelDrawUtil { /**
* 给转盘的每个角度赋初始值
* @return
*/
private final static List<WchatLotteryDomain> initDrawList = new ArrayList<WchatLotteryDomain>() {{
add(new WchatLotteryDomain(1, "200", 1));
add(new WchatLotteryDomain(2, "100", 3));
add(new WchatLotteryDomain(3, "50", 30));
add(new WchatLotteryDomain(4, "30", 30));
add(new WchatLotteryDomain(5, "20", 26));
add(new WchatLotteryDomain(6, "10", 10));
}}; /**
* 生成奖项
* @return
*/
public static WchatLotteryDomain generateAward() {
List<WchatLotteryDomain> initData = initDrawList;
long result = randomnum(1, 100);
int line = 0;
int temp = 0;
WchatLotteryDomain returnobj = null;
int index = 0;
for (int i = 0; i < initDrawList.size(); i++) {
WchatLotteryDomain obj2 = initDrawList.get(i);
int c = obj2.getV();
temp = temp + c;
line = 100 - temp;
if (c != 0) {
if (result > line && result <= (line + c)) {
returnobj = obj2;
break;
}
}
}
return returnobj;
} // 获取2个值之间的随机数
private static long randomnum(int smin, int smax){
int range = smax - smin;
double rand = Math.random();
return (smin + Math.round(rand * range));
} public static void main(String[] args) {
System.out.println(JSON.toJSONString(generateAward()));
} }

controller 层 实现 显示抽奖的结果给页面,页面启动转盘,把对应的中间角度显示给用户看,同时把中间金额保存到系统中。

1.调用util类返回中奖项

 //生成中奖金额对象
WchatLotteryDomain wchatLotteryDomain = BigWheelDrawUtil.generateAward();

2.修改抽奖次数

//修改抽奖次数
Integer result = appShareService.markLuckDraw(id);

3.把中奖信息持久化

//写入中奖信息
writeXinRecord(mobile, wchatLotteryDomain);

4.把当前中奖信息及剩余中奖次数返回

//代码略,参考ActivityAction.java  107、108行

ActivityAction.java

  /**
* 抽奖
*
* @param id id
* @param mobile 中奖号码
* @return
*/
@RequestMapping("wXinMarkLuckDraw.jspx")
@ResponseBody
public JSonRespone markLuckDraw(Long id, String mobile) {
//参数验证
if (id == null || id.longValue() == 0) {
return JSonRespone.makeHasContentJSonRespone("1", "您没有抽奖次数!");
}
//参数验证
if (StringUtils.isEmpty(mobile)) {
return JSonRespone.makeHasContentJSonRespone("1", "中奖手机号码为空!");
} //生成中奖金额对象
WchatLotteryDomain wchatLotteryDomain = BigWheelDrawUtil.generateAward();
if(wchatLotteryDomain == null){
return JSonRespone.makeHasContentJSonRespone("3", "生成抽奖数据失败");
}
try {
//修改抽奖次数
Integer result = appShareService.markLuckDraw(id);
if (result == null || result == 0) {
return JSonRespone.makeHasContentJSonRespone("2", "抽奖失败,请刷新重新验证。");
}
} catch (Exception e) {
logger.debug(e.getMessage());
return JSonRespone.makeHasContentJSonRespone("2", "抽奖失败,请刷新重新验证。");
} if(logger.isErrorEnabled()){
logger.error("微信分享活动:手机号码为:{},中奖信息:{}", mobile, JSON.toJSONString(wchatLotteryDomain));
} //写入中间信息
return writeXinRecord(mobile, wchatLotteryDomain);
} // 微信 用户分享 认证之后送话费活动 中奖记录存储路径
private static final String wXinFilePath = "/home/wxhb/lottery.txt";
//"/home/wxhb/lottery.txt";
//"D:/list.txt"; /**
* 写入中奖金额
* @param mobile
* @param wchatLotteryDomain
* @return
*/
private JSonRespone writeXinRecord(String mobile,WchatLotteryDomain wchatLotteryDomain ) {
// 记录时间
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
Calendar calendar = Calendar.getInstance();
String date = simpleDateFormat.format(calendar.getTime());
// 记录文件是否存在
File file = new File(wXinFilePath);
if (!file.exists()) {
try {
file.createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
}
// 临时记录存储
ArrayList<String> arrayList = new ArrayList<>();
// 是否已经存在记录
Scanner in = null;
try {
in = new Scanner(file);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
// 读取记录放置临时数组
while (in.hasNextLine()) {
arrayList.add(in.nextLine());
}
in.close();
// 查询记录是否存在
if (arrayList.size() > 0) {
for (String str : arrayList) {
if (mobile.equals(str.split("-")[0])) {
return JSonRespone.makeHasContentJSonRespone("1", "成功", "记录已存在");
}
}
}
// 写入记录
BufferedWriter out = null;
try {
out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file, true)));
out.write(mobile + " " + date + " " + wchatLotteryDomain.getPrize());
out.newLine();
out.close();
} catch (IOException e) {
e.printStackTrace();
return JSonRespone.makeHasContentJSonRespone("0", "失败", e.getMessage());
} Map<String, Object> resultMap = new HashMap<String, Object>();
try {
//获取抽奖次数
resultMap.put("luckDrawCounts", appShareService.getLuckDrawCounts(mobile));//抽奖次数
resultMap.put("wchatLotteryDomain", wchatLotteryDomain);
} catch (Exception e) {
logger.debug(e.getMessage());
}
return JSonRespone.makeHasContentJSonRespone("0", "成功", resultMap);
}

抽奖页面代码:

这里省略大转盘样式代码,详细参考:http://www.cnblogs.com/mofish/archive/2013/01/24/2875516.html

点击抽奖按钮 最先执行lottery.html 98行代码   ,页面入口已经告诉大家,剩余请大家往下看应该就明白了。

lottery.html

 <!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>xxx</title>
<meta content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=0" name="viewport"/>
<link rel="stylesheet" type="text/css" href="css/app.css"/>
</head>
<body>
<div class="page">
<div id="verify-section">
<img src="img/1.png" width="750" height="654">
<div class="field lottery">
<h2>输入您的手机号码,查看您的可抽奖次数。</h2>
<p>
<input type="tel" id="mobile" class="mobile" placeholder="请输入你的手机号码" maxlength="11"/>
</p>
<p>
<input type="text" id="code" placeholder="验证码" maxlength="6"/>
<button id="btn-code" class="btn">获取验证码</button>
</p>
<h2 class="error">手机号码格式不正确</h2>
<p>
<button id="btn-verify" class="btn">提交</button>
</p>
</div>
</div>
<div id="lottery-section" class="field lottery">
<h2>您的可抽奖次数为:_<span class="lucktime"></span>_次</h2>
<p>
<button id="btn-list" class="btn">查看好友认证的情况</button>
</p> <p>
<label for="mobile-check">请核对您的充值号码:</label>
<input type="tel" id="mobile-check" placeholder="请输入要充值的手机号" maxlength="11"/>
<p id="submit-check" style="display: none;">充值号码格式不正确 </p>
</p> <div class="ly-plate">
<div class="m-rotate"></div>
<div class="m-pointer"></div>
</div>
<p class="lottery-msg"></p> <h2 class="submit-msg" style="display: none;">话费将在1个工作日内充值,请注意查收。</h2>
<p class="share-more">
<button id="btn-share-more" class="btn">话费还有好多,我要继续推荐</button>
</p>
</div>
<div id="overlay">
<div class="verify-list">
<a href="#" onclick="$('#overlay').hide();"></a>
<ul class="list">
</ul>
</div>
</div>
</div>
</body>
<script src="js/jquery.min.js" type="text/javascript" charset="utf-8"></script>
<script src="js/pageResponse.min.js" type="text/javascript" charset="utf-8"></script>
<script type="text/javascript" src="js/Rotate.js"></script>
<script type="text/javascript" src="js/app.js" charset="utf-8"></script>
<script type="text/javascript">
$(function () {
// $("#lottery-section").show();
$("#btn-list").click(function () {
$("#overlay").show();
});
$("#btn-share-more").click(function(){
window.location = "index.html";
});
pageResponse({
selectors: 'div.page',
mode: 'auto', // auto || contain || cover ,默认模式为auto
width: '750', //输入页面的宽度,只支持输入数值,默认宽度为320px
height: '654'
}); //启动转盘
var rotateFunc = function (angle, prize, luckDrawCounts) { //angle: 奖项对应的角度 prize:中奖金额 luckDrawCounts:抽奖次数
$('.m-rotate').stopRotate();
$('.m-rotate').rotate({
angle: 0,
duration: 5000,
animateTo: angle + 1440, //angle是图片上各奖项对应的角度,1440是我要让指针旋转4圈。所以最后的结束的角度就是这样子^^
callback: function () {
//更改抽奖次数
$(".submit-msg").show();
$(".lucktime").html(luckDrawCounts);
isLottery = false;
$(".lottery-msg").html('您抽中了' + prize + '元手机话费,恭喜您。').css("color", "#fff");
}
});
}; $(".m-pointer").rotate({
bind: {
click: function () {
$("#submit-check").hide();
//判断充值号码
if (!verifyPhoneNumber($("#mobile-check").val())) {
$("#submit-check").css("color", "red").show();
return false;
} if (luckDrawCounts != 0 && isLottery == false) {
var ajaxTimeoutTest = $.ajax({
url: "/activity/wXinMarkLuckDraw.jspx",
data: {"id": listIds[0], "mobile": $("#mobile-check").val()},
type: "POST",
// timeout : 5000, //超时时间设置,单位毫秒
success: function (rs) {
if (rs.result == "0") {
//生成中奖数据
var data = rs.content.wchatLotteryDomain;
//抽奖剩余次数
var luckDrawCounts = rs.content.luckDrawCounts;
if (data.id == 1) {
rotateFunc(360, data.prize, luckDrawCounts);
}
if (data.id == 2) {
rotateFunc(300, data.prize, luckDrawCounts);
}
if (data.id == 3) {
rotateFunc(240, data.prize, luckDrawCounts);
}
if (data.id == 4) {
rotateFunc(180, data.prize, luckDrawCounts);
}
if (data.id == 5) {
rotateFunc(120, data.prize, luckDrawCounts);
}
if (data.id == 6) {
rotateFunc(60, data.prize, luckDrawCounts);
}
}else {
isLottery = false;
$(".lottery-msg").html(rs.errorMessage).css("color", "red");
}
}
// ,complete : function(XMLHttpRequest,status){ //请求完成后最终执行参数
// if(status=='timeout'){
// ajaxTimeoutTest.abort();
// isLottery = false;
// $(".lottery-msg").html("当前抽奖人数过多请稍后重试!").css("color", "red");
// }
// }
});
}else{
if (isLottery && luckDrawCounts > 0){
$(".lottery-msg").html('请提交后再重新抽奖').css("color", "red");
}else{
$(".lottery-msg").html('对不起你的抽奖机会用完了').css("color", "red");
}
}
}
}
});
});
</script>
</html>

为了体验性,我这里的所有请求都是采用Ajax请求。

Java实现抽奖转盘 示例到这里就结束了,比较简单大家一看应该就明白了。这里也想补充说明下:

1.在考虑安全的情况下,抽奖算法实现,最好写在后台,因为这样中奖金额直接在后台去持久化了,无需经过页面传输,页面只是做了单纯的展示,一些非法操作,是没有办法通过改变中奖金额,去刷我们的中奖金额。

举例:如某个用户抽奖中了200元话费,我这里接口入参只需要告诉我 id 和 mobile ,并没有传中奖金额,这里前端就没有办法非法改变中奖金额了。

2.考虑如果用户点击抽奖按钮,但此时由于比较卡(可能受网络限制,请求很慢等等原因)造成用户点击了但是已经离开当前页面了,此时用户应该算已经抽奖了。这时我每次请求都去检查了抽奖次数估,也不会出现重复提交问题。

//修改抽奖次数
Integer result = appShareService.markLuckDraw(id);

if (result == null || result == 0) {
     return JSonRespone.makeHasContentJSonRespone("2", "抽奖失败,请刷新重新验证。");
  }

第一次写博客,请的不好请大家见谅。

有需要源码的朋友可以留言,后续有空我会把项目中的代码整理成单独demo.

利用java实现抽奖转盘(着重安全控制)的更多相关文章

  1. 利用canvas实现抽奖转盘---转载别人的

    功能需求 转盘要美观,转动效果流畅. 转盘上需要显示奖品图片,并且奖品是后台读取的照片和名字. 转动动画完成后要有相应提示. 获取的奖品具体算法在数据库里操作,前端只提供最后的效果展示.   知识要点 ...

  2. Android实现抽奖转盘

    一.SurfaceView认识及的应用的思路 SurfaceView继承自(extends)View,View是在UI线程中进行绘制: 而SurfaceView是在一个子线程中对自己进行绘制,优势:避 ...

  3. css 如何“画”一个抽奖转盘

    主要描述的是如何运用 css 绘制一个抽奖转盘,并运用原生 js 实现转盘抽奖效果. 先来张效果图: 布局 一般来说,转盘一般有四个部分组成:外层闪烁的灯.内层旋转的圆盘.圆盘上的中奖结果.指针. 所 ...

  4. 利用Java的反射与代理机制实现AOP

    在上一篇文章中,我们讲述了利用Java的反射机制中实现Spring中的IOC,在本文中,我们将更进一步,讲述用Java的反射和动态代理机制来实现Spring的AOP. 一.AOP概述 AOP(Aspe ...

  5. Java实现抽奖模块的相关分享

    Java实现抽奖模块的相关分享 最近进行的项目中,有个抽奖的需求,今天就把相关代码给大家分享一下. 一.DAO层 /** * 获取奖品列表 * @param systemVersion 手机系统版本( ...

  6. 利用Java动态生成 PDF 文档

    利用Java动态生成 PDF 文档,则需要开源的API.首先我们先想象需求,在企业应用中,客户会提出一些复杂的需求,比如会针对具体的业务,构建比较典型的具备文档性质的内容,一般会导出PDF进行存档.那 ...

  7. 利用Java代码在某些时刻创建Spring上下文

    上一篇中,描述了如何使用Spring隐式的创建bean,但当我们需要引进第三方类库添加到我们的逻辑上时,@Conponent与@Autowired是无法添加到类上的,这时,自动装配便不适用了,我们需要 ...

  8. 利用JAVA生成二维码

    本文章整理于慕课网的学习视频<JAVA生成二维码>,如果想看视频内容请移步慕课网. 维基百科上对于二维码的解释. 二维条码是指在一维条码的基础上扩展出另一维具有可读性的条码,使用黑白矩形图 ...

  9. 利用Java进行MySql数据库的导入和导出

    利用Java来进行Mysql数据库的导入和导出的总体思想是通过Java来调用命令窗口执行相应的命令. MySql导出数据库的命令如下: mysqldump -uusername -ppassword  ...

随机推荐

  1. fastcgi重启

    重启nginx和php-cgi 的命令 nginx: sudo /etc/init.d/nginx restart 同样也可以有start,stop等参数php-cgi: 先杀死进程sudo kill ...

  2. 企业架构研究总结(40)——TOGAF架构能力框架之架构合同、成熟度模型和架构技能框架

    5. 架构合同 架构合同是在开发团体和赞助者之间关于架构的交付物.质量以及适用目标的联合协议,并且通过有效的架构治理将会促使这些协议的成功施行.通过对合同的管理施行一个治理方法,如下几点将会得到保障: ...

  3. 企业架构研究总结(38)——TOGAF架构能力框架之架构能力建设和架构治理

    为了确保架构功能在企业中能够被成功地运用,企业需要通过建立适当的组织结构.流程.角色.责任和技能来实现其自身的企业架构能力,而这也正是TOGAF的架构能力框架(Architecture Capabil ...

  4. 通过DialogFragment从DatePicker或TimePicker中获取日期数据

    通过DialogFragment从DatePicker或TimePicker中获取日期数据 一个activity类,里面存有date和time的变量,想通过dialogfragment的方式获取用户输 ...

  5. tomcat配置数据池

    1->配置servlet.xml 在 <GlobalNamingResources></GlobalNamingResources>中添加<Resource> ...

  6. LigerUI权限系统之组织结构

    先上图,再看代码.组织结构界面 组织结构添加: 组织结构修改: 组织结构删除: 我在做这个页面的时候treegrid 的远程数据加载让我很头痛,从LigerUI官网提供的Demo来看,它是根据json ...

  7. JavaEE:Tomcat服务器常用配置和HTTP简介

    Web服务器常用配置1.Web系统采用B/S结构通信的:Browser --- Server1)浏览器向服务器发送访问目标资源请求(请求)2)服务器根据请求的目标资源路径,在服务器端进行查找(请求查找 ...

  8. php三中页面跳转方式(header、location、refresh) 乐杨俊

    反法三:也是用的比较多的

  9. Android Phone和Pad UA区别

    很多Android开发者或者网站端都可能会困扰关于如何区分Android phone和Android Pad的ua.确实这个问题很困难,我也曾被困扰了一段时间,后来在Stackoverflow中发现了 ...

  10. web打印小结

    项目中有个需求是将winform客户端的打印,移到网页上由客户自行打印,打印要求是根据一定的格式实现套打. 当时的解决方案是使用PDF打印: 1. 准备好套打格式的底图: 2.打开底图,将动态内容画到 ...