您的位置:首页 > 编程语言 > Java开发

利用java实现抽奖转盘(着重安全控制)

2017-04-25 11:55 513 查看
原文地址:http://www.cnblogs.com/styan/p/5426148.html

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

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

 



 

java 实现方式如下:

构造实体类

WchatLotteryDomain.java

1 package com.cy.dcts.domain.activity;
2
3 import java.io.Serializable;
4
5 /**
6 * 微信用户分享中奖基础数据类
7 * @author yanst 2016/4/23 9:36
8 */
9 public class WchatLotteryDomain implements Serializable{
10 private static final long serialVersionUID = -1595371216905016135L;
11
12 private Integer id;
13
14 //中奖金额
15 private String prize;
16
17 //中奖率
18 private Integer v;
19
20 public WchatLotteryDomain(Integer id, String prize, Integer v){
21 this.id = id;
22 this.prize = prize;
23 this.v = v;
24 }
25
26 public Integer getId() {
27 return id;
28 }
29
30 public void setId(Integer id) {
31 this.id = id;
32 }
33
34 public String getPrize() {
35 return prize;
36 }
37
38 public void setPrize(String prize) {
39 this.prize = prize;
40 }
41
42 public Integer getV() {
43 return v;
44 }
45
46 public void setV(Integer v) {
47 this.v = v;
48 }
49 }


 

 

抽奖算法实现类:  

     1.初始数据集合:initDrawList  。

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

BigWheelDrawUtil.java

1 package com.cy.dcts.common.util;
2
3 import com.alibaba.fastjson.JSON;
4 import com.cy.dcts.domain.activity.WchatLotteryDomain;
5
6 import java.util.ArrayList;
7 import java.util.List;
8
9 /**
10  *
11  * wchat大转盘抽奖活动
12  *
13  * @author yanst 2016/4/23 9:23
14  */
15 public class BigWheelDrawUtil {
16
17
18     /**
19      * 给转盘的每个角度赋初始值
20      * @return
21      */
22     private final static List<WchatLotteryDomain> initDrawList = new ArrayList<WchatLotteryDomain>() {{
23         add(new WchatLotteryDomain(1, "200", 1));
24         add(new WchatLotteryDomain(2, "100", 3));
25         add(new WchatLotteryDomain(3, "50", 30));
26         add(new WchatLotteryDomain(4, "30", 30));
27         add(new WchatLotteryDomain(5, "20", 26));
28         add(new WchatLotteryDomain(6, "10", 10));
29     }};
30
31     /**
32      * 生成奖项
33      * @return
34      */
35     public static WchatLotteryDomain generateAward() {
36         List<WchatLotteryDomain> initData = initDrawList;
37         long result = randomnum(1, 100);
38         int line = 0;
39         int temp = 0;
40         WchatLotteryDomain returnobj = null;
41         int index = 0;
42         for (int i = 0; i < initDrawList.size(); i++) {
43             WchatLotteryDomain obj2 = initDrawList.get(i);
44             int c = obj2.getV();
45             temp = temp + c;
46             line = 100 - temp;
47             if (c != 0) {
48                 if (result > line && result <= (line + c)) {
49                     returnobj = obj2;
50                     break;
51                 }
52             }
53         }
54         return returnobj;
55     }
56
57     // 获取2个值之间的随机数
58     private static long randomnum(int smin, int smax){
59             int range = smax - smin;
60             double rand = Math.random();
61             return (smin + Math.round(rand * range));
62     }
63
64
65     public static void main(String[] args) {
66         System.out.println(JSON.toJSONString(generateAward()));
67     }
68
69 }


 

 

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

1.调用util类返回中奖项

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


2.修改抽奖次数 

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


3.把中奖信息持久化

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


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

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

ActivityAction.java

