javaweb案例:实现注册和登录功能

业务需求分析

在实际开发中,通常会有专门的人去跟客户进行沟通从而了解客户需要什么样的系统,之后由专业的美工将要做的系统以图片的形式表现出来,客户确认后作出一些静态的html demo页面,然后由软件开发人员创建相关数据库,编写代码将该静态页面做成动态页面,由测试人员通过测试后将其交付给客户使用。
这里主要以学习为目的,所以简化一些流程,通常一般的注册和登录都由下面几个页面组成:

  • 注册页面:没有用户名时,首先需要在该页面注册成功之后才可进行登录操作,用户所提交的数据要持久化到数据库中。
  • 登录页面:用户输入用户名和密码提交给后台处理。
  • 登录成功页面:根据输入的用户名和密码去数据库中查找匹配的数据,如果存在则跳转登录成功页面,否则提示用户登录失败。

静态页面如下:
百度网盘地址:https://pan.baidu.com/s/1IEimd9Gnr57qtEhADZOxKg

用户注册页面regist.html:

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>注册</title>
</head>
<body>
    <form action="" method="post">
    <table>
        <tr>
            <td>用&nbsp;户&nbsp;名&nbsp;:</td><td><input type="text" name="name" value=""/></td>
        </tr>
        <tr>
            <td>密&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;码&nbsp;:</td><td><input type="password" name="password" /></td>
        </tr>
        <tr>
            <td>确认密码:</td><td><input type="password" name="repassword"/></td>
        </tr>
        <tr>
            <td>邮&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;箱&nbsp;:</td><td><input type="text" name="email" /></td>
        </tr>
        <tr>
            <td>生&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;日&nbsp;:</td><td><input type="text" name="birthday" /></td>
        </tr>
    </table>
        <input type="submit" value="注册"/><br/>
    </form>
</body>
</html>

用户登录页面login.html:

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>首页</title>
</head>
<body>
    <form action="" method="post">
        <table>
            <tr>
                <td>用户名:</td><td><input type="text" name="name"/></td>
            </tr>
            <tr>
                <td>密&nbsp;&nbsp;&nbsp;码:</td><td><input type="password" name="password"/></td>
            </tr>
        </table>
        <input type="submit" value="登录"/><br/>
    </form>
    没有用户名?点此<a href="">注册</a>
</body>
</html>

登录成功页面:

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>登录成功</title>
</head>
<body>
    欢迎你:刘德华<br>
    <a href="">注销</a>
</body>
</html>

开发前的准备

数据库的设计,该功能比较简单,使用一张表就能完成业务逻辑,创建一个名为t_user的表,语句如下:

CREATE TABLE 't_user' (
  'id' INT NOT NULL AUTO_INCREMENT,
  'name' VARCHAR(45) NOT NULL,
  'password' VARCHAR(45) NULL,
  'email' VARCHAR(45) NULL,
  'birthday' DATE NULL,
  PRIMARY KEY ('id'));

搭建web开发环境:
在IDEA中创建一个web项目,因为要使用jdbc,因此将数据库驱动相关的jar包加入到项目中。
根据分层的开发思想,创建以下包名:

  • com.monkey1024.bean
  • com.monkey1024.servlet
  • com.monkey1024.service
  • com.monkey1024.service.impl
  • com.monkey1024.dao
  • com.monkey1024.dao.impl
  • com.monkey1024.util

在src下创建db.properties

driverClass=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/m-login
username=root
password=monkey1024

在com.monkey1024.util包下创建数据库工具类DBUtil:

package com.monkey1024.util;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.ResourceBundle;

public class DBUtil {

    private static String driverClass;
    private static String url;
    private static String username;
    private static String password;

    static{
        ResourceBundle rb = ResourceBundle.getBundle("db");
        driverClass = rb.getString("driverClass");
        url = rb.getString("url");
        username = rb.getString("username");
        password = rb.getString("password");
        try {
            //注册驱动
            Class.forName(driverClass);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }

    public static Connection getConnection() throws SQLException{
        return DriverManager.getConnection(url, username, password);
    }
}

在com.monkey1024.bean包下创建实体类User:

package com.monkey1024.bean;

import java.util.Date;

/**
 * 用户表(t_user)
 *
 */
public class User {

    private int id;
    private String name;
    private String password;
    private String email;
    private Date birthday;

    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    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;
    }
    public String getEmail() {
        return email;
    }
    public void setEmail(String email) {
        this.email = email;
    }
    public Date getBirthday() {
        return birthday;
    }
    public void setBirthday(Date birthday) {
        this.birthday = birthday;
    }
}

实现注册功能

注册功能需要向数据库中添加数据,首先在com.monkey1024.dao包下创建接口UserDao:

package com.monkey1024.dao;

import com.monkey1024.bean.User;

/**
 * 用户dao
 *
 */
public interface UserDao {

    /**
     * 添加用户信息
     * @param user
     * @throws Exception
     */
    public void addUser(User user) throws Exception;
}

在com.monkey1024.dao.impl包下创建接口UserDao的实现类UserDaoImpl,该类中的addUser方法主要实现向数据库插入的功能:

package com.monkey1024.dao.impl;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.text.SimpleDateFormat;

import com.monkey1024.bean.User;
import com.monkey1024.dao.UserDao;
import com.monkey1024.util.DBUtil;

public class UserDaoImpl implements UserDao {

