frankruby

第一阶段:主要是通过jQuery对注册页面的用户名+密码+邮箱等作出的一些限制

书城第二阶段 ===> 用户注册和登录

第二阶段,我们要实现的是:

  • 注册输入的内容提交给服务器,然后服务器接收到以后,把数据保存到数据库内。
  • 登录输入用户名和密码之后,数据发送给服务器,服务器就会获取用户名和密码去数据库检查,如果正确跳转到登录成功页面,如果失败跳转到登录页面

一、JavaEE三层架构介绍

web层/视图展现层、Service业务层、Dao持久层 (编写持久层之前需要写Utils公共类来连接数据库,      

BaseDao类来管理数据库的对象实现对数据库的增删改查,其他具体操作的对象的Dao,比如:UserDao等

 不同层级对应不同的包:

web层        com.wufq.web/servlet/controller    

service层    com.wufq.service          service接口包

          com.wufq.service.impl        service接口实现类

dao持久层    com.wufq.dao            Dao接口包

        com.wufq.impl            Dao接口实现类

实体bean对象     com.wufq.pojo/entity/domain/bean   javaBean类

测试包     com.wufq.test/junit          

工具类     com.wufq.utils

--------项目开发环境---------

二、代码编写流程

1、创建数据库和表(这一阶段实现的是注册和登录,所以数据需要保存:id,用户名,密码,邮箱)

DROP DATABASE IF EXISTS book;

CREATE DATABASE book;

USE book;

CREATE TABLE t_user(
    id INT PRIMARY KEY AUTO_INCREMENT,
    username VARCHAR(20) NOT NULL UNIQUE,
    PASSWORD VARCHAR(32) NOT NULL,
    email VARCHAR(200)
    
);

DESC t_user;

INSERT INTO t_user(username,PASSWORD,email) VALUES(\'admin\',\'admin\',\'admin@163.com\');

SELECT * FROM t_user;

2、编写数据库表对应的JavaBean对象

package com.wufq.pojo;

/**
 * @Description
 * @Author wufq
 * @Version
 * @Date 2021/6/25 11:07
 */
public class User {
    private Integer id;
    private String username;
    private String password;
    private String email;

//还包含getter、setter方法,toString方法、有参、无参构造器

3、编写工具类JdbcUtils类 (管理数据库连接池:和数据库建立链接以及关闭链接)

第一步:导入需要的jar包(数据库和连接池的jar包)

|-- 在web包下创建lib目录,导入mysql,druid,junit包

|-- 引入上面的jar包:file--Project Structure--Libraries--+(java)选择上面的lib目录,然后修改名称为book_lib --Modules--选择工程--切换到Dependencies

--点击+号选择book_lib --Artifaces--选中工程名--点击fix

第二步:在src源码目录下编写jdbc.properties属性配置文件

username=root
password=1234
url=jdbc:mysql://172.16.203.130:3306/book?characterEncoding=utf-8&serverTimezone=GMT%2B8
driverClassName=com.mysql.jdbc.Driver
initialSize=5
maxActive=10

第三步:编写jdbcUtils工具类

package com.wufq.utils;

import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.pool.DruidDataSourceFactory;

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

/**
 * @Description
 * @Author wufq
 * @Version
 * @Date 2021/6/25 11:13
 */
public class JdbcUtils {

    private static DruidDataSource dataSource;

    static {
        try {
            Properties properties = new Properties();
            InputStream inputStream = JdbcUtils.class.getClassLoader().getResourceAsStream("jdbc.properties");
            //2、从流中加载数据
            properties.load(inputStream);
            //1、创建数据库连接池
            dataSource =(DruidDataSource) DruidDataSourceFactory.createDataSource(properties);

        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    /*
    * 获取数据库连接池中的连接
    * 如果返回null,说明获取链接失败,有值就是获取链接成功
    * */

    public static Connection getConnection(){
        Connection conn=null;
        try {
            conn = dataSource.getConnection();
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return conn;
    }

    /*
    * 关闭链接,放回数据库连接池
    * */

    public static void close(Connection conn){

        if(conn!=null){
            try {
                conn.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }

}

第四步:JdbcUtils测试

public class TestJdbcUtils {

    @Test
    public void testJdbcUtils(){
        for(int i=0;i<50;i++){
            Connection connection = JdbcUtils.getConnection();
            System.out.println(connection);
//            这里一定要关闭数据库连接,因为配置文件内设置的最大连接数是:maxActive=10,如果不及时关闭连接,则只会创建10次连接
            JdbcUtils.close(connection);
        }
    }
}

编写Dao持久层

4、编写BaseDao (给别人复用代码的作用)

第一步:导入DButils的jar包

commons-dbutils-1.3.jar

第二步编写BaseDao

package com.wufq.dao.impl;

import com.wufq.utils.JdbcUtils;
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 java.sql.Connection;
import java.sql.SQLException;
import java.util.List;

/**
 * @Description  管理数据库对象,实现数据的增删改查
 * @Author wufq
 * @Version
 * @Date 2021/6/25 15:09
 */
public abstract class BaseDao {

//    使用DBUtils操作数据库
    private QueryRunner queryRunner = new QueryRunner();

    /*
    * updata()方法用来执行:insert/update/delete语句
    * @return 如果返回-1说明执行失败,返回其他表示影响的行数
    * */

    public int update(String sql,Object... args){ //Object... args可变参数的意思
        Connection conn = JdbcUtils.getConnection();

        try {
            return queryRunner.update(conn,sql,args);
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            JdbcUtils.close(conn);
        }

        return -1;
    }

    /*
    * 查询返回一个javaBean的sql语句
    * type:返回对象类型
    * sql:执行的sql语句
    * args sql对应的参数
    * <T> 返回的类型的泛型
    * */
    public <T> T queryForOne(String sql,Class<T> type,Object... args){
        Connection conn = JdbcUtils.getConnection();

        try {
            return queryRunner.query(conn,sql,new BeanHandler<T>(type),args);
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            JdbcUtils.close(conn);
        }

        return null;
    }

    /*
    * 查询返回多个javaBean的sql语句
    * type:返回对象类型
    * sql:执行的sql语句
    * args sql对应的参数
    * <T> 返回的类型的泛型
    * */
    public <T> List<T> queryForList(String sql, Class<T> type, Object... args){
        Connection conn = JdbcUtils.getConnection();

        try {
            return queryRunner.query(conn,sql,new BeanListHandler<T>(type),args);
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            JdbcUtils.close(conn);
        }

        return null;
    }

    /*
    * 查询返回一行一列的sql语句
    * type:返回对象类型
    * sql:执行的sql语句
    * args sql对应的参数
    * <T> 返回的类型的泛型
    * */
    public Object queryForSingleValue(String sql,Object... args){
        Connection conn = JdbcUtils.getConnection();

        try {
            return queryRunner.query(conn,sql,new ScalarHandler(),args);
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            JdbcUtils.close(conn);
        }

        return null;
    }
}

5、编写UserDao

UserDao接口

package com.wufq.dao;

import com.wufq.pojo.User;

/**
 * @Description User对象接口,验证用户信息在数据库内是否有效(比如:注册用户时首先根据用户名去数据库里面查找)
 * @Author wufq
 * @Version
 * @Date 2021/6/25 16:42
 */
public interface UserDao {

 /*
  * 根据用户名查询用户信息
  * * @param username 用户名
  * @Return: com.wufq.pojo.User 如果返回null,说明没有这个用户,反之亦然
  *
  */
    public User queryUserByUsername(String username);

   /*
    * 根据用户名和密码查询用户信息
   * @param username
   * @param password
    * @Return: com.wufq.pojo.User
    *
    */
    public User queryUserByUsernameAndPasswd(String username,String password);

    /*
     * 保存用户信息
    * @param user
     * @Return: int 返回-1表示操作失败,其他是sql语句影响的行数
     *
     */
    public int saveUser(User user);

}

UserDaoImpl实现类

package com.wufq.dao.impl;

import com.wufq.dao.UserDao;
import com.wufq.pojo.User;

/**
 * @Description UserDao的具体实现类
 * @Author wufq
 * @Version
 * @Date 2021/6/25 17:28
 */
public class UserDaoImpl extends BaseDao implements UserDao{
    @Override
    public User queryUserByUsername(String username) {

        String sql = "SELECT id,username,PASSWORD,email FROM `t_user` WHERE `username`=?";
        return queryForOne(sql,User.class,username);
    }

    @Override
    public User queryUserByUsernameAndPasswd(String username, String password) {
        String sql = "SELECT id,username,PASSWORD,email FROM `t_user` WHERE `username`=? and password=?";

        return queryForOne(sql,User.class,username,password);
    }

    @Override
    public int saveUser(User user) {
        String sql = "INSERT INTO t_user(username,PASSWORD,email) VALUES(?,?,?)";

        return update(sql,user.getUsername(),user.getPassword(),user.getEmail());
    }

}

测试UserDaoImpl

package com.wufq.test;

import com.wufq.dao.UserDao;
import com.wufq.dao.impl.UserDaoImpl;
import com.wufq.pojo.User;
import org.junit.Test;

/**
 * @Description
 * @Author wufq
 * @Version
 * @Date 2021/6/25 17:41
 */
public class UserDaoTest {
    UserDao userDao = new UserDaoImpl();
    @Test
    public void queryUserByUsername() throws Exception {

        if (userDao.queryUserByUsername("admin")==null) {
            System.out.println("用户名可用!");
        } else {
            System.out.println("用户名不存在!");
        }

    }

    @Test
    public void queryUserByUsernameAndPasswd() throws Exception {
        if(userDao.queryUserByUsernameAndPasswd("admin","admin")==null){
            System.out.println("用户名或密码错误,登录失败");
        }else{
            System.out.println("查询成功");
        }
    }

    @Test
    public void saveUser() throws Exception {
        System.out.println(userDao.saveUser(new User(null, "wufq123", "123456", "wufq@163.com")));
    }


}

6、编写UserService和测试

UserService接口

package com.wufq.service;

import com.wufq.pojo.User;

/**
 * @Description Dao持久层写完以后,按照javaEE三层架构我们写Service业务层
 * service层主要作用是:1、处理业务逻辑 2、调用持久层保存到数据库
 * @Author wufq
 * @Version
 * @Date 2021/6/28 10:23
 */

/*
 *
* @param 分析知道:登录是一个业务,注册也是一个业务,检查用户名是否存在也是一个业务
 * @Return:
 *
 */
public interface UserService {

/*
* 注册用户
 * @param: user
* @Return: void
*/
    public void registUser(User user);

    /*
    * 登录
     * @param: user
    * @Return: com.wufq.pojo.User
    */
    public User login(User user);

    /*
    * 检查用户名是否可用
     * @param: username
    * @Return: java.lang.Boolean
    */
    public Boolean existesUserName(String username);
}

UserServiceImpl实现类

package com.wufq.service.impl;

import com.wufq.dao.UserDao;
import com.wufq.dao.impl.UserDaoImpl;
import com.wufq.pojo.User;
import com.wufq.service.UserService;

/**
 * @Description
 * @Author wufq
 * @Version
 * @Date 2021/6/28 13:01
 */
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.queryUserByUsernameAndPasswd(user.getUsername(),user.getPassword());
    }

    @Override
    public Boolean existesUserName(String username) {
        if(userDao.queryUserByUsername(username)==null){
            return false;
        }
        return true;
    }
}

UserServiceTest测试类

package com.wufq.test;

import com.wufq.pojo.User;
import com.wufq.service.UserService;
import com.wufq.service.impl.UserServiceImpl;
import org.junit.Test;

/**
 * @Description
 * @Author wufq
 * @Version
 * @Date 2021/6/28 13:28
 */
public class UserServiceTest {
    UserService userService = new UserServiceImpl();

    @Test
    public void registUser() throws Exception {
        userService.registUser(new User(null,"bbj666","123456","bbj888@163.com"));
        userService.registUser(new User(null,"abc666","123456","abc888@163.com"));
    }

    @Test
    public void login() throws Exception {
        User login = userService.login(new User(null, "bbj888", "123456", null));
        System.out.println(login);
    }

    @Test
    public void existesUserName() throws Exception {
        System.out.println(userService.existesUserName("abc888"));
    }

}

编写web层

7.1、实现用户注册的功能

7.1.1 用户注册的流程

7.1.2  新建RegistServlet类 -->此类继承HttpServlet(后面会详细写RegistServlet类的代码,当前新建是为了配置web服务器)-->编写web.xml文件

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
         version="3.1">
<servlet>
    <servlet-name>RegistServlet</servlet-name>
    <servlet-class>com.wufq.web.RegistServlet</servlet-class>
</servlet>  
    
<servlet-mapping>
    <servlet-name>RegistServlet</servlet-name>
    <url-pattern>/registServlet</url-pattern>
</servlet-mapping>    
</web-app>

-->修改tomcat配置文件(Edit Configuration)

7.1.3  修改regist.html 和regist_success.html页面

前端跳转地址一般分为两种:

1)base标签+相对路径

2)绝对路径

这里我们使用base标签+相对路径,后面使用框架的时候用绝对路径

  • 添加base标签
<head>
<meta charset="UTF-8">
<title>尚硅谷会员注册页面</title>
<!--写base标签,永远固定相对路径跳转的结果-->
<base href="http://localhost:8080/book/">

当用了base标签以后,启动服务器前端页面跳转到注册页时会发现整个css和jQery文件引用都失效了,失效的原因:base标签对页面中所有相对路径的影响

  • 修改base标签对页面中所有相对路径的影响(浏览器F12-->network 那个报红,修改那个)

以下是修改的示例:
修改前
<script type="text/javascript" src="../../static/script/jquery-1.7.2.js"></script>
修改后
<script type="text/javascript" src="static/script/jquery-1.7.2.js"></script>
  • 修改注册表单的提交地址和请求方式

7.1.4  编写RegistServlet程序

package com.wufq.web;

import com.wufq.pojo.User;
import com.wufq.service.UserService;
import com.wufq.service.impl.UserServiceImpl;

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

/**
 * @Description
 * @Author wufq
 * @Version
 * @Date 2021/6/28 16:00
 */
public class RegistServlet extends HttpServlet{

    private UserService userService = new UserServiceImpl();

    /*
    *  按照用户注册流程中RegistServlet程序接受客户端后处理请求的流程
     * @param: req
     * @param: resp
    * @Return: void
    */
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//        1、获取请求的参数
        String username = req.getParameter("username");
        String password = req.getParameter("password");
        String email = req.getParameter("email");
        String code = req.getParameter("code");

//        2、检查验证码是否正确  ===  写死,要求验证码为:abcde  (一般验证码由服务器生成,这个先写死)
        if("abcde".equalsIgnoreCase(code)){
//            3、验证码正确,在继续检查用户名是否可用
            if(userService.existesUserName(username)){
                //用户名存在,跳回注册页面
                System.out.println("用户名["+username+"]已存在");
                req.getRequestDispatcher("/pages/user/regist.html").forward(req,resp);
            }else {
                //用户名不存在,调用UserService保存在数据库,并且页面跳转到注册成功页面
                userService.registUser(new User(null,username,password,email));
                req.getRequestDispatcher("/pages/user/regist_success.html").forward(req,resp);
            }
        }else{
//            4、不正确,页面跳转仍然跳转到注册页面
            System.out.println("验证码["+code+"]错误");
            req.getRequestDispatcher("pages/user/regist.html").forward(req,resp);
        }

    }
}

 7.2 实现用户登录的功能

7.2.1 用户登录流程

7.2.2 在login.html和login_success.html页面添加base标签和表单的请求方式(action="loginServlet" method="post")

7.2.3 LoginServlet程序

package com.wufq.web;

import com.wufq.pojo.User;
import com.wufq.service.UserService;
import com.wufq.service.impl.UserServiceImpl;

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

/**
 * @Description
 * @Author wufq
 * @Version
 * @Date 2021/6/29 09:04
 */
public class LoginServlet extends HttpServlet{

    private UserService userService = new UserServiceImpl();
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//        1、获取请求的参数
        String username = req.getParameter("username");
        String password = req.getParameter("password");

//        2、调用userService.login()登录处理业务
        User loginUser = userService.login(new User(null, username, password, null));

        if(loginUser ==null){
            System.out.println("登录失败!");
            req.getRequestDispatcher("/pages/user/login.html").forward(req, resp);
        }else {
            System.out.println("欢迎["+username+"]登录尘封网");
            req.getRequestDispatcher("/pages/user/login_success.html").forward(req, resp);
        }

    }
}

 

分类:

技术点:

相关文章: