HTTP案例学习:用户登录&验证码

本笔记包括两个案例,分别是用户登录、验证码


案例:用户登录

接着 《HTTP:超文本传输协议》《HTTP请求信息数据 - Request》 的学习,
现在记录一份案例学习。

用户需求

  1. 编写 login.html 登录页面,并且有 username & password 两个输入框
  2. 使用 Druid 数据库连接池技术,操作 MySQL,day14数据库中user表
  3. 使用 JdbcTemplate 技术封装 JDBC
  4. 登录成功跳转到 SuccessServlet 展示:登录成功!用户名,欢迎您
  5. 登录失败跳转到 FailServlet 展示:登录失败,用户名或密码错误

分析

HTTP案例学习:用户登录&验证码

步骤

  1. 创建项目,导入html页面,配置文件,jar包

  2. 创建数据库环境

  3. 创建包cn.itcast.domain,创建类User

  4. 创建包cn.itcast.util,编写工具类JDBCUtils

  5. 创建包cn.itcast.dao,创建类UserDao,提供login方法

  6. 编写cn.itcast.web.servlet.LoginServlet类

  7. 编写FailServlet和SuccessServlet类

  8. BeanUtils工具类,简化数据封装

一、创建项目,导入html页面,配置文件,jar包

  1. 新建Module

HTTP案例学习:用户登录&验证码

  1. web文件夹下创建login.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>用户登录</title>
</head>
<body>
<form action="/day14_test/loginServlet" method="post">
用户名:<input type="text" name="username"> <br>
密码:<input type="password" name="password"><br>

<input type="submit" value="登录">

</form>
</body>
</html>

这里的login.html中form表单的action路径的写法:虚拟目录+Servlet的资源路径
虚拟目录+Servlet的资源路径

关于 《html中form表单的action路径的写法》

  1. 将Druid配置文件druid.properties导入到src文件下
1
2
3
4
5
6
7
driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql:///day14
username=root
password=root
initialSize=5
maxActive=10
maxWait=3000
  1. 导入jar包到Web的WEB-INF文件中

HTTP案例学习:用户登录&验证码

在项目的web文件夹下创建文件夹WEB-INF,将lib文件夹粘贴进去

HTTP案例学习:用户登录&验证码

并把jar包加入到工作空间里

HTTP案例学习:用户登录&验证码

二、创建数据库环境

  1. 打开Navicat,创建数据库和数据表
1
2
3
4
5
6
7
8
CREATE DATABASE	day14;
USE day14;

CREATE TABLE USER(
id INT PRIMARY KEY AUTO_INCREMENT,
username VARCHAR(32) UNIQUE NOT NULL,
PASSWORD VARCHAR(32) NOT NULL
);

HTTP案例学习:用户登录&验证码

  1. 插入一条记录

HTTP案例学习:用户登录&验证码

三、创建包cn.itcast.domain,创建类User

  1. 右键项目的src文件,New一个包cn.itcast.domain

  2. 在包下,New一个User.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
package cn.itcast.domain;

/**
* 用户的实体类
*/
public class User {

private int id;
private String username;
private String password;

public int getId() {
return id;
}

public void setId(int id) {
this.id = id;
}

public String getUsername() {
return username;
}

public void setUsername(String username) {
this.username = username;
}

public String getPassword() {
return password;
}

public void setPassword(String password) {
this.password = password;
}

@Override
public String toString() {
return "User{" +
"id=" + id +
", username='" + username + '\'' +
", password='" + password + '\'' +
'}';
}
}

四、创建包cn.itcast.util,编写工具类JDBCUtils

  1. New一个包cn.itcast.util

  2. New一个JDBCUtils.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
package cn.itcast.util;

import com.alibaba.druid.pool.DruidDataSourceFactory;

import javax.sql.ConnectionEvent;
import javax.sql.DataSource;
import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Properties;

/**
* JDBC的工具类 使用Durid连接池
*/
public class JDBCUtils {

private static DataSource ds;

static {

try {
//1.加载配置文件
Properties pro = new Properties();
//使用ClassLoader加载配置文件,获取字节输入流
InputStream is = JDBCUtils.class.getClassLoader().getResourceAsStream("druid.properties");
pro.load(is);

//2.初始化连接池对象
ds = DruidDataSourceFactory.createDataSource(pro);
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}


}

/**
* 获取连接池对象
*/
public static DataSource getDataSource(){
return ds;
}

/**
* 获取连接池Connection对象
*/
public static Connection getConnection() throws SQLException {
return ds.getConnection();
}
}

五、创建包cn.itcast.dao,创建类UserDao,提供login方法

  1. New一个包cn.itcast.dao
  2. New一个UserDao.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
package cn.itcast.Dao;

import cn.itcast.domain.User;
import cn.itcast.util.JDBCUtils;
import com.alibaba.druid.util.JdbcUtils;
import org.springframework.dao.DataAccessException;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;

/**
* 操作数据库中User表的类
*/
public class UserDao {

// 声明JDBCTemplate对象公用
private JdbcTemplate template = new JdbcTemplate(JDBCUtils.getDataSource());
/**
* 登录方法
* @param loginUser 只有用户名和密码
* @return User包含用户全部数据;没有查询到,返回null
*/
public User login(User loginUser) {
try {
//1.编写SQL
String sql = "select * from user where username = ? and password = ?";
//2.调用query方法
User user = template.queryForObject(sql,
new BeanPropertyRowMapper<User>(User.class),
loginUser.getUsername(), loginUser.getPassword());
return user;
} catch (DataAccessException e) {
e.printStackTrace(); // 记录日志,后期写入文件里,不会总在控制台打印
return null;
}
}
}
  1. 测试一下UserDao
  2. New一个包cn.itcast.test,New一个UserDaoTest.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
package cn.itcast.test;

import cn.itcast.Dao.UserDao;
import cn.itcast.domain.User;
import org.junit.Test;

/**
* @Classname UserDaoTest
* @Description TODO
* @Date 2020/2/23 下午 1:00
* @Created by jerry
*/
public class UserDaoTest {
@Test
public void testLogin(){

User loginuser = new User();
loginuser.setUsername("superbaby");
loginuser.setPassword("123");

UserDao dao = new UserDao();
User user = dao.login(loginuser);

System.out.println(user);
}

}
  1. run后,控制台输出

HTTP案例学习:用户登录&验证码

  1. 这个@Test部分,遇到了一些问题,就顺便记录在《创建@Test测试Druid连接池时的问题》 里面。

六、编写cn.itcast.web.servlet.LoginServlet类

  1. New一个包cn.itcast.web.servlet
  2. New一个LoginServlet.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
package cn.itcast.web.servlet;

import cn.itcast.Dao.UserDao;
import cn.itcast.domain.User;
import cn.itcast.test.UserDaoTest;

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;

@WebServlet("/loginServlet")
public class LoginServlet extends HttpServlet {

@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//1.设置编码
req.setCharacterEncoding("utf-8");
//2.获取请求参数
String username = req.getParameter("username");
String password = req.getParameter("password");
//3.封装user对象
User loginUser = new User();
loginUser.setUsername("username");
loginUser.setPassword("password");

//4.调用UserDao的login方法
UserDao dao = new UserDao();
User user = dao.login(loginUser); //真正获取到的user

//5.判断user
if(user == null){
//登录失败
req.getRequestDispatcher("/failServlet").forward(req,resp); //转发
}else{
//登录成功
//存储数据
req.setAttribute("user",user);
//转发
req.getRequestDispatcher("/successServlet").forward(req,resp);
}

}

@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doGet(req,resp);
}
}

七、编写FailServlet和SuccessServlet类

  1. New一个FailServlet.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
package cn.itcast.web.servlet;

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;

/**
* @Classname failServlet
* @Description TODO
* @Date 2020/2/23 下午 3:38
* @Created by jerry
*/
@WebServlet("/failServlet")
public class FailServlet extends HttpServlet {

@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request,response);
}

@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//给页面写一句话

//设置页面编码
response.setContentType("text/html;charset=utf-8");
//输出
response.getWriter().write("登录失败,用户名或密码错误");
}

}
  1. New一个SuccessServlet.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
package cn.itcast.web.servlet;

