项目学习 —— 登录与注册(完整)

一. 创建动态Web工程

      参考:Tomcat学习_Archer__13的博客-CSDN博客 

      

①web目录存放web工程的资源文件,例如:html页面、css文件、js文件等,将写好的web页面放到该目录下(首页、用户登录页面、用户注册页面);

②web目录下的WEB-INF目录是受服务器保护的目录,浏览器无法直接访问此目录的内容; 

③在WEB-INF目录下创建一个lib目录用来存放所需要的第三方jar包;

④scr目录存放自己编写的java代码,并在src下创建以下目录;

       ​     

二. 编写登录和注册页面

 1. index.jsp页面

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core_1_1" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>首页</title>
    <%    //获取当前工程的路径
        String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+request.getContextPath()+"/";
    %>
    <base href="<%=basePath%>">
</head>
<body>
    <%-- 如果用户还没有登录,显示登录和注册菜单--%>
    <c:if test="${empty sessionScope.user}">
        <a href="pages/user/login.jsp"><input type = "button" value = "登录"/></a>
        <a href="pages/user/regist.jsp"><input type = "button" value = "注册"/></a>
    </c:if>
    <%-- 如果用户已经登录,显示欢迎用户和注销--%>
    <c:if test="${not empty sessionScope.user}">
        欢迎${sessionScope.user.username}
        <a href="userServlet?action=logout"><input type = "button" value = "注销"/></a>
    </c:if>
</body>
</html>

2.login.jsp页面

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>登录</title>
    <base href="http://localhost:8080/StudyProject_war_exploded/">
</head>
<body>
    <form action=" " method="post">
        用户名:<input type="text" name="username"> <br/>
        密码:<input type="password" name="password"> <br/>
        <input type="submit" value="登录">
    </form>
</body>
</html>

3.regist.html页面

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>注册</title>
    <base href="http://localhost:8080/StudyProject_war_exploded/">
</head>
<body>
    <form action=" " method="post">
        用户名:<input type="text" name="username"> <br/>
        用户密码:<input type="password" name="password"> <br/>
        确认密码:<input type="password" name="password"> <br/>
        电子邮箱:<input type="text" name="email"> <br/>
        验证码:<input type="text" name="code" style="width: 60px"/> <img src="kaptcha.jpg" onclick="this.src='kaptcha.jpg?d='+new Date()" style="width: 80px; height: 25px;"/> <br/>
        <input type="submit" value="注册">
    </form>
</body>
</html>

三. 创建数据库和表

  创建一个数据库studyproject,在该数据库下创建一个user表

create table user{
    id int primary key auto_increment,
    username varchar(20) not null unique,
    password varchar(32) not null,
    email varchar(200)
};

insert into user(username,password,email) values('admin','admin','admain@163.com');

四. 编写数据库表对应的JavaBean对象

      在pojo包下创建User类

package server.pojo;

public class User {
    private Integer id;
    private String username;
    private String password;
    private String email;

    public Integer getId() {
        return id;
    }

    public void setId(Integer 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;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", username='" + username + '\'' +
                ", password='" + password + '\'' +
                ", email='" + email + '\'' +
                '}';
    }

    public User() {
    }

    public User(Integer id, String username, String password, String email) {
        this.id = id;
        this.username = username;
        this.password = password;
        this.email = email;
    }
}

五. 连接数据库(utils)

1. 创建jdbc.properties文件,将其放在src下(必须是src目录下第一级),文件内容为:

url=jdbc:mysql://localhost:3306/studyproject   
username=root
password=123456
driverClassName=com.mysql.jdbc.Driver

initialSize=10
maxActive=10

2. 在utils包下创建一个工具类JdbcUtils.java文件,用来连接数据库

package server.utils;

import com.alibaba.druid.pool.DruidDataSourceFactory;

import javax.sql.DataSource;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Properties;

public class JdbcUtils {
    private static DataSource source;
    static{
        try {
            Properties properties = new Properties();
            //读取jdbc.properties属性
            InputStream is = JdbcUtils.class.getClassLoader().getResourceAsStream("jdbc.properties");
            //从流中加载数据
            properties.load(is);
            //创建数据库连接池
            source = DruidDataSourceFactory.createDataSource(properties);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    //获取连接
    public static Connection getConnection() {
        Connection conn = null;
        try {
            conn = source.getConnection();
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return conn;
    }

    //关闭连接
    public static void closeResource(Connection conn){
        try {
            if(conn != null){
                conn.close();
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}

六. Dao持久层 —— 操作数据库

1. 在dao.impl包下编写BaseDao类,用来操作数据库(更新、查询)

package server.dao.impl;

import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanHandler;
import org.apache.commons.dbutils.handlers.BeanListHandler;
import org.apache.commons.dbutils.handlers.ScalarHandler;
import server.utils.JdbcUtils;

import java.sql.Connection;
import java.util.List;

public abstract class BaseDao {
    //使用dbutils操作数据库
    private QueryRunner queryRunner = new QueryRunner();

    //更新数据
    public int updateData(String sql, Object ... args) {
        Connection conn = JdbcUtils.getConnection();
        try {
            return queryRunner.update(conn, sql, args);
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            JdbcUtils.closeResource(conn);
        }
        return -1;
    }

    //返回一条数据
    public <T> T queryOneData(Class<T> type,String sql, Object ... args){
        Connection conn = JdbcUtils.getConnection();
        try {
            return queryRunner.query(conn,sql,new BeanHandler<T>(type),args);
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            JdbcUtils.closeResource(conn);
        }
        return null;
    }

    //返回多条数据
    public <T> List<T> queryList(Class<T> type, String sql, Object ... args){
        Connection conn = JdbcUtils.getConnection();
        try {
            return queryRunner.query(conn,sql,new BeanListHandler<T>(type),args);
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            JdbcUtils.closeResource(conn);
        }
        return null;
    }

    //返回一个值(一行或一列)
    public Object querySingleValues(String sql, Object ... args){
        Connection conn = JdbcUtils.getConnection();
        try {
            return queryRunner.query(conn,sql,new ScalarHandler(),args);
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            JdbcUtils.closeResource(conn);
        }
        return null;
    }
}

2. 在dao包下编写UserDao接口,用来查询数据库中的用户信息和将用户信息保存到数据库中

package server.dao;

import server.pojo.User;

public interface UserDao {
    //根据用户名查询用户信息,如果返回null说明没有这个用户
    public User queryUserByUsername(String username);

    //根据用户名和密码查询用户信息,如果返回null说明用户名或密码错误
    public User queryUserByUsernameAndPassword(String username,String password);

    //保存用户信息
    public int saveUser(User user);
}

 3. 在dao.impl包下编写一个UserDaoImpl类,继承BaseDao类并实现UserDao接口

package server.dao.impl;

import server.dao.UserDao;
import server.pojo.User;

public class UserDaoImpl extends BaseDao implements UserDao {
    @Override
    public User queryUserByUsername(String username) {
        String sql = "select id, username, password, email from user where username = ?";
        return queryOneData(User.class,sql,username);
    }

    @Override
    public User queryUserByUsernameAndPassword(String username, String password) {
        String sql = "select id, username, password, email from user where username = ? and password = ?";
        return queryOneData(User.class,sql,username,password);
    }

    @Override
    public int saveUser(User user) {
        String sql = "insert into user(username,password,email) values(?,?,?)";
        return updateData(sql,user.getUsername(),user.getPassword(),user.getEmail());
    }

}

七. Service业务层 —— 注册和登录

1. 在Service包下编写UserService接口,实现用户注册和登录 

package server.service;

import server.pojo.User;

public interface UserService {
    //用户注册,如果用户名已存在,则需要重新注册一个新的用户名(用户名不可以重复)
    public void registUser(User user);

    //用户登录,如果登录失败会返回null
    public User login(User user);

    //判断用户名是否存在,返回true表示用户名存在,返回flase表示用户名可用
    public boolean existUsername(String username);
}

2. 在service.impl包下编写UserServiceImpl类来实现UserService接口。

package server.service.impl;

import server.dao.UserDao;
import server.dao.impl.UserDaoImpl;
import server.pojo.User;
import server.service.UserService;

public class UserServiceImpl implements UserService {
    private UserDao userDao = new UserDaoImpl();
    @Override
    public void registUser(User user) {
        userDao.saveUser(user);
    }

    @Override
    public User login(User user) {
        return userDao.queryUserByUsernameAndPassword(user.getUsername(),user.getPassword());
    }

    @Override
    public boolean existUsername(String username) {
        if(userDao.queryUserByUsername(username) == null){
            return false;
        }else {
            return true;
        }
    }
}

八. Web层 —— 实现Servlet程序

Servlet程序用于接收客户端请求然后调用Service层的服务来执行

1. 编写BaseServlet类,用于获取隐藏域中的值来执行相应的方法

package server.web;

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

public abstract class BaseServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doPost(req, resp);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        req.setCharacterEncoding("UTF-8");                 // 解决post请求中文乱码问题
        resp.setContentType("text/html; charset=UTF-8");   // 解决响应中文乱码问题

        String action = req.getParameter("action");
        try {
            //获取action业务鉴别字符串,得到相应的业务方法
            Method method = this.getClass().getDeclaredMethod(action, HttpServletRequest.class, HttpServletResponse.class);
            //调用目标业务方法
            method.invoke(this, req, resp);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

2. 编写WebServlet工具类,一次性把所有请求的参数注入到JavaBean中 

package server.utils;

import org.apache.commons.beanutils.BeanUtils;

import java.util.Map;

public class WebUtils {
    public static <T> T copyParamToBean(Map value, T bean){
        try {
            BeanUtils.populate(bean, value);   //把所有请求注入到JavaBean中
        } catch (Exception e) {
            e.printStackTrace();
        }
        return bean;
    }
}

2. 编写UserServlet类,并继承BaseServlet类,执行相应的请求

package server.web;

import server.pojo.User;
import server.service.UserService;
import server.service.impl.UserServiceImpl;
import server.utils.WebUtils;

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

import static com.google.code.kaptcha.Constants.KAPTCHA_SESSION_KEY;

@WebServlet("/userServlet")
public class UserServlet extends BaseServlet {
    private UserService userService = new UserServiceImpl();

    protected void login(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //1.获取客户端的请求
        User user = WebUtils.copyParamToBean(req.getParameterMap(),new User());

        //2.用户登录
        User loginUser = userService.login(user);
        if(loginUser == null){
            //登录失败,跳回登录页面
            req.setAttribute("msg","用户名或密码错误!");
            req.setAttribute("username",user.getUsername());
            req.getRequestDispatcher("pages/user/login.jsp").forward(req,resp);
        }else{
            //登录成功,跳到首页index.jsp
            req.getSession().setAttribute("user",loginUser);
            req.getRequestDispatcher("index.jsp").forward(req,resp);
        }
    }

    protected void regist(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //获取Session中的验证码
        String token = (String) req.getSession().getAttribute(KAPTCHA_SESSION_KEY);
        //删除Session中的验证码
        req.getSession().removeAttribute(KAPTCHA_SESSION_KEY);

        String code = req.getParameter("code");

        //1.获取客户端的请求
        User user = WebUtils.copyParamToBean(req.getParameterMap(),new User());

        //2.用户注册
        if(token != null && token.equalsIgnoreCase(code)){   //检查验证码是否正确
            if(userService.existUsername(user.getUsername())){   //注册不成功
                req.setAttribute("msg","用户名已存在");
                req.setAttribute("username",user.getUsername());
                req.setAttribute("email",user.getEmail());
                req.getRequestDispatcher("/pages/user/regist.jsp").forward(req,resp);  //跳转到注册页面
            }else{
                userService.registUser(user);    //注册成功
                req.getRequestDispatcher("index.jsp").forward(req,resp);  //跳转到首页
            }
        }else {
            // 把回显信息,保存到Request域中
            req.setAttribute("msg", "验证码错误!");
            req.setAttribute("username", user.getUsername());
            req.setAttribute("email", user.getEmail());
            req.getRequestDispatcher("/pages/user/regist.jsp").forward(req, resp);
        }
    }

    protected void logout(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //销毁Session
        req.getSession().invalidate();
        //重定向到首页
        resp.sendRedirect("index.jsp");
    }
}

4. 将loginin.jsp和regist.jsp修改如下,用于接收服务器回传的信息

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>登录</title>
    <base href="http://localhost:8080/StudyProject_war_exploded/">
</head>
<body>
    <form action="userServlet" method="post">
        <input type="hidden" name="action" value="login">
        用户名:<input type="text" name="username" value="${empty requestScope.username ? "" : requestScope.username}"> <br/>
        密码:<input type="password" name="password"> <br/>
        <input type="submit" value="登录"> <br/>
        <div>
            ${empty requestScope.msg ? "请输入用户名和密码" : requestScope.msg}
        </div>
    </form>
</body>
</html>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>注册</title>
    <%    //获取当前工程的路径
        String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+request.getContextPath()+"/";
    %>
    <base href="<%=basePath%>">
</head>
<body>
    <form action="userServlet" method="post">
        <input type="hidden" name="action" value="regist">
        用户名:<input type="text" name="username" value="${empty requestScope.username ? "" : requestScope.username}"> <br/>
        用户密码:<input type="password" name="password"> <br/>
        确认密码:<input type="password" name="password"> <br/>
        电子邮箱:<input type="text" name="email" value="${empty requestScope.email ? "" : requestScope.email}"> <br/>
        验证码:<input type="text" name="code" style="width: 60px"/> <img src="kaptcha.jpg" onclick="this.src='kaptcha.jpg?d='+new Date()" style="width: 80px; height: 25px;"/> <br/>
        <input type="submit" value="注册"> <br/>
        <div>
            ${empty requestScope.msg ? "" : requestScope.msg}
        </div>
    </form>
</body>
</html>
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值