1  /**
2      * 抽奖
3      *
4      * @param id id
5      * @param mobile    中奖号码
6      * @return
7      */
8     @RequestMapping("wXinMarkLuckDraw.jspx")
9     @ResponseBody
10     public JSonRespone markLuckDraw(Long id, String mobile) {
11         //参数验证
12         if (id == null || id.longValue() == 0) {
13             return JSonRespone.makeHasContentJSonRespone("1", "您没有抽奖次数!");
14         }
15         //参数验证
16         if (StringUtils.isEmpty(mobile)) {
17             return JSonRespone.makeHasContentJSonRespone("1", "中奖手机号码为空!");
18         }
19
20         //生成中奖金额对象
21         WchatLotteryDomain wchatLotteryDomain = BigWheelDrawUtil.generateAward();
22         if(wchatLotteryDomain == null){
23             return JSonRespone.makeHasContentJSonRespone("3", "生成抽奖数据失败");
24         }
25         try {
26             //修改抽奖次数
27             Integer result = appShareService.markLuckDraw(id);
28             if (result == null || result == 0) {
29                 return JSonRespone.makeHasContentJSonRespone("2", "抽奖失败,请刷新重新验证。");
30             }
31         } catch (Exception e) {
32             logger.debug(e.getMessage());
33             return JSonRespone.makeHasContentJSonRespone("2", "抽奖失败,请刷新重新验证。");
34         }
35
36         if(logger.isErrorEnabled()){
37             logger.error("微信分享活动:手机号码为:{},中奖信息:{}", mobile, JSON.toJSONString(wchatLotteryDomain));
38         }
39
40         //写入中间信息
41         return writeXinRecord(mobile, wchatLotteryDomain);
42     }
43
44     //    微信 用户分享 认证之后送话费活动 中奖记录存储路径
45     private static final String wXinFilePath =  "/home/wxhb/lottery.txt";
46     //"/home/wxhb/lottery.txt";
47     //"D:/list.txt";
48
49
50     /**
51      * 写入中奖金额
52      * @param mobile
53      * @param wchatLotteryDomain
54      * @return
55      */
56     private JSonRespone writeXinRecord(String mobile,WchatLotteryDomain wchatLotteryDomain ) {
57         // 记录时间
58         SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
59         Calendar calendar = Calendar.getInstance();
60         String date = simpleDateFormat.format(calendar.getTime());
61         // 记录文件是否存在
62         File file = new File(wXinFilePath);
63         if (!file.exists()) {
64             try {
65                 file.createNewFile();
66             } catch (IOException e) {
67                 e.printStackTrace();
68             }
69         }
70         // 临时记录存储
71         ArrayList<String> arrayList = new ArrayList<>();
72         // 是否已经存在记录
73         Scanner in = null;
74         try {
75             in = new Scanner(file);
76         } catch (FileNotFoundException e) {
77             e.printStackTrace();
78         }
79         // 读取记录放置临时数组
80         while (in.hasNextLine()) {
81             arrayList.add(in.nextLine());
82         }
83         in.close();
84         // 查询记录是否存在
85         if (arrayList.size() > 0) {
86             for (String str : arrayList) {
87                 if (mobile.equals(str.split("-")[0])) {
88                     return JSonRespone.makeHasContentJSonRespone("1", "成功", "记录已存在");
89                 }
90             }
91         }
92         // 写入记录
93         BufferedWriter out = null;
94         try {
95             out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file, true)));
96             out.write(mobile + "    " + date + "    " + wchatLotteryDomain.getPrize());
97             out.newLine();
98             out.close();
99         } catch (IOException e) {
100             e.printStackTrace();
101             return JSonRespone.makeHasContentJSonRespone("0", "失败", e.getMessage());
102         }
103
104         Map<String, Object> resultMap = new HashMap<String, Object>();
105         try {
106             //获取抽奖次数
107             resultMap.put("luckDrawCounts", appShareService.getLuckDrawCounts(mobile));//抽奖次数
108             resultMap.put("wchatLotteryDomain", wchatLotteryDomain);
109         } catch (Exception e) {
110             logger.debug(e.getMessage());
111         }
112         return JSonRespone.makeHasContentJSonRespone("0", "成功", resultMap);
113     }


 

抽奖页面代码:

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

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

lottery.html

