写在前面
写web 的人,我想最先要解决的就是注册登录的界面了,一个小小的界面却包含着各种基本的知识,让我这个新手摸了一天。
效果图
知识
1.bootstrap渲染表单
2.JQuery ajax验证用户名
3.两次密码输入要一致
4.后台密码验证
5.点击图片刷新
代码
前台
test.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<link rel="stylesheet" href="css/bootstrap.min.css">
<script src="js/jquery-3.3.1.js"></script>
<script src="js/bootstrap.min.js"></script>
</head>
<body>
<div class="container">
<div id="form-box" class="row col-md-6">
<div class="row">
<form class="form-horizontal" action="/RegisterValidateServlet" method="post">
<fieldset>
<legend>用户注册</legend>
<div class="form-group">
<label for="username" class="control-label col-md-2">用户名:</label>
<div class="col-md-6 has-feedback" id="username-box">
<input type="text" class="form-control" id="username" name="username" required>
<span id="user-exists" class="glyphicon form-control-feedback"></span>
</div>
<p id="username-help" class="help-block"></p>
</div>
<div class="form-group">
<label for="password" class="control-label col-md-2">密码:</label>
<div class="col-md-6 ">
<input type="password" class="form-control" id="password" name="password" required>
</div>
</div>
<div class="form-group">
<label for="password2" class="control-label col-md-2">确认密码:</label>
<div class="col-md-6 has-feedback" id="password2-box">
<input type="password" class="form-control" id="password2" name="password2" required>
<span id="miss-matching" class="glyphicon form-control-feedback"></span>
</div>
<p id="password2-help" class="help-block"></p>
</div>
<div class="form-group">
<label for="identify" class="col-md-2 control-label">验证码:</label>
<div class="col-md-2">
<input type="text" class="form-control" id="identify" name="identify" required>
</div>
<img id="identify-code">
</div>
<div class="form-group">
<div class="col-md-6 col-md-push-2">
<input type="submit" class="btn btn-info" value="提交">
</div>
</div>
</fieldset>
</form>
</div>
</div>
</div>
<script>
$(function () {
/*这个可以防止浏览器后退时候图片不刷新*/
$("#identify-code").prop("src", "/IdentifyingCodeServlet?" + new Date().getTime());
let $form = $("form");
/*点击框自动清空内容*/
$form.on("click", ":input[type!=submit]", function () {
$(this).prop("value", "");
});
/*添加勾这个图标*/
function addOK(box, span) {
span.removeClass("glyphicon-remove");
box.removeClass("has-error");
span.addClass("glyphicon-ok");
box.addClass("has-success");
}
/*添加×这个图标*/
function addRemove(box, span) {
span.removeClass("glyphicon-ok");
box.removeClass("has-success");
span.addClass("glyphicon-remove");
box.addClass("has-error");
}
/*两次密码验证*/
$("#password2,#password").blur(function () {
let password = $("#password").val();
let password2 = $("#password2").val();
let $missmatchingSpan = $("#miss-matching");
let $password2Box = $("#password2-box");
let $password2Help = $("#password2-help");
if (password.trim() === "" || password2.trim() === "" || password2 !== password) {
addRemove($password2Box, $missmatchingSpan);
$password2Help.html("两次密码不一致");
} else {
addOK($password2Box, $missmatchingSpan);
$password2Help.html("");
}
});
/*ajax验证后台用户名是否存在*/
$("#username").blur(function () {
let username = $("#username").val().trim();
if (username !== "") {
$.ajax({
url: "RegisterValidateServlet",
type: "post",
data: {
username: username
},
dataType: "text",
success: function (data) {
let $usernameBox = $("#username-box");
let $userExistsSpan = $("#user-exists");
let $usernameHelp = $("#username-help");
if (data === "exists") {
addRemove($usernameBox, $userExistsSpan);
$usernameHelp.html("用户名已存在");
} else {
addOK($usernameBox, $userExistsSpan);
$usernameHelp.html("用户名可以用");
}
},
error: function (error) {
alert(error);
}
})
}
});
/*点击生成新的验证码*/
$("#identify-code").click(function () {
$(this).prop("src", "/IdentifyingCodeServlet?" + new Date().getTime());
});
})
</script>
</body>
</html>
由于这些代码都是自己想到的,肯定有更好的写法,比如用JQuery框架等,由于我是想从事后端的,就不在这上纠结了。图标是由官网来的,上面有教学,可以看下这里是地址https://v3.bootcss.com/components/,起步中有响应的bootstrap 渲染教程,也可以学习一下哈。ajax是很好的异步技术,是肯定要懂的。加上时间戳能够让浏览器不用缓存,发送新的请求。
后台
验证码Servlet
package web.controller;
import javax.imageio.ImageIO;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.Random;
@WebServlet(name = "IdentifyingCodeServlet")
public class IdentifyingCodeServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
BufferedImage bfi = new BufferedImage(80, 25, BufferedImage.TYPE_INT_RGB);
Graphics2D graphics = (Graphics2D) bfi.getGraphics();
// 设置背景色
graphics.setColor(Color.WHITE);
graphics.fillRect(0, 0, 80, 25);
// 设置边框
graphics.setColor(Color.BLACK);
graphics.drawRect(0, 0, 80 - 1, 25 - 1);
String str = drawRandomNum(graphics);
System.out.println(str);
HttpSession session = request.getSession();
session.setAttribute("identifyCode", str);
drawPoint(bfi);
drawInfluencedLine(graphics);
response.setHeader("Expires", "-1");
response.setHeader("Cache-Control", "no-cache");
response.setHeader("Cache-Control", "no-store");
response.setHeader("Pragma", "no-cache");
response.setHeader("content-type", "image/jpeg");
ImageIO.write(bfi, "jpg", response.getOutputStream());
}
// 画上点
private void drawPoint(BufferedImage bfi) {
int area = (int) (0.02 * 80 * 25);
for (int i = 0; i < area; ++i) {
int x = (int) (Math.random() * 80);
int y = (int) (Math.random() * 25);
bfi.setRGB(x, y, (int) (Math.random() * 255));
}
}
private void drawInfluencedLine(Graphics2D g) {
//设置验证码中的干扰线
for (int i = 0; i < 3; i++) {
Random random = new Random();
//随机获取干扰线的起点和终点
int xstart = random.nextInt(80);
int ystart = random.nextInt(25);
int xend = random.nextInt(80);
int yend = random.nextInt(25);
g.setColor(new Color(random.nextInt(255), random.nextInt(255), random.nextInt(255)));
g.drawLine(xstart, ystart, xend, yend);
}
}
// 生成随机数旋转后写入
private String drawRandomNum(Graphics2D g) {
char[] chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890".toCharArray();
Random random = new Random();
int index;
StringBuilder builder = new StringBuilder();
for (int i = 0; i < 4; i++) {
// 从字符数组中获得随机字符
index = random.nextInt(chars.length);
String value = chars[index] + "";
// 设置随机字符的颜色
g.setColor(new Color(random.nextInt(255), random.nextInt(255), random.nextInt(255)));
// 字体格式
Font font = new Font(null, Font.BOLD, 20);
g.setFont(font);
//生成-30~30之间的数字
int dgree = random.nextInt(60) - 30;
//旋转
g.rotate(dgree * Math.PI / 180, i * 20 + 2, 23);
// 写入字符
g.drawString(value, i * 20 + 2, 20);
// 把画笔再转回去,免得影响下次的弧度
g.rotate(-dgree * Math.PI / 180, i * 20 + 2, 23);
builder.append(value);
}
return builder.toString();
}
}
验证码里面比较重要的就是,缓存的设置了,验证码这种及时性的需要禁止浏览器缓存,保证它的及时刷新。再加上前台的时间戳,就能够保证了。
简单验证Servlet
package web.controller;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Enumeration;
@WebServlet(name = "web.controller.RegisterValidateServlet")
public class RegisterValidateServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("UTF-8");
response.setCharacterEncoding("UTF-8");
response.setContentType("text/html;charset=UTF-8");
String username = "123";
String user = request.getParameter("username");
String identifyCode = request.getParameter("identify");
if (identifyCode != null) {
String identifySession = (String) request.getSession().getAttribute("identifyCode");
if (identifyCode.equals(identifySession)) {
request.setAttribute("message", "注册成功");
request.getRequestDispatcher("/message.jsp").forward(request, response);
}
}
if (user.equals(username)) {
response.getWriter().write("exists");
}
}
}
待改进之处
- 如果有坏人自己写个html,把前台脚本都删掉,这个时候就需要后台的验证
- 前台的两次密码相同处理不好,第一次输入密码的时候不应该有错误框。
- 前台的复杂验证未实现,可以用正则表达式。
总结
本次学习,一在练习bootstrap 和简单的JQuery,ajax,虽然以后从事后端,java代码熟悉。但是这些前台的东西,还是要了解的,不然你看着那个很丑的表格不难受吗?对吧。现在的知识很多,但是能慢慢学习的人却很少,所以 从什么时候开始学都不晚,我现在马上大四了,还在servlet+jsp期间,框架还没学,但是我相信只有把基础打牢,才能走得更远。共勉~