【尚硅谷_书城项目1.0】【学习笔记】寒假javaweb学习之旅1.3

这是,尚硅谷书城项目1.0,距离2月26日开学日只剩16天,😭😭😭,跺jiojio了

前言 / 目标

之前我们,简单学习过了xml、tomcat、servlet…在这个项目,我们要结合所学内容,实现网站功能。我们需要实现尚硅谷书城网站的,登入和注册功能。废话不多说,我们广块开始🐛🐛🐛🐛

主页面
在这里插入图片描述
注册页面
在这里插入图片描述
登入页面
在这里插入图片描述

1、javaEE三层架构介绍

在这里插入图片描述
分层的目的是为了解耦。解耦就是为了降低代码的耦合度。方便项目后期的维护和升级。

下面是文件名规范1下

web层

com.flzj.web/servlet/controller

service层

Service接口包 com.flzj.service
Service接口实现类 com.flzj.service.impl

dao持久层

Dao接口包 com.flzj.dao
Dao接口实现类 com.flzj.dao.impl

实体bean对象

com.flzj.pojo/entity/domain/bean JavaBean类

测试包

com.flzj.test/junit

工具类

com.flzj.utils

然后我们创建好后,大概是这个样子的,赶快继续开始我们的项目嗷

在这里插入图片描述

2、创建数据库

在这里插入图片描述
因为,我们要实现用户的注册和登入功能,这里我们创建一张用户表

DROP TABLE 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)
);

INSERT INTO t_user(`username`,`password`,`email`) 
	VALUES('admin','admin','admin@flzj.com');
	
SELECT * FROM t_user;

3、编写数据库表对应的javaBean对象

public class User {
    private Integer id;
    private String username;
    private String password;
    private String 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;
    }

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", username='" + username + '\'' +
                ", password='" + password + '\'' +
                ", email='" + 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;
    }
}

4、编写工具类

编写工具类,方便对数据库的操作

导个包🤤🤤🤤🤤
在这里插入图片描述
改改jdbc.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);
            System.out.println(dataSource.getConnection());
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    public static void main(String[] args) {

    }
    /*  获取数据库连接池的连接
        如果返回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();
            }
        }
    }
}

💣刚刚,👴跟着视频,差点跟进坑里,因为我的idea没有src,所以properties文件要放到resource下,才能被读到
在这里插入图片描述
然后我们赶快去com.flzj.test文件下创建一个类去测试看看

public class JdbcUtilsTest {
    @Test
    public void testJdbcUtils(){
        System.out.println(JdbcUtils.getConnection());
    }
}

效果图
在这里插入图片描述

5、Dao持久层

在这里插入图片描述

5.1、编写BaseDao

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

    /***
     * update() 方法来执行,Insert\Update\Delete语句
     * @return -1 表示失败,成功返回影响的行数
     */
    public int update(String sql,Object ...args){
        Connection connection = JdbcUtils.getConnection();
        try {
            return queryRunner.update(connection,sql, args);
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            JdbcUtils.close(connection);
        }
        return -1;
    }

    /***
     * 查询返回一条或者一个javabean的sql语句
     * @param type  返回的对象类型
     * @param sql   执行sql语句
     * @param args  sql对应的参数值
     * @param <T>   返回的类型的泛型
     * @return
     */
    public <T>T queryForOne(Class<T> type,String sql,Object...args){
        Connection connection = JdbcUtils.getConnection();
        try {
            return queryRunner.query(connection,sql,new BeanHandler<T>(type),args);
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            JdbcUtils.close(connection);
        }
        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 connection = JdbcUtils.getConnection();
        try {
            return queryRunner.query(connection,sql,new BeanListHandler<T>(type),args);
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            JdbcUtils.close(connection);
        }
        return null;
    }


    /***
     * 执行返回一行一列的sql语句
     * @param sql   执行sql语句
     * @param args  sql对应的参数值
     * @return
     */
    public Object queryForSingleValue(String sql,Object...args){
        Connection connection = JdbcUtils.getConnection();
        try {
            return queryRunner.query(connection,sql,new ScalarHandler(),args);
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            JdbcUtils.close(connection);
        }
        return null;
    }
}

5.2、编写UserDao