import cn.itcast.domain.User;

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;

/**
* @Classname successServlet
* @Description TODO
* @Date 2020/2/23 下午 3:38
* @Created by jerry
*/
@WebServlet("/successServlet")
public class SuccessServlet extends HttpServlet {

@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request,response);
}

@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//获取request域*享的user对象
User user = (User) request.getAttribute("user");

if(user != null){
//给页面写一句话

//设置页面编码
response.setContentType("text/html;charset=utf-8");
//输出
response.getWriter().write("登录失败,用户名或密码错误");
}

}

}

八、测试

浏览器访问:http://localhost/day14_test/login.html

HTTP案例学习:用户登录&验证码

HTTP案例学习:用户登录&验证码

九、BeanUtils工具类,简化数据封装

  • 在LoginServlet.java中使用BeanUtils工具类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
package cn.itcast.web.servlet;

import cn.itcast.Dao.UserDao;
import cn.itcast.domain.User;
import cn.itcast.test.UserDaoTest;
import org.apache.commons.beanutils.BeanUtils;

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.lang.reflect.InvocationTargetException;
import java.util.Map;

@WebServlet("/loginServlet")
public class LoginServlet extends HttpServlet {

@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//1.设置编码
req.setCharacterEncoding("utf-8");
/*//2.获取请求参数
String username = req.getParameter("username");
String password = req.getParameter("password");
//3.封装user对象
User loginUser = new User();
loginUser.setUsername(username);
loginUser.setPassword(password);*/

//2.获取所有请求参数
Map<String, String[]> map = req.getParameterMap();
//3.创建User对象
User loginUser = new User();
//3-2.使用BeanUtils封装
try {
BeanUtils.populate(loginUser,map);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}

//4.调用UserDao的login方法
UserDao dao = new UserDao();
User user = dao.login(loginUser); //真正获取到的user

//5.判断user
if(user == null){
//登录失败
req.getRequestDispatcher("/failServlet").forward(req,resp); //转发
}else{
//登录成功
//存储数据
req.setAttribute("user",user);
//转发
req.getRequestDispatcher("/successServlet").forward(req,resp);
}

}

@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doGet(req,resp);
}
}

与本笔记相关的资源

链接: https://pan.baidu.com/s/1pV1ArOotLcoH9mKYABEm5g 提取码: w9h8


案例:验证码

接着 《JSP&Cookie&Session技术》 的学习,

现在记录一份案例的学习。

用户需求

  1. 访问带有验证码的登录页面login.jsp

  2. 用户输入用户名,密码以及验证码,

    • 如果用户名和密码输入有误,跳转登录页面,提示:用户名或密码错误

    • 如果验证码输入有误,跳转登录页面,提示:验证码错误

    • 如果全部输入正确,则跳转到主页success.jsp,显示:用户名,欢迎您

分析

  1. 设置request编码

  2. 获取参数

  3. 获取生成的验证码

  4. 将用户信息封装到User对象

  5. 判断程序生成的验证码和用户输入的验证码是否一致。从session中获取程序生成的验证码

  6. 一致:再判断用户名和密码是否正确

    • 正确:
      • 1.登陆成功
      • 2.存储数据到session中
      • 3.跳转(重定向)到success.jsp
    • 不正确:
      • 1.给提示信息:用户名或密码错误
      • 2.跳转(转发)到登录页面
  7. 不一致:

    • 1.给用户提示信息:验证码错误
    • 2.存储提示信息到request
    • 3.跳转(转发)到登录页面
  8. login.jsp显示错误信息,从request域中获取

Code

CheckCodeServlet.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
package cn.itcast.servlet;

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 java.awt.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.Random;

@WebServlet("/checkCodeServlet")
public class CheckCodeServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {


int width = 100;
int height = 50;

//1.创建一对象,在内存中图片(验证码图片对象)
BufferedImage image = new BufferedImage(width,height,BufferedImage.TYPE_INT_RGB);


//2.美化图片
//2.1 填充背景色
Graphics g = image.getGraphics();//画笔对象
g.setColor(Color.PINK);//设置画笔颜色
g.fillRect(0,0,width,height);

//2.2画边框
g.setColor(Color.BLUE);
g.drawRect(0,0,width - 1,height - 1);

String str = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghigklmnopqrstuvwxyz0123456789";
//生成随机角标
Random ran = new Random();
StringBuilder sb = new StringBuilder();
for (int i = 1; i <= 4; i++) {
int index = ran.nextInt(str.length());
//获取字符
char ch = str.charAt(index);//随机字符
sb.append(ch);

//2.3写验证码
g.drawString(ch+"",width/5*i,height/2);
}
String checkCode_session = sb.toString();
//将验证码存入session
request.getSession().setAttribute("checkCode_session",checkCode_session);

//2.4画干扰线
g.setColor(Color.GREEN);

//随机生成坐标点

for (int i = 0; i < 10; i++) {
int x1 = ran.nextInt(width);
int x2 = ran.nextInt(width);

int y1 = ran.nextInt(height);
int y2 = ran.nextInt(height);
g.drawLine(x1,y1,x2,y2);
}


//3.将图片输出到页面展示
ImageIO.write(image,"jpg",response.getOutputStream());


}

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request,response);
}
}

login.jsp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>用户登录</title>

<!--点击刷新验证码-->
<script>
window.onload = function(){
document.getElementById("img").onclick = function(){
this.src="/day16/checkCodeServlet?time="+new Date().getTime();
}
}


</script>
<style>
div{
color: red;
}

</style>
</head>
<body>

<form action="/day16/loginServlet" method="post">
<table>
<tr>
<td>用户名</td>
<td><input type="text" name="username"></td>
</tr>
<tr>
<td>密码</td>
<td><input type="password" name="password"></td>
</tr>
<tr>
<td>验证码</td>
<td><input type="text" name="checkCode"></td>
</tr>
<tr>
<td colspan="2"><img id="img" src="/day16/checkCodeServlet"></td>
</tr>
<tr>
<td colspan="2"><input type="submit" value="登录"></td>
</tr>
</table>


</form>

<div><%=request.getAttribute("cc_error") == null ? "" : request.getAttribute("cc_error")%></div>
<div><%=request.getAttribute("login_error") == null ? "" : request.getAttribute("login_error") %></div>

<!-- 等同于 EL表达式。有信息就打印输出,没有就显示空字符串。
${requestScope.cc_error}
${requestScope.login.error}
-->

</body>
</html>

LoginServlet.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
package cn.itcast.servlet;

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.io.IOException;

@WebServlet("/loginServlet")
public class LoginServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//1.设置request编码
request.setCharacterEncoding("utf-8");
//2.获取参数
String username = request.getParameter("username");
String password = request.getParameter("password");
String checkCode = request.getParameter("checkCode");
//3.先获取生成的验证码
HttpSession session = request.getSession();
String checkCode_session = (String) session.getAttribute("checkCode_session");
//删除session中存储的验证码
session.removeAttribute("checkCode_session");
//3.先判断验证码是否正确
if(checkCode_session!= null && checkCode_session.equalsIgnoreCase(checkCode)){
//忽略大小写比较
//验证码正确
//判断用户名和密码是否一致
if("zhangsan".equals(username) && "123".equals(password)){//需要调用UserDao查询数据库
//登录成功
//存储信息,用户信息
session.setAttribute("user",username);
//重定向到success.jsp
response.sendRedirect(request.getContextPath()+"/success.jsp");
}else{
//登录失败
//存储提示信息到request
request.setAttribute("login_error","用户名或密码错误");
//转发到登录页面
request.getRequestDispatcher("/login.jsp").forward(request,response);
}


}else{
//验证码不一致
//存储提示信息到request
request.setAttribute("cc_error","验证码错误");
//转发到登录页面
request.getRequestDispatcher("/login.jsp").forward(request,response);

}

}

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
}

success.jsp

1
2
3
4
5
6
7
8
9
10
11
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>成功登录</title>
</head>
<body>

<h1><%=request.getSession().getAttribute("user")%>,欢迎您</h1>

</body>
</html>

Demo

HTTP案例学习:用户登录&验证码

HTTP案例学习:用户登录&验证码

视频详解