本文主要是用于记录原生的servlet生成验证码、前后端数据的获取,最终完成用户名、密码和验证码的验证。
一、验证码的生成
这个我其实在其他的博客也有写过,但是没有具体的使用,下面正式的使用一下。
验证码生成类
package com.service;
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("/ValidateCodeServlet")
public class ValidateCodeServlet extends HttpServlet {
private char[] codeSequence = {'A', '1', 'B', 'C', '2', 'D', '3', 'E', '4', 'F', '5', 'G', '6', 'H', '7', 'I', '8', 'J',
'K', '9', 'L', '1', 'M', '2', 'N', 'P', '3', 'Q', '4', 'R', 'S', 'T', 'U', 'V', 'W',
'X', 'Y', 'Z'};
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
int width = 76;
int height = 45;
Random random = new Random();
//设置response头信息
//禁止缓存
response.setHeader("Pragma", "No-cache");
response.setHeader("Cache-Control", "no-cache");
response.setDateHeader("Expires", 0);
//生成缓冲区image类
BufferedImage image = new BufferedImage(width, height, 1);
//产生image类的Graphics用于绘制操作
Graphics g = image.getGraphics();
//Graphics类的样式 背景颜色
g.setColor(new Color(16, 48, 77));
g.setFont(new Font("Times New Roman", 0, 25));
g.fillRect(0, 0, width, height);
//绘制干扰线
for (int i = 0; i < 20; i++) {
g.setColor(this.getColor(130, 200));
int x = random.nextInt(width);
int y = random.nextInt(height);
int x1 = random.nextInt(12);
int y1 = random.nextInt(12);
g.drawLine(x, y, x + x1, y + y1);
}
//绘制字符
String strCode = "";
for (int i = 0; i < 4; i++) {
String rand = String.valueOf(codeSequence[random.nextInt(codeSequence.length)]);
strCode = strCode + rand;
// g.setColor(new Color(20+random.nextInt(110),20+random.nextInt(110),20+random.nextInt(110)));
//设置字体颜色
g.setColor(new Color(255, 255, 255));
g.drawString(rand, 13 * i + 8, 30);
}
//将字符保存到session中用于前端的验证
request.getSession().setAttribute("authCode", strCode.toLowerCase());
g.dispose();
ImageIO.write(image, "JPEG", response.getOutputStream());
response.getOutputStream().flush();
}
public Color getColor(int fc, int bc) {
Random random = new Random();
if (fc > 255)
fc = 255;
if (bc > 255)
bc = 255;
int r = fc + random.nextInt(bc - fc);
int g = fc + random.nextInt(bc - fc);
int b = fc + random.nextInt(bc - fc);
return new Color(r, g, b);
}
}
用以上的代码可以生成一个验证码图片和并将生成的验证码(即数字和字母保存到session
中),只需要插入到前端界面就可以看见。
下面是前端页面
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>首页</title>
<script src="js/jquery-1.8.3.js"></script>
</head>
<body>
<h1>欢迎来到登录</h1>
<form action="/firstWeb/CookieHomework02" method="get" >
用户名:<input type="text" name="name"/><br/>
密码:<input type="text" name="password"/><br/>
<input type="text" name="validationCode" style="width: 50px;height: 20px"/>
<img src="/firstWeb/ValidateCodeServlet" id="validationCode" ><br/>
<input type="submit" value="登录"/>
</form>
<script>
//这里主要是用于刷新验证码图片,
$('#validationCode').click(function () {
//加上时间戳就可以和原来的额src地址有区别,如果他们两个地址没有区别,浏览器默认是同一个,并不会刷新验证码图片
$(this).attr('src','/firstWeb/ValidateCodeServlet?time='+ new Date().getTime());
});
</script>
<a href="/firstWeb/html/homeword.html">没有账户?注册一个</a>
</body>
</html>
下面来写servlet
package com.homework;
import com.service01.User;
import com.util.BeanUtil;
import com.util.JDBCUtil;
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.List;
@WebServlet("/CookieHomework02")
public class CookieHomework02 extends HttpServlet {
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//设置字符集
req.setCharacterEncoding("utf-8");
resp.setContentType("text/html;charset=UTF-8");
User user = BeanUtil.formToBean(User.class, req.getParameterMap());
// 获取从前端获取用户输入的验证码
String validationCode = req.getParameter("validationCode");
// 获取session
HttpSession session = req.getSession();
// 从验证码中获取验证码
String validation_code = (String) session.getAttribute("authCode");
//将两个验证码作比较,看是否一直,equalsIgnoreCase() 方法用于将字符串与指定的对象比较,不考虑大小写
if (validationCode.equalsIgnoreCase(validation_code)) {
//验证码正确,在开始验证用户名和密码
//selectUser(user)返回一个list集合,只要是集合长度大于1说明有该用户
if(selectUser(user).size()>0){
req.setAttribute("name",user.getName());
req.getRequestDispatcher("/success.jsp").forward(req, resp);
}else {
// 否则的话就说明是验证码正确,但是用户名或者是密码错误。
System.out.println("用户名或者是密码错误!");
}
} else {
//验证失败的话,直接转到
System.out.println("验证码错误");
}
}
private List<User> selectUser(User user) {
String sql = "select name,password from t_user where name=? and password = ? ";
return JDBCUtil.queryByCondition(User.class, sql,user.getName(), user.getPassword());
}
}
以上的代码涉及到两个工具类,其实我其他的博客都有些,这里在贴一下
BeanUtil
类
package com.util;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.beanutils.ConvertUtils;
import org.apache.commons.beanutils.Converter;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Map;
public class BeanUtil {
//直接将页面表单数据给封装到Bean对象中,但是日期必须是"yyyy-MM-dd"
public static <T> T formToBean(Class<T> clazz, Map<String,String[]> map){
T t = null;
try {
t = clazz.newInstance();
ConvertUtils.register(new Converter() {
//o:页面输入的日期
@Override
public Object convert(Class aClass, Object o) {
//判断日期是否null ***** ""
if(o == null){
return null;
}
//指定页面输入的日期格式
String pattern = "yyyy-MM-dd";
SimpleDateFormat sdf = new SimpleDateFormat(pattern);
try {
return sdf.parse(o.toString());
} catch (ParseException e) {
e.printStackTrace();
}
return null;
}
}, Date.class);
BeanUtils.populate(t,map);
} catch (Exception e) {
e.printStackTrace();
}
return t;
}
}
JDBCUtil
类
package com.util;
import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.pool.DruidDataSourceFactory;
import com.alibaba.druid.pool.DruidPooledConnection;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.beanutils.ConvertUtils;
import org.apache.commons.beanutils.Converter;
import java.io.IOException;
import java.io.InputStream;
import java.io.Serializable;
import java.lang.reflect.Constructor;
import java.sql.*;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.*;
public class JDBCUtil {
private static DruidDataSource dataSource;
private static Properties properties;
static {
InputStream inputStream =
com.util.JDBCUtil.class.getClassLoader().getResourceAsStream("db.properties");
properties = new Properties();
try {
properties.load(inputStream);
dataSource = (DruidDataSource) DruidDataSourceFactory.createDataSource(properties);
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
//获取数据库连接
public static Connection getConnection(){
DruidPooledConnection connection = null;
try {
connection = dataSource.getConnection();
} catch (SQLException e) {
e.printStackTrace();
}
return connection;
}
//关闭流 增删改
public static void close(Connection connection, PreparedStatement ps){
if(connection != null){
//alt+enter
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(ps != null){
//alt+enter
try {
ps.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
//关闭流 增删改
public static void close(Connection connection, PreparedStatement ps,ResultSet rs){
if(connection != null){
//alt+enter
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(ps != null){
//alt+enter
try {
ps.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(rs != null){
//alt+enter
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
//增删改通用方法
public static boolean update(Connection connection,String sql,Object...params){
//获取连接
PreparedStatement ps = null;
try{
ps = connection.prepareStatement(sql);
//设置参数
for(int i = 0; i < params.length; i++){
ps.setObject(i + 1,params[i]);
}
int result = ps.executeUpdate();
return result > 0;
}catch (Exception e){
e.printStackTrace();
}
return false;
}
//通用的查询方法 单表不带条件的,带条件的
public static <T> List<T> queryByCondition(Class<T> clazz,String sql,Object...params){
Connection conn = com.util.JDBCUtil.getConnection();
PreparedStatement ps = null;
ResultSet rs = null;
List<T> list= new ArrayList<>();
try{
ps = conn.prepareStatement(sql);
//设置参数
for(int i = 0; i < params.length; i++){
ps.setObject(i + 1,params[i]);
}
rs = ps.executeQuery();
//需要知道查询结果集的列名
ResultSetMetaData metaData = rs.getMetaData();
//用于存储每次查询列的结果集
Map<String,Object> data = new HashMap<>();
//遍历查询的结果集
while(rs.next()){
T t = clazz.newInstance();
for(int i = 0; i < metaData.getColumnCount(); i++){
String name = metaData.getColumnName(i+1).toLowerCase();
Object value = rs.getObject(name);
data.put(name,value);
}
ConvertUtils.register(new Converter() {
//o:页面输入的日期
@Override
public Object convert(Class aClass, Object o) {
//判断日期是否null ***** ""
if(o == null){
return null;
}
//指定页面输入的日期格式
String pattern = "yyyy-MM-dd";
SimpleDateFormat sdf = new SimpleDateFormat(pattern);
try {
return sdf.parse(o.toString());
} catch (ParseException e) {
e.printStackTrace();
}
return null;
}
}, Date.class);
//将Map中的数据放入到对象中
BeanUtils.populate(t,data);
list.add(t);
}
}catch (Exception e){
e.printStackTrace();
}
return list;
}
//根据主键查询
//Serializable:可以序列化 可以通过网络传输对象
public static <T> T queryByPrimaryKey(Class<T> clazz, String sql, Serializable primaryKey){
Connection connection = getConnection();
PreparedStatement ps = null;
ResultSet rs = null;
T t = null;
try{
//根据字节码得到该对象的实例
//要求:原类的构造方法必须是public
// t = clazz.newInstance();
//如果构造方法私有化
Constructor<T> constructor = clazz.getDeclaredConstructor();
t = constructor.newInstance();
// System.out.println("t======"+t);
ps = connection.prepareStatement(sql);
ps.setObject(1,primaryKey);
rs = ps.executeQuery();
//元数据
ResultSetMetaData metaData = rs.getMetaData();
if(!rs.next())
return null;
for(int i = 0; i < metaData.getColumnCount(); i++){
String columnName = metaData.getColumnName(i + 1).toLowerCase();
Object value = rs.getObject(columnName);
BeanUtils.setProperty(t,columnName,value);
}
}catch (Exception e){
e.printStackTrace();
}
// System.out.println("t="+t);
//t是通过反射
return t;
}
//查询总记录数(包含条件) 为分页服务的 limit a,b
//a = (page - 1) * b
public static int count(String sql,Object...params){
Connection connection = getConnection();
PreparedStatement ps = null;
ResultSet rs = null;
try{
ps = connection.prepareStatement(sql);
for(int i = 0 ; i < params.length; i++){
ps.setObject(i + 1,params[i]);
}
rs = ps.executeQuery();
rs.next();
return rs.getInt(1);
}catch (Exception e){
e.printStackTrace();
}
return 0;
}
/*
多表带条件和不带条件的查询结果集封装
该查询结果集全部封装到map中,和实体类没有关系
*/
public static List<Map<String,Object>> queryByCondition(String sql,Object...params){
Connection connection = getConnection();
PreparedStatement ps = null;
ResultSet rs = null;
List<Map<String,Object>> list = new ArrayList<>();
try {
ps = connection.prepareStatement(sql);
//设置参数
for(int i = 0; i < params.length; i++){
ps.setObject(i + 1,params[i]);
}
rs = ps.executeQuery();
//需要知道查询结果集的列名
ResultSetMetaData metaData = rs.getMetaData();
//遍历查询的结果集
while(rs.next()){
//用于存储每次查询列的结果集
Map<String,Object> data = new HashMap<>();
for(int i = 0; i < metaData.getColumnCount(); i++){
String name = metaData.getColumnName(i+1).toLowerCase();
Object value = rs.getObject(name);
data.put(name,value);
}
list.add(data);
}
}catch (Exception e){
e.printStackTrace();
}
return list;
}
//分页多条件复杂查询结果集封装,适合单表和多表查询
//将所有查询结果集都放到一个List<Map<>>
public static List<Map<String,Object>> pagination(String page,int pageSize,String sql,Object...params){
int pageNum = 0;
if(page == null){
pageNum = 1;
}else{
pageNum = Integer.parseInt(page);
}
sql += " limit "+(pageNum-1)*pageSize+","+pageSize+"";
return queryByCondition(sql,params);
}
}
实体类:User
类
package com.service01;
public class User {
private String name;
private String password;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
", password='" + password + '\'' +
'}';
}
}
登录成功页面success.jsp
<%--
Created by IntelliJ IDEA.
User: y1833
Date: 2020/9/4
Time: 15:55
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>登录成功</title>
<h1>欢迎${name}登录系统</h1>
</head>
<body>
</body>
</html>
最后看一下数据库的表
最后将项目配置到tomcat
中运行,效果图如下:
接下来是: