黑马旅游网 —— 登录/注册案例


前言

刚学习了一个Session案例,即服务器端会话技术案例,做完案例之后,
突然想将之前学习前端技术的案例和这个结合起来,于是就有了这个项目。

项目功能介绍

将tomcat集成到IDEA中,创建JavaEE项目,部署web项目,结合了Servlet、MySQL、JSP和Bootstrap技术,
简单实现以下功能:
1、未注册过的用户以游客身份浏览首页,
2、注册账号后,以用户身份跳转到首页,
- 如果用户名或密码均无输入,跳转注册页面,提示:用户名或密码错误
- 如果验证码输入有误,跳转注册页面,提示:验证码错误
3、登录账号后,以用户身份跳转到首页,
- 如果用户名和密码输入有误,跳转登录页面,提示:用户名或密码错误
- 如果验证码输入有误,跳转登录页面,提示:验证码错误
4、退出登录,回到游客身份跳转到首页。


一、创建一个web项目

1、先建立一个工程,创建web项目

2、修改虚拟目录名称,我一般设为web项目名称

二、浏览器页面部署

1.设置首页

1、游客首页

1、首页效果图

2、首页整体代码,结合Bootstrap编写在index.jsp里
3、页眉部分

4、主体部分



5、页脚部分

2.用户首页

1、首页展示效果图,只有以下这里发生了改变

2、代码实现,点击退出登录后,回到游客首页

2.登录页面

1、登录页面效果图,弄的比较随意

2、用户名或密码错误效果
①数据库用户数据

②用户名或密码输入错误

③登录结果

3、代码实现,结合了Servlet和MySQL技术实现,将代码写到login.jsp中

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>登录</title>
    <script>
        window.onload = function () {
            document.getElementById("img").onclick = function () {
                this.src="/yanshi/checkCodeServlet?time="+new Date().getTime();
            }
        }
    </script>
    <style>
        .error{
            color: red;
        }
    </style>
</head>
<body>

    <form action="/yanshi/loginServlet" method="post">
        <table>
            <tr>
                <td>用户名</td>
                <td>
                    <input type="text" name="username">
                </td>
            </tr>
            <tr>
                <td>密码</td>
                <td class="error">
                    <input type="text" name="password">
                    <%=request.getAttribute("login_error") == null ? "" : request.getAttribute("login_error")%>
                </td>
            </tr>
            <tr>
                <td>验证码</td>
                <td class="error">
                    <input type="text" name="checkCode">
                    <%=request.getAttribute("cc_error") == null ? "" : request.getAttribute("cc_error")%>
                </td>
            </tr>
            <tr>
                <td colspan="2"><img id="img" src="/yanshi/checkCodeServlet"></td>
            </tr>
            <tr>
                <td colspan="2"><input type="submit" value="登录"></td>
            </tr>
        </table>
    </form>

</body>
</html>

3.注册页面

1、注册页面效果图

①数据库用户数据

②注册时,用户名或密码无输入,或用户名与数据库的用户名重复


③注册结果

在这里插入图片描述

2、代码实现,本处只对用户名和密码进行数据库存储,其余数据没有存储,将代码编写到register.jsp中

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>注册</title>
    <script>
        window.onload = function () {
            document.getElementById("img_check").onclick = function () {
                this.src="/yanshi/checkCodeServlet?time="+new Date().getTime();
            };
        };
    </script>
    <style>
        *{
            margin: 0px;
            padding: 0px;
            box-sizing: border-box;
        }
        body{
            background: url("img/register_bg.png") no-repeat center;
            padding-top: 150px;
            background-size:cover;
        }

        .rg_layout{
            width: 900px;
            height: 500px;
            border: 8px solid #eeeeee;
            background-color: white;
            /*让div水平居中显示*/
            margin: auto;
            margin-bottom: 100px;
            box-sizing: border-box;
        }

        .rg_left{
            /*border: 1px solid red;*/
            float: left;
            margin: 15px;
        }
        .rg_left > p:first-child{
            color: #ffd026;
            font-size: 20px;
        }
        .rg_left > p:last-child{
            color: #a6a6a6;
            font-size: 20px;
        }

        .rg_center{
            /*border: 1px solid red;*/
            float: left;
            margin: 30px;
        }

        .rg_right{
            /*border: 1px solid red;*/
            float: right;
            margin: 25px;
        }
        .rg_right > p{
            font-size: 15px;
        }
        .rg_right p a{
            color: pink;
        }

        .td_left{
            width: 150px;
            height: 45px;
            text-align: right;
        }
        .td_right{
            padding-left: 20px;
        }
        #username,#password,#checkCode,#name,#birthday,#tel,#email{
            width: 175px;
            height: 32px;
            border: 1px solid #a6a6a6;
            /*设置边框圆角*/
            border-radius: 5px;
            padding-left: 10px;
        }
        #checkCode{
            width: 105px;
        }
        #img_check{
            height: 32px;
            vertical-align: middle;
        }
        #btn_sub{
            width: 150px;
            height: 40px;
            background-color: #ffd026;
            border: 1px solid #ffd026;
        }
        .error{
            color:red;
        }
        #td_sub{
            padding-left: 170px;
        }
    </style>
