尚硅谷JavaWeb2020-02-26书城项目阶段二的实现笔记整理

发布于:2022-10-16 ⋅ 阅读:(425) ⋅ 点赞:(0)

 然后我们运行代码:

开发工具:IDEA2020.3、Mysql8.0、Tomcat8.0

在开发之前,我们首先明确JavaEE的三层架构:

①Web层/视图展现层:

  • 获取请求参数,封装称为Bean对象

  • 调用Service层,处理对象

  • 相应数据给客户端,请求转发重定向

②:Service业务层:

  • 处理业务逻辑

  • 调用持久层保存到数据库

③:Dao持久层:

  • Dao持久层只负责和数据库进行交互

  • CRUD操作:增删改查 Create Read Update Delete

这三层实际上相当于我们以后将要学习的Spring、SpringMVC、MyBaties

  1. Dao持久层(JDBC、MyBaties):只负责跟数据库交互。

  2. Service业务层(Spring)包括:①处理业务;②调用DAO持久层将数据保存到数据库。

  3. Web层(SpringMVC)包括:a.使用Servlet程序接收客户端的请求参数,封装成为Bean对象;b.调用Service层处理业务;c.响应数据给客户端,请求转发,请求重定向。

了解了这些之后我们进行进一步的操作。

目录

1.创建工程

2.创建书城项目所需的数据库的表

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

4.编写JdbcUtils工具类(管理数据库连接池,从其中获取连接)

5.编写BaseDao

6.编写UserDao和测试

​编辑 ​编辑

7.编写UserServicce和测试

8.编写Web层

服务器的部署为:

登录操作:



1.创建工程

我们选择Java Enterprise,创建项目名称为book,将静态页面复制粘贴到webapp中,静态页面我们使用的是尚硅谷中的,资料可以在尚硅谷课程javaweb中下载。链接:百度网盘 请输入提取码 提取码:3rz5。

 然后创建包web、utils、test、service.impl(业务层的实现类的包)、pojo、dao.impl(持久层的实现类的包),这个在原来的包已经删除的情况下创建的。 (由于test在下方Idea已经自动创建好了,我们后面就不用这里的test了) 。

2.创建书城项目所需的数据库的表

我们所用到的工具是mysql数据库:

DROP DATABASE IF EXISTS book;#如果存在数据库book先进行删除

CREATE DATABASE book;# 创建数据库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)
);#创建t_user表

INSERT INTO t_user(`username`,`password`,`email`) VALUES('admin',
'admin','admin@zr.com');#向表中添加对应的值

SELECT * FROM t_user;#查看表t_user

此时book数据库和t_user表已经创建好了。  

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

  • 在pojo中创建User类,在User类中写下一些必要的属性

 	private Integer id;
    private String username;
    private String password;
    private String email;
  • 对这些属性生成get、set方法,有参无参构造,toString方法

4.编写JdbcUtils工具类(管理数据库连接池,从其中获取连接)

  • 这里需要用到数据库连接池(druid-1.1.9.jar)和数据库驱动(mysql-connector-java-5.1.7-bin.jar),把它放在WEB-INF下创建的lib中  

  • 将其名称修改为book_lib,并且在点击应用

  •  在resources中创建jdbc.properties
username=root
password=abc123
url=jdbc:mysql://localhost:13306/book
driverClassName=com.mysql.jdbc.Driver
initialSize=5
maxActive=10
    #其中要输入自己的mysql用户名和密码,
以及自己的数据库是什么版本的,这里我采用的
是8.0版本的,因此我们的端口号为13306,5.0为3306

​
  •  JdbcUtiles类的代码为:
package com.atguigu.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;

public class JdbcUtils {

    private static DruidDataSource dataSource;

    static {

        try {
            Properties properties = new Properties();
            //读取jdbc.properties属性配置文件
            InputStream inputStream = JdbcUtils.class.getClassLoader().getResourceAsStream("jdbc.properties");
            //从流中加载数据
            properties.load(inputStream);
            //创建数据库连接池
            dataSource = (DruidDataSource) DruidDataSourceFactory.createDataSource(properties);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /*获取数据库连接池中的连接
    * 如果返回值为null,说明获取连接池失败,有值就是获取连接成功
    * */

    public static Connection getConnection(){
        Connection conn = null;

        try {
            conn = dataSource.getConnection();
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }


        return conn;
    }

    /*关闭连接,放回数据库连接池*/
    public static void close(Connection conn){
        if(conn!=null){
            try {
                conn.close();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }
    }
}
  • 创建JdbcUtilsTest测试JdbcUtils是否创建成功  
package com.atguigu.test;

import com.atguigu.utils.JdbcUtils;
import org.junit.Test;

import java.sql.Connection;

public class JdbcUtilsTest {

    @Test
    public void testJdbcUtils(){
        for (int i = 0;i<100;i++){
            Connection connection = JdbcUtils.getConnection();
            System.out.println(connection);
            JdbcUtils.close(connection);
        }
    }
	@Test
    public void testJdbcUtils2(){
        for (int i = 0;i<100;i++){
            Connection connection = JdbcUtils.getConnection();
            System.out.println(connection);
            //注意此时没有关闭只能打印出10个,因为在jdbc.properties中我们已经设置了最大连接个数,及时释放的话才可以成功
        }
    }

}

在获取连接成功的情况下说明已经成功了。  

5.编写BaseDao

package com.atguigu.dao.impl;

import com.atguigu.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;

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


    /*
     * update方法来执行Insert\update\Delete语句
     *
     * @retuen 如果返回-1,则说明执行失败,返回其他表示影响的行数
     * */
    public int update(String sql, Object... args) {
        Connection connection = JdbcUtils.getConnection();
        try {
            return queryRunner.update(connection, sql, args);
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }
        return -1;
    }


    /**
     * 查询返回一个javaBean的sql语句
     *
     * @param type:返回对象类型
     * @param sql:执行的sql语句
     * @param args:sql对应的参数值
     * @param <T>:返回的类型的泛型
     * @return
     */
    public <T> Object queryForOne(Class<T> type, String sql, Object... args) {
        Connection con = JdbcUtils.getConnection();
        try {
            return queryRunner.query(con, sql, new BeanHandler<T>(type), args);
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }
        return null;
    }


    /**
     * 查询返回多个javaBean的sql语句
     *
     * @param type:返回对象类型
     * @param sql:执行的sql语句
     * @param args:sql对应的参数值
     * @param <T>:返回的类型的泛型
     * @return
     */
    public <T> List<T> queryForList(Class<T> type, String sql, Object... args) {
        Connection con = JdbcUtils.getConnection();
        try {
            return queryRunner.query(con, sql, new BeanListHandler<T>(type), args);
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }
        return null;
    }


    /**
     * 执行返回一行一列的sql语句
     *
     * @param sql:执行的sql语句
     * @param args:sql对应的参数值
     * @return
     */
    public Object queryForSingleValue(String sql, Object... args) {
        Connection conn = JdbcUtils.getConnection();

        try {
            return queryRunner.query(conn, sql, new ScalarHandler(), args);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }


}

6.编写UserDao和测试

package com.atguigu.dao;
import com.atguigu.pojo.User;

public interface UserDao {



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

    /**
     * 保存用户信息
     * @param user:用户
     * @return
     */
    public int saveUser(User user);

    /**
     * 根据用户名和密码查询用户信息
     * @param username
     * @param password
     * @return 如果返回值为null,则说明用户名或者密码错误,反之亦然
     */
    public User queryUserByUsernameAndPassword(String username,String password);


}
package com.atguigu.dao.impl;

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

/**
 * @Program:fadaizhouzhou
 * @description:impl
 * @author: jiangzeren
 * @create: 2022-10-15 17
 **/

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 (User) queryForOne(User.class,sql,username);
    }

    @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());
    }

    @Override
    public User queryUserByUsernameAndPassword(String username, String password) {
        String sql = "select `id`,`username`,`password`,`email` from t_user where username = ? and password = ?";
        return (User) queryForOne(User.class,sql,username,password);
    }
}
package com.atguigu.test;

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

import static org.junit.Assert.*;

public class UserDaoTest {


    UserDao userDao = new UserDaoImpl();


    @Test
    public void queryUserByUsername() {
        if (userDao.queryUserByUsername("admin1234") == null){
            System.out.println("用户名可用!");
        }else {
            System.out.println("用户名已存在!");
        }
    }

    @Test
    public void saveUser() {
        System.out.println( userDao.saveUser(new User(null,"admin2","123456","wwwwji@qq.com")));
    }

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

 

 

7.编写UserServicce和测试

  • UserService接口:
package com.atguigu.service;

import com.atguigu.pojo.User;

public interface UserService {

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

    /**
     * 登录
     * @param user
     * @return 如果返回null,则说明登录失败,否则登录成功
     */
    public User login(User user);


    /**
     * 检查 用户名是否可用
     * @param username
     * @return 返回true表示用户名已存在,返回false表明用户名可用
     */
    public boolean existsUsername(String username);



}
  • UserServiceImpl类:
package com.atguigu.service.impl;

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

/**
 * @Program:fadaizhouzhou
 * @description:impl
 * @author: jiangzeren
 * @create: 2022-10-15 20
 **/

public class UserServiceImpl implements UserService{

    private UserDao userDao = new UserDaoImpl();//这里感觉关键
    //这里的体现了多态!userDao的左边是接口 右边实现类 所以调用userDao的方法时看似是调用了接口中的方法(编译状态下) 但实际调用的是调用实现类中的方法(运行状态)


    @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 existsUsername(String username) {
        if (userDao.queryUserByUsername(username) == null){
            //等于null说明没查到,没查到表示有用
            return false;
        }
        return true;
    }
}
  • UserService测试:
package com.atguigu.test;

import com.atguigu.pojo.User;
import com.atguigu.service.UserService;
import com.atguigu.service.impl.UserServiceImpl;
import org.junit.Test;
import sun.security.util.Password;

import static org.junit.Assert.*;

public class UserServiceTest {

    UserService userService = new UserServiceImpl();
    @Test
    public void registUser() {
        userService.registUser(new User(null,"qqq7488", "666666","7488@qq.com"));
        userService.registUser(new User(null,"woshi", "wwjiji","7wi928@qq.com"));
    }

    @Test
    public void login() {
        System.out.println( userService.login(new User(null,"qqq7488", "666666",null)));
    }

    @Test
    public void existsUsername() {
        if (userService.existsUsername("woshi")){
            System.out.println("用户名已存在");
        }else {
            System.out.println("用户名可用");
        }
    }
}
  • 执行:

 

 

  • SQL结果:

 

由于点了重复添加相同信息,因此添加失败,但我们看到id自增并未按顺序增加,这里以后应该能解决。

8.编写Web层

需求1:用户注册

  • 访问汪册贝面

  • 填写注册信息,提交给服务器

  • 服务器应该保存用户

  • 当用户已经存在一提示用户注册失败,用户名已存在

  • 当用户不存在---注册成功

需求2:用户登录

 

  • 首先在类RegistServlet中继承HttpServlet

  • 然后再WEB-INF下配置web.xml文件

	<servlet>
        <servlet-name>RegistServlet</servlet-name>
        <servlet-class>com.atguigu.web.RegistServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>RegistServlet</servlet-name>
        <url-pattern>/RegistServlet</url-pattern>
    </servlet-mapping>
  • 在regist.html页面中将地址写为/registServlet

  • base+相对路径

 

需要咋title下面加上<base href="http://localhost:8080/book/">

  1. 但是这会带来很多问题,我们尝试打开regist.html发现样式和图片等打不开,原因是在加了base之后,会在前面默认加上"http://localhost:8080/book/,如果再使用../,那么book的上一层已经没有东西了,无法访问,解决方法是把../全部删掉。

  2. <!--写base标签,永远固定相对路径的跳转结果-->

这里的结果时需要在部署服务器Tomcat的基础上运行的  

服务器的部署为:

 

  • UserServiceImpl代码:
package com.atguigu.service.impl;

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

/**
 * @Program:fadaizhouzhou
 * @description:impl
 * @author: jiangzeren
 * @create: 2022-10-15 20
 **/

public class UserServiceImpl implements UserService{

    private UserDao userDao = new UserDaoImpl();//这里感觉关键
    //这里的体现了多态!userDao的左边是接口 右边实现类 所以调用userDao的方法时看似是调用了接口中的方法(编译状态下) 但实际调用的是调用实现类中的方法(运行状态)


    @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 existsUsername(String username) {
        if (userDao.queryUserByUsername(username) == null){
            //等于null说明没查到,没查到表示有用
            return false;
        }
        return true;
    }
}
package com.atguigu.web;

import com.atguigu.pojo.User;
import com.atguigu.service.UserService;
import com.atguigu.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;

/**
 * @Program:fadaizhouzhou
 * @description:web
 * @author: jiangzeren
 * @create: 2022-10-16 09
 **/

public class RegistServlet extends HttpServlet {

    /**
     * 由于Web层不能直接操作Dao,我们只能操作Service层
     */
    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");
        String email = req.getParameter("email");
        String code = req.getParameter("code");
//        2、检查验证码是否正确  ==== 写死,目前要求验证码为abcde
        if ("abcde".equalsIgnoreCase(code)){
            //                正确:
//                  3:检查用户名是否可
            if (userService.existsUsername(username)){
//                      不可用:
                System.out.println("用户名["+username+"]已存在");
                //                          跳回注册
                req.getRequestDispatcher("/pages/user/regist.html").forward(req,resp);
            }else{
                //                      可用:
                System.out.println("用户名可用!");
                //                          调用Sservice保存到数据库。
                userService.registUser(new User(null,username,password,email));
                //跳回注册成功页面
                req.getRequestDispatcher("/pages/user/regist_success.html").forward(req,resp);
            }

        }else {
            System.out.println("验证码["+code+"]错误");
            req.getRequestDispatcher("/pages/user/regist.html").forward(req,resp);
        }


    }

}

我们接下来进行测试:

 

 出现了405错误,这说明是请求methods问题中出错,我们这里是由于多写了一个空格导致的。

 删掉空格我们再次尝试过程中也可能会出现页面跳转失败问题(404 NOT found),同样的道理我们可能是因为路径出错,应该把“../”去除。

 这时明显跳转成功,接下来查看Mysql数据库中看看是否数据成功保存。

登录操作:

 

 

本文含有隐藏内容,请 开通VIP 后查看

网站公告

今日签到

点亮在社区的每一天
去签到