public interface UserDao {
    /***
     * 根据用户查询用户信息
     * @param username  用户名
     * @param password 密码
     * @return  如果返回null,说明用户名或密码错误
     */
    public User queryUserByUsername(String username,String password);
    /***
     * 根据用户查询用户信息
     * @param username  用户名
     * @return  如果返回null,说明没有这个用户
     */
    public User queryUserByUsernameAndPassword(String username);

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

然后再写个类来实现它

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

    @Override
    public User queryUserByUsernameAndPassword(String username, String password) {
        String sql = "select `id`,`username`,`password`,`email` from t_user where username = ? and password = ?";
        return queryForOne(User.class,sql,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());
    }
}

那么我们要怎么自动生成3个方法帮我们快速测试下捏?

在这里插入图片描述
在这里插入图片描述

所以说,我们跟着视频写的那个test真的皮用都没有了😭😭😭😭,idea版本高,自动就生成了test

public class UserDaoTest {
    //方便测试才放外面的
    UserDao userDao = new UserDaoImp();
    @Test
    public void queryUserByUsername() {

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

    @Test
    public void queryUserByUsernameAndPassword() {
        if(userDao.queryUserByUsernameAndPassword("admin","admin") == null){
            System.out.println("用户名或密码错误");
        }else{
            System.out.println("登入成功");
        }
    }
    @Test
    public void saveUser() {
        System.out.println(userDao.saveUser(new User(null,"ft","123456","246fzlj@qq.com")));
    }
}

下图为测试第一个方法的效果图
在这里插入图片描述

6、Service业务层

6.1、编写UserService

在这里插入图片描述
登入、注册、检查用户名是否存在

public interface UserService {

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

    /**
     * 登入
     * @param user
     * @return 如果登入失败返回null
     */
    public User login(User user);

    /**
     * 判断用户账号是否存在
     * @param username
     * @return 返回true说明存在
     */
    public boolean existsUsername(String username);

}

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 existsUsername(String username) {
        if(userDao.queryUserByUsername(username) == null){
            return false;
        }
        return true;
    }
}

6.2、测试

registUser()方法 (负责注册)

@Test
public void registUser() {
    userService.registUser(new User(null,"aaa","123456","aaa@qq.com"));
    userService.registUser(new User(null,"bbb","123456","bbb@qq.com"));
}

在这里插入图片描述

login()方法 (负责登入)

@Test
public void login() {
    if(userService.login(new User(null,"aaa","123456",null))== null){
        System.out.println("登入失败");
    }else{
        System.out.println("登入成功");
    }
}

在这里插入图片描述

existsUsername() 方法 (用来判断用户注册的用户名是否存在)

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

在这里插入图片描述

7、实现功能

7.1、实现用户注册功能

图解

在这里插入图片描述

代码实现

首先我们要写个RegistServlet程序,和去web.xml里配置

public class RegistServlet 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");
        String email = req.getParameter("email");
        String code = req.getParameter("code");

//        2、检查验证码是否正确      这里我们先写死abcde
        if("abcde".equals(code)) {
//              正确

//        3、检查用户名是否可用
            if(!userService.existsUsername(username)) {
//                可用
//        调用Sservice保存到数据库
                userService.registUser(new User(null,username,password,email));
//        跳到注册成功末面regist_success.html
                req.getRequestDispatcher("/pages/user/regist.html").forward(req,resp);
            }else {
//          不可用
            System.out.println("账号已存在");
//          跳回注册页面
            req.getRequestDispatcher("/pages/user/regist_success.html").forward(req,resp);
            }
        }else{
//                不正确
            System.out.println("验证密码[ "+code+" ]错误");
//        跳回注册页面
            req.getRequestDispatcher("/pages/user/regist.html").forward(req,resp);
        }
    }
}

<servlet>
    <servlet-name>RegistServlet</servlet-name>
    <servlet-class>com.flzj.web.RegistServlet</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>RegistServlet</servlet-name>
    <url-pattern>/registServlet</url-pattern>
</servlet-mapping>

然后我们溜到,regist.html,

改表单提交路径到registServlet

