JavaWeb登录案例带验证码(mysql+servlet+jsp+idea)

Java学习 专栏收录该内容
6 篇文章 0 订阅

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
    如果是跟着我的思路走的话

后记

本博客只是一个个人学习过程中的记录,写的可能会不太全面,如果看客们有问题,欢迎留言提问~~

  • 2
    点赞
  • 2
    评论
  • 21
    收藏
  • 打赏
    打赏
  • 扫一扫,分享海报

©️2022 CSDN 皮肤主题:1024 设计师:我叫白小胖 返回首页

打赏作者

Challow

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值