第一阶段:主要是通过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); } } }