Java Web登录案例
Java Web课程应该是算学了一半了,今天做了一个登录的界面,还简单有一个验证码验证的实现。运用了许多前面的知识点,这里做一个简单的总结吧。以此记录学习内容。中间有些内容来源于itcast
案例分析
话不多说,先看一下这个超级简陋的登录界面(虽然写起来也不少代码)
登录成功:
实现的功能:
简单的登录界面,通过用户输入用户名、密码和验证码。通过验证验证码是否正确以及用户名和密码是否在数据库中存在,判断登录成功与否。
无情分割,正文开始
第一步
不妨先实现一个测试代码块,完成数据库与Java代码的关联。
0x00 创建数据库day14
- 当然也可以为其他名字,代码中相应位置做更改就行(建议不改,因为只是一个登录样例测试嘛)
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
);
然后添加一条数据就OK的。
0x01 创建User类,与数据库表中的数据属性相对应
package cn.challow.domain;
public class User {
private int id;
private String username;
private String password;
// 在idea中可以直接使用ALT+INSERT快捷键生成属性的getter和setter
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 + '\'' +
'}';
}
}
0x02 创建JDBCUtils工具类
package cn.challow.utils;
import com.alibaba.druid.pool.DruidDataSourceFactory;
import javax.sql.DataSource;
import java.io.IOException;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Properties;
/*
JDBC工具类,使用Druid连接池
* */
public class JDBCUtils {
private static DataSource ds;
static {
// 1. 加载配置文件
Properties prop = new Properties();
try {
// 使用ClassLoader加载配置文件,获取字节输入流
prop.load(JDBCUtils.class.getClassLoader().getResourceAsStream("druid.properties"));
// 初始化连接池对象
ds = DruidDataSourceFactory.createDataSource(prop);
} 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();
}
}
0x03 创建UserDao类,ps : DAO(Data Access Object)
package cn.challow.dao;
import cn.challow.domain.User;
import cn.challow.utils.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());
/*
登录方法:
参数:loginUser只有用户名和密码
返回值:user 包含用户的全部数据,如果没有查询到,返回null
*/
public User login(User loginUser){
try{
//1. 编写sql,查询user表中的数据
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; // 判断如果数据库总没有该用户就返回一个null
}
}
}
0x04 编写一个UserDaoTest测试类,测试UserDao类是否可以运行正确
package cn.itcast.test;
import cn.itcast.dao.UserDao;
import cn.itcast.domain.User;
import org.junit.Test;
public class UserDaoTest {
@Test // 测试类的一种写法,直接加注解就可以
public void testLogin(){
User loginuser = new User(); // 创建User类对象
loginuser.setUsername("superbaby"); // 设置loginUser的用户名和密码
loginuser.setPassword("123");
UserDao dao = new UserDao(); // 创建UserDao类对象
User user = dao.login(loginuser);// 通过调用类方法返回用户类型
System.out.println(user);
}
}
第一个测试点!!如果UserDaoTest可以正常运行的话就表明数据库与Java之间可以通过代码建立起一个桥梁了。
第二步
编写验证码生成类CheckCodeServlet类
package cn.challow.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);
// 验证码从str里面随机选取
String str = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghigklmnopqrstuvwxyz0123456789";
//生成随机角标
Random ran = new Random();
// 获取验证码并共享在session中,验证码为sb
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);
}
// 设置session的共享对象,设置方法类似于map的键值对
String checkCode_session = sb.toString();
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);
}
}
可以启动tomcat服务器来测试该类是否能够生成验证码。
第三步
编写前端jsp页面以及项目中最主要的代码逻辑,通过浏览器传递给服务器的参数来判断验证码和用户是否存在,这里使用到上面编写的类
0x01 编写前端代码login.jsp以及success.jsp
<%--
Created by IntelliJ IDEA.
User: Challow_
Date: 2020/12/6
Time: 19:57
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>login</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("checkCode_error") == null ? "" : request.getAttribute("checkCode_error")%></div>
<div><%= request.getAttribute("login_error") == null ? "" : request.getAttribute("login_error")%></div>
</body>
</html>
0x02 success.jsp
<%--
Created by IntelliJ IDEA.
User: Challow_
Date: 2020/12/6
Time: 20:45
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>success</title>
</head>
<body>
<h1><%=request.getSession().getAttribute("user")%>,欢迎您</h1>
</body>
</html>
0x03 LoginServlet类
package cn.challow.servlet;
import cn.challow.dao.UserDao;
import cn.challow.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 javax.servlet.http.HttpSession;
import java.io.IOException;
import java.util.Map;
@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 checkCode = null;
// 获取用户参数
User loginUser = new User();
// 获取请求头中的所有键值对参数
Map<String, String[]> map = request.getParameterMap();
for (String key : map.keySet()) {
// 通过遍历map中的键来获取对应中的参数值
String[] values = map.get(key);
for (String value : values) {
// 如果key是username,设置loginUser对象的用户名
if ("username".equals(key)) {
loginUser.setUsername(value);
} else if ("password".equals(key)) {
loginUser.setPassword(value);
} else if ("checkCode".equals(key)) {
checkCode = value;
}
}
}
// Debug使用,看服务器端是否能获取到客户端传递过来的参数
System.out.println(loginUser);
System.out.println(checkCode);
//3. 先获取生成的验证码
HttpSession session = request.getSession();
String checkCode_session = (String) session.getAttribute("checkCode_session");
// 删除session中存储的验证码
session.removeAttribute("checkCode_session");
// 4. 判断验证码是否相同
if(checkCode_session != null && checkCode_session.equalsIgnoreCase(checkCode)){
// 忽略大小写比较
// 1. 验证码正确的情况
// 判断用户名与密码是否一致
System.out.println("验证码正确");
UserDao dao = new UserDao();
User user = dao.login(loginUser); // 不为空说明数据库中有user对象
System.out.println(user);
if(user != null){
// 不为空说明数据库中存在此用户
// 存储信息,用户信息
session.setAttribute("user", user.getUsername());
// 重定向到success.jsp
response.sendRedirect(request.getContextPath() + "/success.jsp");
}else{
//登录失败
// 存储信息到request
request.setAttribute("login_error", "用户名或密码错误");
// 转发到登录页面
request.getRequestDispatcher("/login.jsp").forward(request, response);
}
}else{
System.out.println("验证码错误");
//2. 验证码不正确的情况下
// 存储信息到request
request.setAttribute("checkCode_error", "验证码错误");
// 转发到登录页面
request.getRequestDispatcher("/login.jsp").forward(request, response);
}
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
}
好了,到这里整个项目的代码都在这里了。下面说一些项目启动时的注意事项
项目运行注意事项
- 项目没有启动的原因很大程度上是一些小细节没有设置好,所以说简单说一下项目部署的细节
第一步
- new 一个module或者project出来
- 选择Web Application项目,web.xml对于本项目要不要都行
- 创建完成之后的一个空白项目大概是这个样子的
- 然后把该项目的虚拟目录改为day16,学习的时候更改了虚拟目录
第二步
- 将上面的代码移植到新建立的项目中
- 注意:文件的多级目录也要相应的建立,或自行更改!!
- 还有lib中的一些资源也要导进去,有需要的可以留言或者自行查找
- 还有一件事,就是druid.properties一定也要放到相应的位置,可以通过直接创建File文件复制粘贴,代码如下
driverClassName=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://127.0.0.1:3306/day14?serverTimezone=GMT%2B8
username=mysql数据库的用户名
password=mysql数据库的密码
initialSize=5
maxActive=10
maxWait=3000
其中的day14是数据库的名称,如果上面更改了的话需要自己更改。
- 提一点:页面的打开网址在
http://localhost:8080/day16/login.jsp
如果是跟着我的思路走的话