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

来源:互联网 发布:cnc编程软件mastercam 编辑:程序博客网 时间:2024/06/06 01:21

原文地址: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:2314  */15 public class BigWheelDrawUtil {16 17 18     /**19      * 给转盘的每个角度赋初始值20      * @return21      */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      * @return34      */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.

 

复制代码
好文要顶 关注我 收藏该文

0 0
原创粉丝点击