个人博客网站编写(05)--注冊功能的編寫(邮件激活、Redis 缓存、Ajax 异步获取)
前言:上一篇我們將介紹了如何編寫接口及測試的編寫,這一篇我們將開始從最基礎的功能開始寫!
最近兩天沒有寫博客,第一:最近滿著去將我買的服務器備案。真是一個麻煩的事情。第二:最近兩天有開發任務。效率真低哦!拖了很久的時間。
好吧開始!
前期準備:
第一步,在webapp頁面下放入jsp、css、js、images。等資源文件,在文末我會將對應的資源放入網盤。
第二步,將register.jsp直接放入webapp的頁面,activeFail.jsp、activeSuccess、registerSuccess、文件放入web-inf目錄下。
在這我需要解釋一下,在webapp頁面下,是可以直接通過超連接就能訪問的,而web-info下面的目錄是需要通過controller跳轉才能訪問,所以更加安全!因此一般的做法是將不需要權限訪問的,放在WEBAPP下!
第三步,將register.jsp頁面打開,並輸入下面的代碼。
<%@ page contentType="text/html;charset=UTF-8"%>//設計編碼為utf-8
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>//使用Jstl的c標簽
<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %> //使用jstl的函數標簽
<c:set var="ctx" value="${pageContext.request.contextPath }"/> //定義全局的獲取路徑啊?
在 head 标签内引入 CSS 和 JS 文件:
<link type="text/css" rel="stylesheet" href="${ctx}/css/dreamland.css">//css文件
<script type="text/javascript" src="${ctx}/js/jquery.min.js"></script>//js文件
第四步,在index.jsp中添加超鏈接跳轉到登陸界面。
<h2><a href=''register.jsp">注冊</a></h2>
然後運行項目,點擊注冊。
OJBK,現在開始來咯!
首先是驗證碼。
验证码
1.在 id 为 nickName_span 的 span 标签下加入 input 输入框和验证码图片(src 属性引入图片):
//首先是加入一個輸入框。
<input id="code" name="code" type="text" class="kuang_txt yanzm" placeholder="验证码" onblur="checkCode()">
<div>
<IMG id="captchaImg" style="CURSOR: pointer"
onclick="changeCaptcha()"
title="看不清楚?请点击刷新验证码!" align='absmiddle' src="${ctx}/captchaServlet"
height="18" width="55">
<a href="javascript:;"
onClick="changeCaptcha()" style="color: #666;">看不清楚</a> <span id="code_span" style="color: red"></span>
</div>
代碼解釋:
(1)其中 onclick 点击事件 changeCaptcha,点击之后更换验证码,具体方法如下:
//更换验证码
function changeCaptcha() {
$("#captchaImg").attr('src', '${ctx}/captchaServlet?t=' + (new Date().getTime()));
}
根据 id(captchaImg) 获取 image 标签对象,将它的 src 属性值替换成新的验证码图片。
(2)src 属性值对应的是一个 Servlet,Servlet 对应的URL是 /captchaServlet
,当页面加载的时候它会调用该 Servlet 的方法,返回一个验证码图片。
2.在 web.xml 文件中配置 captchaServlet。
<!--验证码-->
<servlet>
<servlet-name>CaptchaServlet</servlet-name>
<servlet-class>
com.liwei.blog.common.CodeCaptchaServlet
</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>CaptchaServlet</servlet-name>
<url-pattern>/captchaServlet</url-pattern>
</servlet-mapping>
captchaServlet執行過程。
1、點擊看不清,然後代碼執行找到WEB.XML中servlet-name為 CaptchaServlet的servlt.
2、然後servlet通過servlet-mapping找到項目中servlet的實際位置。
3、SO,現在我們要去寫驗證碼的servlet了。
在 common 包下引入 CodeCaptchaServlet.java,制作验证码的类,主要是通过 Graphics 设置图片大小,然后随机生成干扰点和4位随机验证码,并保存到 Session 中,用于注册时验证。生成验证码的 CodeCaptchaServlet.java 文件我已放在了文末的百度网盘链接中,可以当作工具类来直接使用。
4.重新启动 Tomcat,点击 index.jsp 内的链接“点我注册”查看效果:
嗯,很不錯我們現在有了驗證碼了!
注册
页面表单校验
这里主要说下手机号的校验、验证码的校验、勾选用户协议的校验和表单提交,其他校验方法参考源码中的方法。
1.手机号的校验:
<input id="phone" name="phone" type="text" class="kuang_txt phone" placeholder="手机号" onblur="checkPhone();"><span id="phone_ok"></span>
<br/>
<span id="phone_span" style="color: red"></span>
其中 br 标签代表换行,给手机号的 input 框添加一个离焦事件 onblur="checkPhone();"
, 具体方法如下:
//校验手机号
var v = 0;
var flag2 = false;
function checkPhone(){
var phone = $("#phone").val();
phone = phone.replace(/^\s+|\s+$/g,"");
if(phone == ""){
$("#phone_span").text("请输入手机号码!");
$("#phone_ok").text("");
var hgt = $("#regist-left").height();
if(v==0){
$("#regist-left").height(hgt+30);
$("#regist-right").height(hgt+30);
v++;
}
flag2 = false;
}
if(!(/^1[3|4|5|8|7][0-9]\d{8}$/.test(phone))){
$("#phone_span").text("手机号码非法,请重新输入!");
$("#phone_ok").text("");
var hgt = $("#regist-left").height();
if(v==0){
$("#regist-left").height(hgt+30);
$("#regist-right").height(hgt+30);
v++;
}
flag2 = false;
}else{
$.ajax({
type:'post',
url:'/checkPhone',
data: {"phone":phone},
dataType:'json',
success:function(data){
var val = data['message'];
if(val=="success"){
$("#phone_span").text("");
$("#reg_span").text("");
$("#phone_ok").text("√").css("color","green");
var content = $("#phone_ok").text();
if(content=="√" ){
var hgt = $("#regist-left").height();
if(v==1){
$("#regist-left").height(hgt-30);
$("#regist-right").height(hgt-30);
}
v=0;
}
flag2 = true;
}else{
$("#phone_span").text("该手机号已经注册!");
$("#phone_ok").text("");
var hgt = $("#regist-left").height();
if(v==0){
$("#regist-left").height(hgt+30);
$("#regist-right").height(hgt+30);
v++;
}
flag2 = false;
}
}
});
}
return flag2;
}
//根据内容增加而增加高度
function increaseHeight() {
var hgt = $("#regist-left").height();
$("#regist-left").height(hgt+30);
$("#regist-right").height(hgt+30);
}
//根据内容减少而减少高度
function reduceHeight() {
var hgt = $("#regist-left").height();
$("#regist-left").height(hgt-30);
$("#regist-right").height(hgt-30);
}
代码解读如下:
(1)通过 var 定义两个变量,一个变量 v 赋初始值为0,方法中可以根据 v 的值控制外部 div 的高度。另一个变量 flag2 赋初始值 false,代表手机号 input 框的状态,false 情况下不能提交表单。
(2)jQuery 获取对象的方式为:$("#phone")
,根据 $+("#id")
的方式获取该 id 的标签对象,记得通过 id 获取对象要加 #
,通过 class 获取标签对象要加 .
,还有其他获取对象的方法,不会的同学可搜索 CSS 标签选择器进行学习。
(3)获取 input 框对象之后,可通过对象 .val()
方法获取该对象的值,即鼠标离焦后该 input 框内的值,赋值给变量 phone。
(4)接下来通过 replace 方法去掉前后空格,该方法的第一个参数是一个正则表达式,表示以空格开头或者以空格结尾。
(5)判断该手机号是否为空,如果为空则在 id=phone_span
的 span 标签中进行提示,span 标签中有内容后,整个 div 会向下扩张,所以要动态增加外部 div 的高度,通过 id=regist-left
获取左边 div 的高度,右边的 div 和左边一样,如果变量 v=0,则将左边和右边的 div 高度都加30,v 自增1。
(6)对手机号进行正则匹配,判断手机号是否正确合法,如果不正确给予错误提示,动态增加外部 div 高度,原理同上。
(7)手机号码判断正确以后,发送 AJAX 请求到后台,请求方式为 post ,请求 URL 为 /checkPhone
,映射后台的某个 Controller 的方法,请求参数 data 是手机号,数据类型是 JSON 格式,success 回调函数返回后台处理结果,放在 data 中,通过 data['message']
取出放在 data 中的数据,如果是“success”,说明该手机号未被注册,则在 input 后的 span 标签中打“√”,并且如果 v=1,则将外部 div 减去30,动态缩短 div 高度,将变量 v 重置为0,并将 flag2 赋值为 true,表示手机号的 input 框状态已正确。
(8)如果返回结果不是“success”,说明该手机号已被注册,则给予提示,然后将外部 div 高度动态增加30,v自增 1,将 flag2 赋值为 false,表示 input 框状态错误,不能提交表单。
(9)最后将 flag2 返回。
(10)后面两个方法是将动态增加和缩短 div 的高度封装成了方法,直接调用方法即可。
其中 $("#reg_span").text("")
用来对点击注册时出现的错误进行错误提示,默认情况下都为空。
手机号校验 AJAX 请求对应的后台代码:
在 wang.dreamland.www.controller 包下新建 RegisterController.java,将关于注册的方法都放在此 Controller 下:
@Controller
public class RegisterController {
private final static Logger log = Logger.getLogger(RegisterController.class);
@Autowired
private UserService userService;
@RequestMapping("/checkPhone")
@ResponseBody
public Map<String, Object> checkPhone(Model model, @RequestParam(value = "phone", required = false) String phone) {
log.debug("注册-判断手机号" + phone + "是否可用");
Map map = new HashMap<String, Object>();
User user = userService.findByPhone(phone);
if (user == null) {
//未注册
map.put("message", "success");
} else {
//已注册
map.put("message", "fail");
}
return map;
}
}
代码解读如下:
(1)在类上加上 @Controller
注解代表这是 Controller 层。
(2)通过 Logger.getLogger 方法获取日志对象 Logger,参数就是要打印的类的字节码文件。
(3)通过 @Autowired
注解注入 UserService 对象,可调用其中的方法。
(4)@RequestMapping
注解映射前端访问的 URL 路径,这里对应的就是 AJAX 请求的 URL。
(5)@ResponseBody
注解作用是返回 JSON 格式的数据。
(6)@RequestParam
注解接收前台传来的参数,value 对应参数的名字,required=false
代表该参数是非必须的,可以没有,后面的 String phone 用来接收参数的值,类型为 String 类型。
(7)打印 Log 日志。
(8)new 一个 HashMap 集合,将数据以 key-value 的形式存入 map 中。
(9)根据手机号码查询用户,如果用户为 null 则代表未注册,则以“message”为键,“success”为值存入 map 集合。
(10)如果用户不为 null,则代表该手机号已被注册,则把“fail”作为值存入 map 集合,最后将 map 集合返回。
2.验证码的校验
<input id="code" name="code" type="text" class="kuang_txt yanzm" placeholder="验证码" onblur="checkCode()">
验证码 input 框的离焦事件 checkCode 方法如下:
//验证码校验
var flag_c = false;
function checkCode() {
var code = $("#code").val();
code = code.replace(/^\s+|\s+$/g,"");
if(code == ""){
$("#code_span").text("请输入验证码!").css("color","red");
flag_c = false;
}else{
$.ajax({
type: 'post',
url: '/checkCode',
data: {"code": code},
dataType: 'json',
success: function (data) {
var val = data['message'];
if (val == "success") {
$("#code_span").text("√").css("color","green");
$("#reg_span").text("");
flag_c = true;
}else {
$("#code_span").text("验证码错误!").css("color","red");
flag_c = false;
}
}
});
}
return flag_c;
}
代码解读如下:
(1)定义一个变量 flag_c = false
,默认状态为错误状态,不可提交表单。
(2)根据标签 id 获取标签对象,通过对象的 val() 方法取得该标签对象的值,即用户输入的验证码。
(3)将验证码去空格后,判断该验证码是否为空,为空则给予错误提示,因为错误提示是加在验证码右侧,所以不用增加 div 高度。
(4)如果验证码不为空,则发送 AJAX 请求给后台,后台将处理后的结果放在 data 中,通过 data["message"]
获取放入 data 中的数据,如果是“success”,则代表验证码正确,打个“√”,flag_c
赋值为 true,代表该 input 框状态正确。
(5)如果 AJAX 返回的结果不是“success”,则说明输入的验证码错误,则给出错误提示,flag_c
赋值为 flase,代表状态错误。
(6)最后将 flag_c
返回。
验证码校验 AJAX 请求对应的后台代码:
在 RegisterController.java 中添加如下方法:
@RequestMapping("/checkCode")
@ResponseBody
public Map<String, Object> checkCode(Model model, @RequestParam(value = "code", required = false) String code) {
log.debug("注册-判断验证码" + code + "是否可用");
Map map = new HashMap<String, Object>();
ServletRequestAttributes attrs = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
String vcode = (String) attrs.getRequest().getSession().getAttribute(CodeCaptchaServlet.VERCODE_KEY);
if (code.equals(vcode)) {
//验证码正确
map.put("message", "success");
} else {
//验证码错误
map.put("message", "fail");
}
return map;
}
代码解读如下:
(1)通过 ServletRequestAttributes 获取 Request 对象,然后通过 Request 获取 Session 对象。
(2)通过 session.getAttribute 方法获取之前生成验证码时存入 session 中的验证码,赋值给 vcode。
(3)判断前台传来的验证码和 Session 中存入的验证码是否相同。如果相同则代表验证码输入正确,将“success”返回给前台,否则代表验证码输入错误,将“fail”返回给前台。
勾选用户协议的校验:
<input id="protocol" type="checkbox" onclick="checkProtocol();"><span>已阅读并同意<a href="#" target="_blank" ><span class="lan">《梦境网用户协议》</span></a></span>
选择框 checkbox 的点击事件 checkProtocol 方法如下:
//勾选用户协议校验
function checkProtocol() {
if($('#protocol').prop("checked"))
{
$("#reg_span").text("");
return true;
}
else{
return false;
}
}
如上面的代码,通过 id 获取 input 框对象,通过该对象的 prop 方法返回 checked 属性的值,如果为 true 则将 id=reg_span
的 span 标签的错误内容清空,返回 true,否则返回 false。
表单提交
所有的 input 框被 form 标签包裹着,成功提交表单后,后台通过 input 框的 name 属性获取 value 中的值。
<form action="${ctx}/doRegister" method="post" id="registerForm">
action 对应后台 Controller 中的映射 URL,method 请求方式是 post 请求,form 表单的 id 是 registerForm。
通过点击注册按钮提交表单:
<input name="注册" type="button" class="btn_zhuce" id ="to_register" value="注册">
注册按钮的点击事件如下:
//提交注册信息
$("#to_register").click (function(){
if(!checkProtocol()){
$("#protocol_span").text("请勾选\"阅读并接受梦境网用户协议\"!").css("color","red");
}else{
$("#protocol_span").text("");
}
if(checkPhone() && checkPassword()&& checkEmail() && checkNickName()&& checkCode() && checkProtocol()){
$("#registerForm").submit();
}else {
$("#reg_span").text("请将信息填写完整!").css("color","red");
}
});
代码解读如下:
(1)通过 id 获取对象,对象.click(function(){});
即该对象的点击事件函数。
(2)判断是否勾选用户协议,没有的话给予错误提示,勾选则将 span 标签内容清空。
(3)判断手机号、密码、邮箱、昵称、验证码、勾选用户协议都正确后,则通过 form 表单对象的 submit() 方法提交表单,否则有一个错误,则提示错误信息。
接下來是重頭戲,關於郵箱的驗證。不過限於本篇的篇幅。我決定寫個小專題,專門記錄。
郵箱驗證請點擊這裏。郵箱驗證
链接:https://pan.baidu.com/s/1e1k05lX6_PwGrey82v3Gdw 密码:3gd3