</head>
<body>
    <div class="rg_layout">
    <div class="rg_left">
        <p>新用户注册</p>
        <p>USER REGISTER</p>
    </div>
    <div class="rg_center">
        <div class="rg_form">
            <!--定义表单 form-->
            <form action="/yanshi/registerServlet" method="post">
                <table>
                    <tr>
                        <td class="td_left"><label for="username">用户名</label></td>
                        <td class="td_right error">
                            <input type="text" name="username" id="username" placeholder="请输入用户名">
                            <span id="s_username" class="error"></span>
                            <%=request.getAttribute("username_error") == null ? "" : request.getAttribute("username_error")%>
                        </td>
                    </tr>

                    <tr>
                        <td class="td_left"><label for="password">密码</label></td>
                        <td class="td_right error">
                            <input type="password" name="password" id="password" placeholder="请输入密码">
                            <span id="s_password" class="error"></span>
                            <%=request.getAttribute("password_error") == null ? "" : request.getAttribute("password_error")%>
                        </td>
                    </tr>

                    <tr>
                        <td class="td_left"><label for="email">Email</label></td>
                        <td class="td_right"><input type="email" name="email" id="email" placeholder="请输入邮箱"></td>
                    </tr>

                    <tr>
                        <td class="td_left"><label for="name">姓名</label></td>
                        <td class="td_right"><input type="text" name="name" id="name" placeholder="请输入姓名"></td>
                    </tr>

                    <tr>
                        <td class="td_left"><label for="tel">手机号</label></td>
                        <td class="td_right"><input type="text" name="tel" id="tel" placeholder="请输入手机号"></td>
                    </tr>

                    <tr>
                        <td class="td_left"><label>性别</label></td>
                        <td class="td_right">
                            <input type="radio" name="gender" value="male"><input type="radio" name="gender" value="female"></td>
                    </tr>

                    <tr>
                        <td class="td_left"><label for="birthday">出生日期</label></td>
                        <td class="td_right"><input type="date" name="birthday" id="birthday" placeholder="请输入出生日期"></td>
                    </tr>

                    <tr>
                        <td class="td_left"><label for="checkCode" >验证码</label></td>
                        <td class="td_right error"><input type="text" name="checkCode" id="checkCode" placeholder="请输入验证码">
                            <img id="img_check" src="/yanshi/checkCodeServlet">
                            <%=request.getAttribute("cc_error") == null ? "" : request.getAttribute("cc_error")%>
                        </td>
                    </tr>

                    <tr>
                        <td colspan="2" id="td_sub"><input type="submit" id="btn_sub" value="注册"></td>
                    </tr>
                </table>
            </form>
        </div>
    </div>
    <div class="rg_right">
        <p>已有账户?<a href="/yanshi/login.jsp">立即登录</a></p>
    </div>
</div>

</body>
</html>

三、Servlet编写

注册Servlet

package servlet;

import org.apache.commons.beanutils.BeanUtils;
import servlet.sql.dao.UserDao;
import servlet.sql.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.lang.reflect.InvocationTargetException;
import java.util.Map;

