文章目录
需求分析与实现思路:
进入登录页面时请求CheckCodeServlet生成验证码,并把验证码的值保存到session里,当用户提交登录表单时,使用validator插件进行表单校验,除验证码外的其他参数都校验通过后,使用validator插件提供的方式不提交表单,而是把表单提交的验证码值作为参数使用AJAX发送异步请求,在服务端(LoginServlet)从session里获取保存的验证码的值和表单提交的验证码值进行比较,把结果返回给客户端做相应处理。
代码示例:
- 登录页面。 (login.html)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>登录</title>
<style type="text/css">
table {
width: 30%;
margin:auto;
position: absolute;
right: 0;
left: 0;
}
/*验证码效验不通过时提示的字体颜色*/
.showtip {
color: red;
}
/*validator插件效验不通过时提示的字体颜色*/
.error{
color:red;
}
</style>
</head>
<body>
<form name="empForm" id="empForm" method="post" action="#">
<table>
<tr>
<td>用户名</td>
<td><input type="text" id="username" name="username" autocomplete="off" /></td>
</tr>
<tr>
<td>密码</td>
<td><input type="password" id="pwd" name="pwd" /></td>
</tr>
<tr>
<td>验证码</td>
<td>
<input type="text" name="check" id="check" autocomplete="off">
<!--该项目的context路径为 /test , src属性值是图像文件的URL ,这里请求/test/checkCode,CheckCodeServlet会响应输出验证码图片-->
<img src="/test/checkCode" id="checkImg" alt="" onclick="changeImage(this)">
<label class="showtip" id="vfcodelab" ></label>
</td>
</tr>
<tr>
<td></td>
<td><input type="submit" id="smtBtn" value="登录"></td>
</tr>
</table>
</form>
<!--导入jquery-->
<script src="js/jquery-1.11.0.min.js"></script>
<!-- 引入validator插件 -->
<script src="js/jquery.validate.min.js"></script>
<script>
//点击时切换验证码,改验证码图片的src属性值。
function changeImage(obj) {
//每次点击时,要保证src属性值是变化的,否则浏览器会从缓存里取图片显示,而不会发请求重新请求图片。
//如何让src属性值是变化:在发请求时,可以在请求路径的后边,通过?追加一些参数(参数随机),这样每次src属性值都是变化的。
//请求路径?参数名=参数值就等价于表单的get提交的参数,请求到达CheckCodeServlet,动态生成验证码,再输出到页面,对于参数是何值有没有参数这些都不重要。
obj.src = "/test/checkCode?a=" + Math.random();
}
//表单校验
$("#empForm").validate({
submitHandler:function(){//校验通过后,表单不提交,而是执行function里的代码
var params = $("#empForm").serialize();
$.post("login",params,function (result) {
if(result.ok){//验证码验证通过
alert("验证码验证通过")
}else{//验证码验证不通过
$("#vfcodelab").show()
$("#vfcodelab").text(result.msg);
//点击切换验证码
$("#checkImg").click();
}
},"json")
},
rules:{//配置表单项校验的规则
username:{
required: true
},
pwd:{
required: true,
rangelength:[6,12]
}
},
messages:{//配置对应的表单项校验失败后的错误提示信息
username:{
required: "请输入用户名"
},
pwd:{
required: "请输入密码",
rangelength:"密码必须是6~12位"
}
}
})
//验证码验证不通过时,点击验证码输入框,重新输入时把提示隐藏
$("#check").click(function () {
$("#vfcodelab").hide();
})
</script>
</body>
</html>
- 验证码图片请求,Java生成验证码,响应客户端,登录页面再显示验证码。 (CheckCodeServlet)
注:网络资源,供参考
/**
* Java生成验证码,响应客户端
*/
@WebServlet("/checkCode")
public class CheckCodeServlet extends HttpServlet {
@Override
public void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {
//服务器通知浏览器不要缓存
response.setHeader("pragma","no-cache");
response.setHeader("cache-control","no-cache");
response.setHeader("expires","0");
//在内存中创建一个长80,宽30的图片,默认黑色背景
//参数一:长
//参数二:宽
//参数三:颜色
int width = 80;
int height = 30;
BufferedImage image = new BufferedImage(width,height,BufferedImage.TYPE_INT_RGB);
//获取画笔
Graphics g = image.getGraphics();
//设置画笔颜色为灰色
g.setColor(Color.GRAY);
//填充图片
g.fillRect(0,0, width,height);
//产生4个随机验证码,12Ey
String checkCode = getCheckCode();
//将验证码放入HttpSession中
request.getSession().setAttribute("CHECKCODE_SERVER",checkCode);
//设置画笔颜色为黄色
g.setColor(Color.YELLOW);
//设置字体的小大
g.setFont(new Font("黑体",Font.BOLD,24));
//向图片上写入验证码
g.drawString(checkCode,15,25);
//将内存中的图片输出到浏览器
//参数一:图片对象
//参数二:图片的格式,如PNG,JPG,GIF
//参数三:图片输出到哪里去
ImageIO.write(image,"PNG",response.getOutputStream());
}
/**
* 产生4位随机字符串
*/
private String getCheckCode() {
String base = "0123456789ABCDEFGabcdefg";
int size = base.length();
Random r = new Random();
StringBuffer sb = new StringBuffer();
for(int i=1;i<=4;i++){
//产生0到size-1的随机值
int index = r.nextInt(size);
//在base字符串中获取下标为index的字符
char c = base.charAt(index);
//将c放入到StringBuffer中去
sb.append(c);
}
return sb.toString();
}
@Override
public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doGet(request,response);
}
}
- 登录页面表单校验,AJAX异步发送请求,效验表单提交验证码与服务端保存的验证码是否相同,并响应客户端 。(LoginServlet)
@WebServlet(name = "LoginServlet",urlPatterns ="/login")
public class LoginServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
ResultInfo info=null;
response.setContentType("text/html;charset=utf-8");
request.setCharacterEncoding("UTF-8");
//接收参数
//String username = request.getParameter("username");
//String password = request.getParameter("password");
String check = request.getParameter("check");
//完成功能
//先验证验证码是否正确
String checkcode_server = (String) request.getSession().getAttribute("CHECKCODE_SERVER");
if(check.equalsIgnoreCase(checkcode_server)){
//封装后端返回前端的数据
info=new ResultInfo(true);
}else{
info=new ResultInfo(false,"验证码填写错误");
}
//处理结果
ObjectMapper mapper = new ObjectMapper();
String json = mapper.writeValueAsString(info);
response.getWriter().print(json);
}
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
}
- 封装后端返回前端的数据,Java对象转换为json字符串,登录页面AJAX异步请求接收到json对象 (ResultInfo)
注:网络资源,供参考
/**
* 用于封装后端返回前端数据对象。对应json格式:{"ok":true, "data":{结果数据}, "msg":"消息描述"}
*/
public class ResultInfo implements Serializable {
private boolean ok;//后端返回结果正常为true,发生异常返回false
private Object data;//后端返回结果数据对象
private String msg;//描述消息。如果发生异常,则是错误信息
public ResultInfo() {
}
/**
* @param ok 是否正常处理完成
*/
public ResultInfo(boolean ok) {
this.ok = ok;
}
/**
* @param ok 是否正常处理
* @param data 处理结果数据
*/
public ResultInfo(boolean ok, Object data) {
this.ok = ok;
this.data = data;
}
/**
* @param ok 是否正常处理
* @param msg 消息描述
*/
public ResultInfo(boolean ok, String msg) {
this.ok = ok;
this.msg = msg;
}
/**
* @param ok 是否正常处理
* @param data 返回数据
* @param msg 消息描述
*/
public ResultInfo(boolean ok, Object data, String msg) {
this.ok = ok;
this.data = data;
this.msg = msg;
}
public boolean isOk() {
return ok;
}
public void setOk(boolean ok) {
this.ok = ok;
}
public Object getData() {
return data;
}
public void setData(Object data) {
this.data = data;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
}