1 <!DOCTYPE html>
2 <html lang="en">
3 <head>
4     <meta charset="UTF-8">
5     <title>xxx</title>
6     <meta content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=0" name="viewport"/>
7     <link rel="stylesheet" type="text/css" href="css/app.css"/>
8 </head>
9 <body>
10 <div class="page">
11     <div id="verify-section">
12         <img src="img/1.png" width="750" height="654">
13         <div class="field lottery">
14             <h2>输入您的手机号码,查看您的可抽奖次数。</h2>
15             <p>
16                 <input type="tel" id="mobile" class="mobile" placeholder="请输入你的手机号码" maxlength="11"/>
17             </p>
18             <p>
19                 <input type="text" id="code" placeholder="验证码" maxlength="6"/>
20                 <button id="btn-code" class="btn">获取验证码</button>
21             </p>
22             <h2 class="error">手机号码格式不正确</h2>
23             <p>
24                 <button id="btn-verify" class="btn">提交</button>
25             </p>
26         </div>
27     </div>
28     <div id="lottery-section" class="field lottery">
29         <h2>您的可抽奖次数为:_<span class="lucktime"></span>_次</h2>
30         <p>
31             <button id="btn-list" class="btn">查看好友认证的情况</button>
32         </p>
33
34         <p>
35             <label for="mobile-check">请核对您的充值号码:</label>
36             <input type="tel" id="mobile-check" placeholder="请输入要充值的手机号" maxlength="11"/>
37             <p id="submit-check" style="display: none;">充值号码格式不正确 </p>
38         </p>
39
40         <div class="ly-plate">
41             <div class="m-rotate"></div>
42             <div class="m-pointer"></div>
43         </div>
44         <p class="lottery-msg"></p>
45
46         <h2 class="submit-msg" style="display: none;">话费将在1个工作日内充值,请注意查收。</h2>
47         <p class="share-more">
48             <button id="btn-share-more" class="btn">话费还有好多,我要继续推荐</button>
49         </p>
50     </div>
51     <div id="overlay">
52         <div class="verify-list">
53             <a href="#" onclick="$('#overlay').hide();"></a>
54             <ul class="list">
55             </ul>
56         </div>
57     </div>
58 </div>
59 </body>
60 <script src="js/jquery.min.js" type="text/javascript" charset="utf-8"></script>
61 <script src="js/pageResponse.min.js" type="text/javascript" charset="utf-8"></script>
62 <script type="text/javascript" src="js/Rotate.js"></script>
63 <script type="text/javascript" src="js/app.js" charset="utf-8"></script>
64 <script type="text/javascript">
65     $(function () {
66 //        $("#lottery-section").show();
67         $("#btn-list").click(function () {
68             $("#overlay").show();
69         });
70         $("#btn-share-more").click(function(){
71             window.location = "index.html";
72         });
73         pageResponse({
74             selectors: 'div.page',
75             mode: 'auto', // auto || contain || cover ,默认模式为auto
76             width: '750', //输入页面的宽度,只支持输入数值,默认宽度为320px
77             height: '654'
78         });
79
80         //启动转盘
81         var rotateFunc = function (angle, prize, luckDrawCounts) {  //angle: 奖项对应的角度 prize:中奖金额 luckDrawCounts:抽奖次数
82             $('.m-rotate').stopRotate();
83             $('.m-rotate').rotate({
84                 angle: 0,
85                 duration: 5000,
86                 animateTo: angle + 1440, //angle是图片上各奖项对应的角度,1440是我要让指针旋转4圈。所以最后的结束的角度就是这样子^^
87                 callback: function () {
88                     //更改抽奖次数
89                     $(".submit-msg").show();
90                     $(".lucktime").html(luckDrawCounts);
91                     isLottery = false;
92                     $(".lottery-msg").html('您抽中了' + prize + '元手机话费,恭喜您。').css("color", "#fff");
93                 }
94             });
95         };
96
97
98         $(".m-pointer").rotate({
99             bind: {
100                 click: function () {
101                     $("#submit-check").hide();
102                     //判断充值号码
103                     if (!verifyPhoneNumber($("#mobile-check").val())) {
104                         $("#submit-check").css("color", "red").show();
105                         return false;
106                     }
107
108                     if (luckDrawCounts != 0 && isLottery == false) {
109                         var ajaxTimeoutTest = $.ajax({
110                             url: "/activity/wXinMarkLuckDraw.jspx",
111                             data: {"id": listIds[0], "mobile": $("#mobile-check").val()},
112                             type: "POST",
113 //                            timeout : 5000, //超时时间设置,单位毫秒
114                             success: function (rs) {
115                                 if (rs.result == "0") {
116                                     //生成中奖数据
117                                     var data = rs.content.wchatLotteryDomain;
118                                     //抽奖剩余次数
119                                     var luckDrawCounts = rs.content.luckDrawCounts;
120                                     if (data.id == 1) {
121                                         rotateFunc(360, data.prize, luckDrawCounts);
122                                     }
123                                     if (data.id == 2) {
124                                         rotateFunc(300, data.prize, luckDrawCounts);
125                                     }
126                                     if (data.id == 3) {
127                                         rotateFunc(240, data.prize, luckDrawCounts);
128                                     }
129                                     if (data.id == 4) {
130                                         rotateFunc(180, data.prize, luckDrawCounts);
131                                     }
132                                     if (data.id == 5) {
133                                         rotateFunc(120, data.prize, luckDrawCounts);
134                                     }
135                                     if (data.id == 6) {
136                                         rotateFunc(60, data.prize, luckDrawCounts);
137                                     }
138                                 }else {
139                                     isLottery = false;
140                                     $(".lottery-msg").html(rs.errorMessage).css("color", "red");
141                                 }
142                             }
143 //                            ,complete : function(XMLHttpRequest,status){ //请求完成后最终执行参数
144 //                                if(status=='timeout'){
145 //                                    ajaxTimeoutTest.abort();
146 //                                    isLottery = false;
147 //                                    $(".lottery-msg").html("当前抽奖人数过多请稍后重试!").css("color", "red");
148 //                                }
149 //                            }
150                         });
151                     }else{
152                         if (isLottery && luckDrawCounts > 0){
153                             $(".lottery-msg").html('请提交后再重新抽奖').css("color", "red");
154                         }else{
155                             $(".lottery-msg").html('对不起你的抽奖机会用完了').css("color", "red");
156                         }
157                     }
158                 }
159             }
160         });
161     });
162 </script>
163 </html>


 

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

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

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

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

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

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

  if (result == null || result == 0) {

     return JSonRespone.makeHasContentJSonRespone("2", "抽奖失败,请刷新重新验证。");

  }

 

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

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

 

好文要顶
关注我 收藏该文



内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
相关文章推荐