<form action="registServlet" method="post">
    <label>用户名称:</label>
    <input class="itxt" type="text" placeholder="请输入用户名"
           autocomplete="off" tabindex="1" name="username" id="username" />
    <br />
    <br />
    <label>用户密码:</label>
    <input class="itxt" type="password" placeholder="请输入密码"
           autocomplete="off" tabindex="1" name="password" id="password" />
    <br />
    <br />
    <label>确认密码:</label>
    <input class="itxt" type="password" placeholder="确认密码"
           autocomplete="off" tabindex="1" name="repwd" id="repwd" />
    <br />
    <br />
    <label>电子邮件:</label>
    <input class="itxt" type="text" placeholder="请输入邮箱地址"
           autocomplete="off" tabindex="1" name="email" id="email" />
    <br />
    <br />
    <label>验证码:</label>
    <input class="itxt" type="text" style="width: 150px;" id="code" name="code"/>
    <img alt="" src="../../static/img/code.bmp" style="float: right; margin-right: 40px">
    <br />
    <br />
    <input type="submit" value="注册" id="sub_btn" />
</form>

这里我们先用base标签,改路径。这么一改,我们的regist.html里面的css,jquery,什么的路径都要改动

<!--写base标签,永远固定相对路径跳转的结果		
记住工程名(book)后面要加/ 	下面这图base标签,book的后面没加/害我搞了半天
-->
<base href="http://localhost:8080/book/">
<link type="text/css" rel="stylesheet" href="../../static/css/style.css" >
<script type="text/javascript" src="../../static/script/jquery-1.7.2.js"></script>

为什么捏?😄,因为,写上base标签后,这里http://localhost:8080/book 的 …/…/ 的是 http://localhost:8080,所以这里被解读的相对路径为:http://localhost:8080/static/css/style.css,这根本不存在,所以我们只要把…/…/去掉即刻。

在这里插入图片描述

其他地方同理,什么之前写的,图片、视频、的相对路径 都要改改,其实实际上,也就是去去…/…/ 而已

下图为注册成功

在这里插入图片描述

7.2、用户登入

图解

在这里插入图片描述

代码实现

1、同样的,先去写一个base标签,修改css或者图片的相对路径,改改form表单的method 和 action

2、我们写个LoginServlet程序

public class LoginServlet extends HttpServlet {
    private UserService userService = new UserServiceImpl();
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//        1、获取请求的参数
        String username = request.getParameter("username");
        String password = request.getParameter("password");
        System.out.println("接收到用户的账为"+username+"\t"+password);
//        2、调用XxxService. xxx()处理业务
//        userService. login(登录
        User user = userService.login(new User(null, username, password, null));
//                3、根据login()方法返回结果判断登录是否成功
        if(!(user == null)) {
//                成功
//                跳到成功页面login_ success. html
            System.out.println(username + " 登入成功");
            request.getRequestDispatcher("/pages/user/login_success.html").forward(request,response);
        }else {
//                失败
//                跳回登录页面
            System.out.println(username + " 登入失败");
            request.getRequestDispatcher("/pages/user/login.html").forward(request,response);
        }
    }
}

在这里插入图片描述

7.3、小问题

刚刚出现了,浏览器缓存问题,就是,我这里html文件怎么修改,web工程里的相同html就是不会变,这个时候我们只要清楚缓存就行了,谷歌浏览器快捷键ctrl + shift + delet

在这里插入图片描述

还有一个,就是之前,servlet没学好的同学肯定会问了,嗨呀,这个表单的题交action为什么是action=“loginServlet”(servlet名),而不是action="/loginServlet"

<form action="loginServlet" method="post">
    <label>用户名称:</label>...

因为这样会被解释成 http://ip:port/你写的,下图为action = “/loginServlet”

在这里插入图片描述

8、IDE的Debug功能

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bytAw2v5-1644416046724)(D:\java\javaweb\picture\sanguigubookstoreitem\IDE调试1.png)]

我们去注册页面,正确填写后,点击注册,启动了RegistServlet程序,卡在我们设置的断点位置

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6C8bGAMX-1644416046724)(D:\java\javaweb\picture\sanguigubookstoreitem\注册页面点击后被卡.png)]

8.1、测试工具栏

在这里插入图片描述

8.2、变量窗口

它可以查看当前方法里的,所有有效变量(这里是doPost()方法里的所有有效变量)

在这里插入图片描述

8.3、方法调用栈窗口

1、方法调用栈可以查看当前线程有哪些方法调用信息
2、下面的调用上一行的方法,比如这里的doPost()方法调用了 getParameter()方法

在这里插入图片描述

8.4、其他常用调试相关按钮

在这里插入图片描述

  • 3
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值