@WebServlet("/registerServlet")
public class registerServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //1.设置request编码
        request.setCharacterEncoding("utf-8");
        //2.1获取所有请求参数
        Map<String, String[]> map = request.getParameterMap();
        String checkCode = request.getParameter("checkCode");
        //2.2创建User对象
        User registerUser = new User();
        //2.3使用BeanUtils封装
        try {
            BeanUtils.populate(registerUser,map);
        } catch (IllegalAccessException | InvocationTargetException e) {
            e.printStackTrace();
        }

        //3.1先获取生成的验证码
        HttpSession session = request.getSession();
        String checkCode_session = (String)session.getAttribute("checkCode_session");
        //删除session中存储的验证码
        session.removeAttribute("checkCode_session");
        //3.2先判断验证码是否正确
        if (checkCode_session != null && checkCode_session.equalsIgnoreCase(checkCode)){
            //忽略大小写,验证码正确
            //判断用户名或密码是否有输入
            if ((registerUser.getUsername().length() & registerUser.getPassword().length()) != 0){
                //2.4创建UserDao对象
                UserDao dao = new UserDao();
                //2.4调用UserDao的login方法
                User login = dao.login(registerUser);
                //判断用户名是否存在
                if (registerUser.getUsername().equals(login.getUsername()) != true){
                    //注册成功
                    User user = dao.register(registerUser);
                    //存储信息,用户信息
                    session.setAttribute("user",user.getUsername());
                    //重定向到success.jsp
                    response.sendRedirect(request.getContextPath()+"/user_homepage.jsp");
                }else {
                    //注册失败
                    //存储提示信息到request
                    request.setAttribute("username_error", "用户名重复");
                    //转发到登录页面
                    request.getRequestDispatcher("/register.jsp").forward(request,response);
                }
            } else {
                //注册失败
                if (registerUser.getUsername().length() == 0){
                    //存储提示信息到request
                    request.setAttribute("username_error","用户名错误");
                }
                if (registerUser.getPassword().length() == 0){
                    //存储提示信息到request
                    request.setAttribute("password_error","密码错误");
                }
                //转发到登录页面
                request.getRequestDispatcher("/register.jsp").forward(request,response);
            }
        }else {
            //验证码不一致
            //存储提示信息到request
            request.setAttribute("cc_error","验证码错误");
            //转发到登录页面
            request.getRequestDispatcher("/register.jsp").forward(request,response);
        }
    }

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

登录Servlet

package servlet;

import org.apache.commons.beanutils.BeanUtils;
import servlet.sql.dao.UserDao;
import servlet.sql.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.lang.reflect.InvocationTargetException;
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 username = request.getParameter("username");
        String password = request.getParameter("password");*/
        //2.1获取所有请求参数
        Map<String, String[]> map = request.getParameterMap();
        String checkCode = request.getParameter("checkCode");
        //2.2创建User对象
        User loginUser= new User();
        //2.3使用BeanUtils封装
        try {
            BeanUtils.populate(loginUser,map);
        } catch (IllegalAccessException | InvocationTargetException e) {
            e.printStackTrace();
        }
        //2.4调用UserDao的login方法
        UserDao dao = new UserDao();
        User user = dao.login(loginUser);

        //3.1先获取生成的验证码
        HttpSession session = request.getSession();
        String checkCode_session = (String)session.getAttribute("checkCode_session");
        //删除session中存储的验证码
        session.removeAttribute("checkCode_session");
        //3.2先判断验证码是否正确
        if (checkCode_session != null && checkCode_session.equalsIgnoreCase(checkCode)){
            //忽略大小写,验证码正确
            //判断用户名和密码是否一致
            if (user != null){  //需要调用UserDao查询数据库
                //登录成功
                //存储信息,用户信息
                session.setAttribute("user",user.getUsername());
                //重定向到success.jsp
                response.sendRedirect(request.getContextPath()+"/user_homepage.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);
    }
}

验证码Servlet

package 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 {
        //简单形式,设置编码
        //response.setContentType("text/html;charset=utf-8");

        int width = 100;
        int height = 50;
        //1.创建一对象,在内存中代表图片(验证码对象)
        BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_3BYTE_BGR);

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

        //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/6*i,30);// y: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 < 5; 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);
    }
}

四、Java操作MySQL

1、用户的实体类