    @Override
    public void addUser(User user) throws Exception {
        Connection conn = null;
        PreparedStatement ps = null;
        try {
            conn = DBUtil.getConnection();
            ps = conn.prepareStatement("INSERT INTO t_user(name,password,email,birthday) VALUES(?,?,?,?)");
            ps.setString(1, user.getName());
            ps.setString(2, user.getPassword());
            ps.setString(3, user.getEmail());
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
            String birthday = sdf.format(user.getBirthday());
            ps.setString(4, birthday);
            ps.executeUpdate();
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException("添加失败!");
        }
    }

}

在com.monkey1024.service包下创建UserService接口:

package com.monkey1024.service;

import com.monkey1024.bean.User;

public interface UserService {

    /**
     * 添加用户信息
     * @param user
     * @throws Exception
     */
    public void addUser(User user) throws Exception;

}

在com.monkey1024.service.impl包下创建UserServiceImpl实现类:

package com.monkey1024.service.impl;

import com.monkey1024.bean.User;
import com.monkey1024.dao.UserDao;
import com.monkey1024.dao.impl.UserDaoImpl;
import com.monkey1024.service.UserService;

public class UserServiceImpl implements UserService {

    UserDao userDao = new UserDaoImpl();

    @Override
    public void addUser(User user) throws Exception {
        userDao.addUser(user);
    }

}

在com.monkey1024.servlet包下创建RegistServlet处理请求数据:

package com.monkey1024.servlet;

import java.io.IOException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.monkey1024.bean.User;
import com.monkey1024.service.UserService;
import com.monkey1024.service.impl.UserServiceImpl;

/**
 * 用户注册
 */
public class RegistServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;

    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        request.setCharacterEncoding("UTF-8");
        response.setContentType("text/html;charset=UTF-8");

        //将表单提交的数据放在User类中
        User u = new User();
        u.setName(request.getParameter("name"));
        u.setPassword(request.getParameter("password"));
        u.setEmail(request.getParameter("email"));
        String birthday = request.getParameter("birthday");
        try {
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
            Date date = sdf.parse(birthday);
            u.setBirthday(date);
        } catch (ParseException e) {
            e.printStackTrace();
        }

        //调用业务逻辑
        UserService us = new UserServiceImpl();
        try {
            us.addUser(u);
            // 分发转向
            response.getWriter().write("注册成功!1秒跳转到主页");
            response.setHeader("refresh", "1;url=/login.jsp");
        } catch (Exception e) {
            e.printStackTrace();
        }


    }

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

}

登录功能

在UserDao接口中添加下面方法:

/**
 * 根据用户姓名和密码查找用户
 * @param user
 * @return
 * @throws Exception
 */
public User findUserByNameAndPassword(User user) throws Exception;

在UserDaoImpl实现类中添加下面方法,根据用户名和密码去数据库中查找响应的记录

@Override
public User findUserByNameAndPassword(User user) throws Exception {
    Connection conn = null;
    PreparedStatement ps = null;
    ResultSet rs = null;
    User u = null;
    try {
        conn = DBUtil.getConnection();
        ps = conn.prepareStatement("select * from t_user where name=? and password=?");
        ps.setString(1, user.getName());
        ps.setString(2, user.getPassword());

        rs = ps.executeQuery();
        if(rs.next()){
            u = new User();
            u.setId(rs.getInt(1));
            u.setName(rs.getString(2));
            u.setPassword(rs.getString(3));
            u.setEmail(rs.getString(4));
            u.setBirthday(rs.getDate(5));
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
    return u;
}

在UserService中添加下面方法:

/**
 * 根据用户姓名和密码查找用户
 * @param user
 * @return
 * @throws Exception
 */
public User findUserByNameAndPassword(User user) throws Exception;

在UserServiceImpl实现类中添加下面方法:

@Override
public User findUserByNameAndPassword(User user) throws Exception {
    return userDao.findUserByNameAndPassword(user);
}

创建LoginServlet用来接收提交的用户名和密码,如果根据该用户名和密码可以从数据库中查询出相应的数据,则可以登录成功,否则登录失败。

package com.monkey1024.servlet;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.monkey1024.bean.User;
import com.monkey1024.service.UserService;
import com.monkey1024.service.impl.UserServiceImpl;

/**
 * 用户登录
 */
public class LoginServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        request.setCharacterEncoding("UTF-8");
        response.setContentType("text/html;charset=UTF-8");
        User user = new User();
        user.setName(request.getParameter("name"));
        user.setPassword(request.getParameter("password"));

        UserService us = new UserServiceImpl();

        try {
            User u = us.findUserByNameAndPassword(user);

            //分发转向
            if(u!=null){
                //如果登录成功,就把user对象放到session对象中
                request.getSession().setAttribute("user", u);
                request.getRequestDispatcher("/login_success.jsp").forward(request, response);
            }else{
                request.setAttribute("msg", "用户名或密码不正确!");
                request.getRequestDispatcher("/login.jsp").forward(request, response);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

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

}

注销功能

创建LogoutServlet,在里面将session销毁:

package com.monkey1024.servlet;

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * 用户注销
 */
public class LogoutServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //使用sessions销毁
        request.getSession().invalidate();
        //重定向到登录页面
        response.sendRedirect("/login.jsp");
    }

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

}

上面就实现了一个简单的注册和登录的功能,但是该代码中存在太多问题了,我们会在后面进行重构