
接着上一篇.上一篇还没有输出,其实加入了index在实体类中. package com.sha256.sha256.bean; import com.sha256.sha256.utils.SHA256Util; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; import java.util.Date; @Data @NoArgsConstructor @AllArgsConstructor public class Block { private long index; private String hash; // our signature private String previousHash; // the hash of previous block private String data; //our data will be a simple message. private long timeStamp; //as number of milliseconds since 1/1/1970. //Block Constructor public Block(long index,String data,String previousHash){ this.index = index; this.data = data; this.previousHash = previousHash; this.timeStamp = new Date().getTime(); this.hash = SHA256Util.calculateHash(this); //Making sure we do this after we set the other values. } } 测试类: package com.sha256.sha256.test; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.google.gson.GsonBuilder; import com.sha256.sha256.bean.Block; import com.sha256.sha256.utils.SHA256Util; import java.util.ArrayList; import java.util.Random; public class TestSHA256 { //声明一个区块链,用于添加Block实体 public static ArrayList<Block> blockChain = new ArrayList<>(); public static void main(String[] args) { //test1 测试三个被加密字符串 加密后的hash值的差别 /** * 虽然第三条信息仅仅多一个".",但加密后的数据hash相差极大 */ // String message0 = "我是要被加密的信息"; // String message1 = "我是要被加密的信息"; // String message2 = "我是要被加密的信息."; // String encryptionMessage0 = SHA256Util.applySha256(message0); // String encryptionMessage1 = SHA256Util.applySha256(message1); // String encryptionMessage2 = SHA256Util.applySha256(message2); // System.out.println(encryptionMessage0); // System.out.println(encryptionMessage1); // System.out.println(encryptionMessage2); // // //test2 创建区块链逻辑, 因为第一个块没有上一个块的hash头部值,所以输入0 作为前一个块的previous hash // /** // * 由于在{@link SHA256Util#calculateHash(Block)} // * 中对同时产生的new Date().getTime() (timestamp) // * 也加入进行了hash加密,所以固有的message (data)及 // * previoushash之和进行了加密. // */ // Block genesisBlock = new Block(0,"这是第一个区块中的要被加密的信息和交易信息","0"); // String hash1 = genesisBlock.getHash(); // System.out.println("Hash for block 1 : "+hash1); // // Block secondBlock = new Block(1,"这是第二个区块,以及其中信息!!!它的前区块头部hash我们拿上一个的来使用",hash1); // String hash2 = secondBlock.getHash(); // // System.out.println("Hash for block 2 : "+hash2); // // Block thirdBlock = new Block(2,"这是第三个区块,它的hash应该已经被前两个的信息纳入进来了,它的hash如果对不上,那么说明前面的信息被改动过了",hash2); // String hash3 = thirdBlock.getHash(); // System.out.println("Hash for block 3 : "+hash3); // //// test3 add our blocks to the blockchain ArrayList : // blockChain.add(new Block(0,"区块链上第一小节","0")); // blockChain.add(new Block(1,"区块链第二小节",blockChain.get(blockChain.size()-1).getHash())); // blockChain.add(new Block(2,"区块链第三小节",blockChain.get(blockChain.size()-1).getHash())); int chainNumber = 24; int index = 0; while (chainNumber > 0) { System.out.println("blockChain.size():" + blockChain.size()); if (blockChain.size() == 0) { blockChain.add(new Block(0, "创世块", "0")); } index++; blockChain.add(new Block(index, "区块内容" + blockChainMessage(index), blockChain.get(blockChain.size() - 1).getHash())); chainNumber--; } // JSONArray blockChainJson1 = (JSONArray)JSONArray.toJSON(blockChain); //JSONArray是不排版的 // System.out.println(blockChainJson1); String blockChainJson = new GsonBuilder().setPrettyPrinting().create().toJson(blockChain); System.out.println(blockChainJson); } //模拟一些交易信息 private static String blockChainMessage(int getNumber) { Random random = new Random(getNumber); long l = random.nextLong(); System.out.println("blockChainMessage:" + l); return String.valueOf(l); } }
没有SSM框架前项目分包分层是这样的. (其中的命名不太规范,应省略_) 在有了框架之后项目使用SSM后sql语句都半封装在了.....xml文件中.对应的Dao的接口中的方法,实现对数据库的增删改查操作.获取JDBC链接写在了mybatis的xml配置文件里了. 而servlet也变成了一个,并使用Spring,SpringMVC提供的IOC,DI,视图解析等多工具,只使用指定的@...注解就可以实现生成bean的对象,指定哪个方法为哪个/*.do(action)路径等. 总体代码量减少了,需要配置的xml文件多了.大部分的事情好像都交给了框架去做.忽然感觉一下落了空.没关系,还有重要的事情要处理. 上面的是一个简单的用户登陆的页面,在类似 jq22 这样的网站上可以找到类似的jquery的相关工具js,如验证码.页面效果. 当判定用户输入的验证码与给出的一致后,进入用户名及密码的判定,从数据库查询该用户名和密码,如果核对正确,则登陆成功.反之.则反之. 具体注册和登陆要使用ajax与json去传递数据,因为这样可以预先判定用户名是否已注册,已经注册的话,直接返回给用户说已经注册了,你就别用这个名字了,然后可以跟一系列的随机数字在这个名字后面(但这样是不是还是已经注册了的,判定起来就略麻烦些) <!-- 登陆验证码,判定后如果成功,再执行登陆方法 --> <script> $.idcode.setCode(); $("#loginButton").click(function (){ var IsBy = $.idcode.validateCode(); /* alert(IsBy); */ console.log(IsBy); if(!IsBy){ //如果验证码通过,则执行ajax的方法 event.preventDefault(); }else{ loginUser(); } }); </script> 登陆: <!-- 登陆的ajax方法 --> <script> function loginUser(){ console.log("in loginUser() ~"); var user_name = $("#user_name").val(); var user_pwd = $("#user_pwd").val(); /* var passPattern = /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)[^]{8,16}$/; */ var namePattern = /^[a-zA-Z0-9_-]{4,16}$/; if(namePattern.test(user_name)){ console.log(user_name); console.log(user_pwd); //用户名RegExp正确后,再判定其是否已经在数据库中存在 $.ajax({ url:"<%=path%>/user/queryUserByNameAndPwd.do", //根据用户名查询用户实例 type:"POST", data:{"user_name":user_name, "user_pwd":user_pwd}, dataType:"json", success:function(data){//响应回传成功后到这里 if(data.code==1){//如果用户名密码正确,则登陆. console.log(data.message); document.forms["loginForm"].submit(); window.location.href="http://localhost:8084/OrderSystemM/Test1/index.jsp"; /* return true; */ }else if(data.code==0){ alert(data.message); /* return false; */ }else{ //用户实例不为空,但用户名不等于该查询的用户名 (几率微乎其微) alert("网络错误,请稍后再试"); //发送BUG信息到管理员 /* return false; */ } } }) } } </script> 用户登陆后返回首页,如果不调用window.location.href方法回转到index.jsp,会显示.do路径,我想还有别的方法可以解决这一问题.! 之后用户需要退出时: <!-- 清除session --> <script> function removeSessoin(){ console.log("清除session"); $.ajax({ url:"<%=path%>/user/removeSession.do", //清除用户sessoin type:"POST", data:{}, dataType:"json", success:function(data){//响应回传成功后到这里 if(data.removeCode==1){//如果用户名重复,则< alert("您已退出登陆!欢迎下次光临"); window.location.href="http://localhost:8084/OrderSystemM/Test1/index.jsp"; }else if(data.removeCode==0){ alert("退出失败!请联系!"); }else{ //用户实例不为空,但用户名不等于该查询的用户名 (几率微乎其微) alert("网络错误,请稍后再试"); //发送BUG信息到管理员 } } }) } </script> 在用户注册时,将bootstrap的插件又get了几个新方法. <!-- 注册用户的ajax方法 --> <script> //注册按钮点击执行注册判定 $("#regButton").click(registerUser); //用户名失去焦点时,执行查询该用户名是否已经存在的ajax操作 $("#user_nameReg").blur(userNameJudger); //密码框失焦,执行密码判定 $("#user_pwdReg").blur(pwdCompare); //密码2变动时执行 $("#user_pwdReg2").change(pwdCompare); //用户名的正则表达式 var uPattern = /^[a-zA-Z0-9_-]{4,16}$/; //密码的正则表达式 var pPattern = /^.*(?=.{6,30})(?=.*\d)(?=.*[A-Z])(?=.*[a-z])(?=.*[!@#$%^&*? ]).*$/; //设定用户名的判定boolean var nameFlag = false; var user_nameReg = $("#user_nameReg").val(); //用户名判定 function userNameJudger(){ var user_nameReg = $("#user_nameReg").val(); if(user_nameReg != null && user_nameReg !=''){ //用户名不为空 if(uPattern.test(user_nameReg)){ //用户名格式正式 console.log("用户名格式正确"); //格式正确后判定是否已经存在数据库中 //ajax $.ajax({ url:"<%=path%>/user/queryUserInsByName.do", type:"POST", data:{"user_name":user_nameReg}, dataType:"json", success:function(data){ if(data.exist==1){ $("#nameSp").html("&nbsp;&nbsp;&nbsp; <label class='text-danger'><strong>×用户名已经重复</strong></label>"); nameFlag = false; /* alert(data.message); */ }else{ $("#nameSp").html("&nbsp;&nbsp;&nbsp; <label class='text-success'><strong>√</strong></label>"); nameFlag = true; /* alert(data.message); */ } } }) }else{ nameFlag = false; console.log("用户名格式不正确"); //用户名格式不正确 /* alert("用户名格式错误,应为4到16位(可使用 : 字母,数字,下划线,减号)"); */ /* <label data-toggle="tooltip" data-placement="right" title="右侧的 Tooltip">右侧的 Tooltip</label> */ $("#nameSp").html("&nbsp;&nbsp;&nbsp; <label data-toggle='tooltip' data-placement='right' title='用户名格式错误,应为4到16位.可使用 : 字母,数字,下划线,减号'><p class='text-warning'>用户名格式错误,点我查看具体原因.</p></label>"); $("[data-toggle='tooltip']").tooltip(); } }else{ //用户名不能为空 nameFlag = false; $("#nameSp").html("&nbsp;&nbsp;&nbsp; <label class='text-danger'><strong>用户名不能为空</strong></label>"); } } /* tHIS FUNCTION IS SLOW function getNameBool(){ userNameJudger(); return nameFlag; } */ /* 设置密码的判定boolean */ var pwdFlag = false; //密码格式及相同比较,如果相同,pwdFlag为true function pwdCompare(){ pwdFlag = false; var user_pwd1Reg = $("#user_pwdReg").val(); var user_pwd2 = $("#user_pwdReg2").val(); if(user_pwd1Reg != null && user_pwd1Reg != ''){ //如果密码1不为空,不为空字符串 if(pPattern.test(user_pwd1Reg)){ //密码格式正确,继续判定两个密码是否相同 console.log("密码1格式正确");//ok $("#pwd1Sp").html("&nbsp;&nbsp;&nbsp; <label class='text-success'><strong>√</strong></label>"); if(user_pwd1Reg===user_pwd2){ //两个密码相同,格式也正确 /* alert("密码一致~可以注册");//ok */ pwdFlag = true; $("#pwd1Sp").html("&nbsp;&nbsp;&nbsp; <label class='text-success'><strong>√</strong></label>"); $("#pwd2Sp").html("&nbsp;&nbsp;&nbsp; <label class='text-success'><strong>√</strong></label>"); return pwdFlag; }else{ //第一个密码格式正确,第二个密码跟第一个不相同 /* alert("两个密码不同~");//ok */ if(user_pwd2==''){ pwdFlag = false; $("#pwd2Sp").html("&nbsp;&nbsp;&nbsp; <label class='text-warning'><strong>请输入重复密码.</strong></label>"); return pwdFlag; }else{ pwdFlag = false; $("#pwd2Sp").html("&nbsp;&nbsp;&nbsp; <label class='text-danger'><strong>重复密码错误.</strong></label>"); return pwdFlag; } } }else{ //密码1格式错误 pwdFlag = false; /* alert("密码格式错误,需求6-30位,包括至少1个大写字母,1个小写字母,1个数字,1个特殊字符");//ok */ $("#pwd1Sp").html("&nbsp;&nbsp;&nbsp; <label data-toggle='tooltip' data-placement='right' title='密码格式错误,需求6-30位,包括至少1个大写字母,1个小写字母,1个数字,1个特殊字符'><p class='text-warning'>密码格式错误,点我查看具体原因.</p></label>"); $("[data-toggle='tooltip']").tooltip(); return pwdFlag; } }else{ //如果密码1为空,为空字符串,判断重复密码是否空 if(user_pwd2 != null && user_pwd2 != ''){ pwdFlag = false; //如果密码1为空,密码2不空,则清空密码2,关注密码1输入框提示先输入密码1 $("#user_pwdReg2").val('');//ok console.log("密码2被清空,先填写密码1");//ok $("#user_pwdReg").focus();//ok /* alert("先要输入密码1~"); //ok */ $("#pwd2Sp").html("&nbsp;&nbsp;&nbsp; <label class='text-warning'><strong>请先输入上面的密码.</strong></label>"); return pwdFlag; } } } //注册新用户的一系列focus,blur事件. /* function getRegsiterInfo(){ $() } */ //注册新用户 function registerUser(){ console.log("in registerUser() ~"); var user_nameTrue = $("#user_nameReg").val(); var user_pwdTrue = $("#user_pwdReg").val(); //执行用户名判断,是否已经存在或格式等. userNameJudger(); if(pwdCompare() && nameFlag){ $.ajax({ url:"<%=path%>/user/insertNewUser.do", type:"POST", data:{"user_name":user_nameTrue,"user_pwd":user_pwdTrue}, dataType:"json", success:function(data){ if(data.insertNum>0){ console.log("注册成功"); //发送用户名密码到用户邮箱(待添加) console.log("用户名:"+user_nameTrue+".密码:"+user_pwdTrue); //提交表单 document.forms["regForm"].submit(); /* 跳转页面并刷新获取session及*/ window.location.href="http://localhost:8084/OrderSystemM/Test1/userinfo.jsp"; // }else{ console.log("注册失败"); } } }) }else{ console.log("阻止提交"); event.preventDefault(); } } </script> 基本注册的流程是这样,口述的话简单说明为,先判定注册的用户名是否已经存在于了数据库中,如果是,则提示已经存在,并阻止提交 nameFlag = false 两次重复密码进行比对,格式正确并两者相同,则返回true, 当这些具体满足了条件,将用户注册信息通过ajax及json注册到数据库,并返回注册状态码1or0, 1的话页面假性submit提交让注册框消失,并跳转如userinfo用户信息页面. (这里如果使用邮箱则可以发送邮件给注册邮箱,当用户点击后再判断操作) 基本的controller 更新用户 //动态更新用户数据 用户信息界面 @RequestMapping("updateUser") @ResponseBody public Map<String,Object> updateUser(User user){ Map<String,Object> map = new HashMap<String,Object>(); int updateNum = us.updateByPrimaryKeySelective(user); map.put("updateNum",updateNum); if(updateNum>0){ map.put("message", "用户数据更新成功"); } return map; } 注册 //注册新用户,成功返回状态码1 @RequestMapping("insertNewUser") @ResponseBody public Map<String,Object> insertNewUser(User u,HttpSession session){ Map<String,Object> map = new HashMap<String,Object>(); int insertNum = us.insertUser(u); if(insertNum>0){ map.put("insertNum", insertNum); map.put("message", "注册成功."); User user = us.queryUserByNameAndPwd(u); System.out.println(user); session.setAttribute("userID", user.getUser_id()); //刚注册,昵称为空,放入用户名 session.setAttribute("userName", u.getUser_name()); return map; }else{ map.put("insertNum", insertNum); map.put("message", "注册失败,请联系网站管理员."); return map; } } 根据session中的用户id查询用户实例,将数据反填到用户数据中 //根据用户ID查询用户实例 从session中获取ID @RequestMapping("getUserById") @ResponseBody public ModelMap getUserById(HttpSession session,ModelMap map){ System.out.println(">>>>>>>>>>>>>>>>"+(Long)session.getAttribute("userID")); User user = us.queryUserById((Long)session.getAttribute("userID")); map.addAttribute("userIns",user); /* return "redirect:/user/showUser.do";*/ return map; } 用户退出 //用户退出.清空session @RequestMapping("removeSession") @ResponseBody public Map<String,Object> removeSession(HttpSession session){ Map<String,Object> map = new HashMap<String,Object>(); session.removeAttribute("userID"); //清空session 并无返回类型 session.removeAttribute("userName"); System.out.println("触发removeSession"); map.put("removeCode",1); return map; } 用户名和密码登陆 //用户登陆进行ajax判定 如果登陆成功判断状态码并展示用户姓名链接,及退出按钮 @RequestMapping("queryUserByNameAndPwd") @ResponseBody public Map<String,Object> queryUserByNameAndPwd(User user,HttpSession session){ Map<String,Object> map = new HashMap<String,Object>(); User u = us.queryUserByNameAndPwd(user); if(u!=null){ //用户存在登陆成功放入1 map.put("message", "登陆成功"); map.put("code", 1); //sessoin放入用用户名和密码 session.setAttribute("userID", u.getUser_id()); //如果用户昵称不为空,则将用户昵称进行展示 if(u.getNick_name()!=null){ session.setAttribute("userName", u.getNick_name()); return map; }else{ //昵称为空,放入用户名 session.setAttribute("userName", u.getUser_name()); return map; } }else{ //如果用户为空,则放入0 System.out.println("密码错误"); map.put("message", "用户名或密码错误"); map.put("code", 0); return map; } } ... 接下来是对数据库表的设计以及商家入驻及套餐内容展示. 感谢徐老大的xJsonBindView.js 将编程看作是一门艺术,而不单单是个技术。 敲打的英文字符是我的黑白琴键, 思维图纸画出的是我编写的五线谱。 当美妙的华章响起,现实通往二进制的大门即将被打开。
package kata_011; /** * Some numbers have funny properties. For example: * * 89 --> 8¹ + 9² = 89 * 1 * * 695 --> 6² + 9³ + 5⁴= 1390 = 695 * 2 * * 46288 --> 4³ + 6⁴+ 2⁵ + 8⁶ + 8⁷ = 2360688 = 46288 * 51 * * Given a positive integer n written as abcd... (a, b, c, d... being digits) * and a positive integer p we want to find a positive integer k, if it exists, * such as the sum of the digits of n taken to the successive powers of p is * equal to k * n. In other words: * * Is there an integer k such as : (a ^ p + b ^ (p+1) + c ^(p+2) + d ^ (p+3) + ...) = n * k * * If it is the case we will return k, if not return -1. * * Note: n, p will always be given as strictly positive integers. * * digPow(89, 1) should return 1 since 8¹ + 9² = 89 = 89 * 1 digPow(92, 1) * should return -1 since there is no k such as 9¹ + 2² equals 92 * k * digPow(695, 2) should return 2 since 6² + 9³ + 5⁴= 1390 = 695 * 2 * digPow(46288, 3) should return 51 since 4³ + 6⁴+ 2⁵ + 8⁶ + 8⁷ = 2360688 = 46288 * 51 * * @author SeeClanUkyo * */ public class DigPow { public static void main(String[] args) { System.out.println(digPow(46288, 3)); } public static long digPow(int n, int p) { // your code if (n > 0) { String nstr = n + ""; int nlen = nstr.length(); long sum = 0; for (int i = 0; i < nlen; i++) { sum += Math.pow(Integer.parseInt(nstr.substring(i, i + 1)), (p + i)); if (sum % n == 0) { return sum / n; } } } return -1; } } 将编程看作是一门艺术,而不单单是个技术。 敲打的英文字符是我的黑白琴键, 思维图纸画出的是我编写的五线谱。 当美妙的华章响起,现实通往二进制的大门即将被打开。
将编程看作是一门艺术,而不单单是个技术。 敲打的英文字符是我的黑白琴键, 思维图纸画出的是我编写的五线谱。 当美妙的华章响起,现实通往二进制的大门即将被打开。
将编程看作是一门艺术,而不单单是个技术。 敲打的英文字符是我的黑白琴键, 思维图纸画出的是我编写的五线谱。 当美妙的华章响起,现实通往二进制的大门即将被打开。