package servlet.sql.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 + '\'' +
                '}';
    }
}

2、JDBC工具类 使用Durids连接池

package servlet.sql.util;

import com.alibaba.druid.pool.DruidDataSourceFactory;

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工具类 使用Durids连接池
 */
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();
    }
}

3、操作数据库中User表的类

package servlet.sql.dao;

import org.springframework.dao.DataAccessException;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import servlet.sql.domain.User;
import servlet.sql.util.JDBCUtils;
/**
 * 操作数据库中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;
        }
    }

    /**
     * 注册方法
     * @param registerUser 只有用户名和密码
     * @return user包含用户全部数据,没有查询到,返回null
     */
    public User register(User registerUser){
        //1.定义sql语句
        String sql1 = "insert into user(username,password) values(?,?)";
        //2.调用方法实现
        Object[] args = {registerUser.getUsername(), registerUser.getPassword()};
        //3.执行sql
        template.update(sql1,args);
        return login(registerUser);
    }
}



4、配置文件

driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql:///test
username=root
password=root
initialSize=5
maxActive=10
maxWait=3000

五、其他

1、需要导入的jar包

2、IDEA整体项目布局

3、注册或登录时,首先判断验证码是否正确

①数据库用户数据

②验证码有误

③结果

登录同样,不再演示。

结尾

1、未实现的功能

在注册页面中,输入用户名和密码时,想进行一个表单的校验,
即输入用户名或密码时,鼠标移出输入框,点击鼠标时,会通过正则表达式来校验其用户名或密码的格式是否正确,若是则出现√,否则提示错误。
然后功能并未实现,没想明白

/*
分析:
    1.给表单绑定onsubmit事件。监听器中判断每一个方法校验的结果。
        如果都为true,则监听器方法返回true
        如果有一个为false,则监听器方法返回false
    2.定义一些方法分别校验各个表单项。
    3.给各个表单项绑定onblur事件。
*/
        window.onload = function(){
            //1.给表单绑定onsubmit事件
            document.getElementById("form").onsubmit = function(){
                //调用用户校验方法   chekUsername();
                //调用密码校验方法   chekPassword();
                //return checkUsername() && checkPassword();

                return checkUsername() && checkPassword();
            };
            //给用户名和密码框分别绑定离焦事件
            document.getElementById("username").onblur = checkUsername;
            document.getElementById("password").onblur = checkPassword;

        };

        //校验用户名
        function checkUsername(){
            //1.获取用户名的值
            var username = document.getElementById("username").value;
            //2.定义正则表达式
            var reg_username = /^\w{6,12}$/;
            //3.判断值是否符合正则的规则
            var flag = reg_username.test(username);
            //4.提示信息
            var s_username = document.getElementById("s_username");

            if(flag){
                //提示绿色对勾
                s_username.innerHTML = "<img width='35' height='25' src='img/gou.png'/>";
            }else{
                //提示红色用户名有误
                s_username.innerHTML = "用户名格式有误";
            }
            return flag;
        }

        //校验密码
        function checkPassword(){
            //1.获取用户名的值
            var password = document.getElementById("password").value;
            //2.定义正则表达式
            var reg_password = /^\w{6,12}$/;
            //3.判断值是否符合正则的规则
            var flag = reg_password.test(password);
            //4.提示信息
            var s_password = document.getElementById("s_password");

            if(flag){
                //提示绿色对勾
                s_password.innerHTML = "<img width='35' height='25' src='img/gou.png'/>";
            }else{
                //提示红色用户名有误
                s_password.innerHTML = "密码格式有误";
            }
            return flag;
        }

2、存在的Bug

思路:登录时,若用户名或密码输入错误,则对用户名或密码单独提醒。
结果:无法完成,若用户名或密码输入错误,只能对它们同时提醒。
思考:因为调用以下的查询数据库函数进行封装成User对象时,若从数据库中查询没有结果,则通过调用这个函数返回的结果是null,此时无法再通过调用User对象的getUsername方法或getPassword方法得到数据库中的值。

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;
        }
    }

3、项目总结

通过Java操作数据库还是很不熟练,对表单校验得操作也有点迷,还有首页很多功能未实现,还是得多学习一下吧。

  • 18
    点赞
  • 31
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值