书城第二阶段——用户注册和登录
【尚硅谷最新版JavaWeb全套教程,java web零基础入门完整版-哔哩哔哩】https://b23.tv/6gk5sV
1. JavaEE 项目的三层架构
分层的目的是为了解耦。解耦就是为了降低代码的耦合度。方便项目后期的维护和升级。
web层 com.atguigu.web/servlet/controller
service层 com.atguigu.service Service接口包
com.atguigu.service.impl Service接口实现类
dao持久层 com.atguigu.dao Dao接口包
com.atguigu.dao.impl Dao接口实现类
实体bean对象 com.atguigu.pojo/entity/domain/bean JavaBean类
测试包 com.atguigu.test/junit
工具类 com.atguigu.utils
模块结构
1、先创建书城需要的数据库和表
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)
);
insert into t_user(`username`,`password,`email`) values ('admin','admin','admin@atguigu.com');
select * from t_user;
2、编写数据库表对应的JavaBean对象
User
package com.atguigu.pojo;
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;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setName(String name) {
this.username = name;
}
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 + '\'' +
'}';
}
}
3、编写工具类 JdbcUtils
3.1 导入需要的jar包
1.复制两个jar包在lib下
2.Ctrl+Alt+Shift+s
3.Libraries 中点+——》 点Java 选中上面的两个Jar包
4.先不加到模块下,点Cancel
5.改名字name:book_lib ——》Apply
6.Modules中,模块book 中 Dependencies中 点+ 点2Libraries 选中book_lib 点Add Seleted
7.Artifacts中 选中book 点Fix按钮 Apply OK
3.2 在src下编写jdbc.properties
username=root
password=root
url=jdbc:mysql://localhost:3306/book?serverTimezone=GMT%2B8
driverClass=com.mysql.cj.jdbc.Driver
jdbc.driver=com.mysql.cj.jdbc.Driver
initialSize=5
maxActive=10
3.3 编写JdbcUtils工具类
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);//Ctrl+ALT+T
} catch (Exception e){
e.printStackTrace();
}
}
/**
* 获取数据库连接池中的连接
* @return 如果返回null,说明获取连接失败<br/> 有值就是获取连接成功
*/
public static Connection getConnection(){
Connection conn=null;
try {
conn=dataSource.getConnection();
} catch (Exception e) {
e.printStackTrace();
}
return conn;
}
/**
* 关闭连接,放回数据库连接池
* @param conn
*/
public static void close(Connection conn){
if (conn!=null){
try {
conn.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
}
}
3.4 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);
}
}
}
4、编写BaseDao
导DbUtils的jar包
1.dbutils的jar包复制在lib下
2.Ctrl+Alt+Shift+s
3.Libraries中,选book_lib 中点+ 选择dbutils的jar包——》点击OK
4.Apply OK
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 {
//使用DbUtils操作数据库
private QueryRunner queryRunner=new QueryRunner();
/**
* update() 方法用来执行,Insert\Update\Delete语句
* @return 如果返回-1,说明执行失败<br/>返回其他表示影响的行数
*/
private int update(String sql,Object... args){
Connection connection= JdbcUtils.getConnection();
try {
return queryRunner.update(connection,sql,args);
} catch (SQLException throwables) {
throwables.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 con=JdbcUtils.getConnection();
try {
return queryRunner.query(con,sql,new BeanHandler<T>(type),args);
} catch (SQLException throwables) {
throwables.printStackTrace();
}finally {
JdbcUtils.close(con);
}
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();
}finally {
JdbcUtils.close(con);
}
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();
}finally {
JdbcUtils.close(conn);
}
return null;
}
}
5、编写 UserDao和测试
UserDao
package com.atguigu.dao;//ALT+Enter Move...
import com.atguigu.pojo.User;
public interface UserDao {
//Ctrl+Shift+T
/**
* 根据 用户名查询用户信息
* @param username 用户名
* @return 如果返回null,说明没有这个用户。
*/
public User queryUserByUsername(String username);
/**
* 根据 用户名和密码查询用户信息
* @param username
* @param password
* @return 如果返回null,说明没有这个用户。
*/
public User queryUserByUsernameAndPassword(String username,String password);
/**
* 保存用户信息
* @param user
* @return 返回-1表示操作失败,其他是sql语句影响的行数
*/
public int saveUser(User user);
}
UserDaoImpl
package com.atguigu.dao.impl;
import com.atguigu.dao.UserDao;
import com.atguigu.pojo.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());
}
}
测试:快捷键:在UserDao中Ctrl+Shift+T,生成包改成test包勾选全部方法
UserDaoTest
package com.atguigu.test;
import com.atguigu.dao.UserDao;
import com.atguigu.dao.impl.UserDaoImpl;
import com.atguigu.pojo.User;
import org.junit.Test;
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 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,"wzg168","123456","wzg168@qq.com")));
}
}
如果出现错误“程序包不存在 找不到符号,点File——》Invalidate Caches… 然后重启IDEA,重新导入DbUtils.jar包”
6、编写 UserService和测试
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 existUsername(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;
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){
//等于null,说明没查到,没查到表示可用
return false;
}
return true;
}
}
UserServiceTest
package com.atguigu.test;
import com.atguigu.pojo.User;
import com.atguigu.service.UserService;
import com.atguigu.service.impl.UserServiceImpl;
import org.junit.Test;
public class UserServiceTest {
UserService userService =new UserServiceImpl();
@Test
public void registUser() {
userService.registUser(new User(null,"bbj168","666666","bbj168@qq.com"));
userService.registUser(new User(null,"abc168","666666","abc168@qq.com"));
}
@Test
public void login() {
System.out.println(userService.login(new User(null,"wzg168","123456",null)));
}
@Test
public void existUsername() {
if (userService.existUsername("wzg16888")){
System.out.println("用户名已存在!");
}else {
System.out.println("用户名可用!");
}
}
}
7、编写web层
7.1 实现用户注册的功能
regist.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>尚硅谷会员注册页面</title>
<!--写base标签,永远固定相对路径跳转的结果-->
<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.js"></script>
<script type="text/javascript">
//页面加载完成之后
$(function () {
//给注册绑定单击事件
$("#sub_btn").click(function () {
//验证用户名:必须由字母,数字下划线组成,并且长度为5到12位
//1获取用户名输入框里的内容
var usernameText=$("#username").val();
//2创建正则表达式对象
var usernamePatt=/^\w{5,12}$/;
//3使test方法验证
if(!usernamePatt.test(usernameText)){
//4提示用户结果
$("span.errorMsg").text("用户名不合法!");
return false;
}
//验证密码:必须由字母,数字下划线组成,并且长度为5到12位
//1获取用户名输入框里的内容
var passwordText=$("#password").val();
//2创建正则表达式对象
var passwordPatt=/^\w{5,12}$/;
//3使test方法验证
if(!passwordPatt.test(passwordText)){
//4提示用户结果
$("span.errorMsg").text("密码不合法!");
return false;
}
//验证确认密码:和密码相同
//1获取确认密码内容
var repwdText=$("#repwd").val();
//2和密码相比较
if (repwdText!=passwordText){
//3提示用户
$("span.errorMsg").text("确认密码和密码不一致!");
return false;
}
//邮箱验证:xxxxx@xxx.com
//1获取邮箱里的内容
var emailText=$("#email").val();
//2创建正则表达式对象
var emailPatt=/^[a-z\d]+(\.[a-z\d]+)*@([\da-z](-[\da-z])?)+(\.{1,2}[a-z]+)+$/;
//3使test方法验证
if(!emailPatt.test(emailText)){
//4提示用户结果
$("span.errorMsg").text("邮箱格式不合法!");
return false;
}
//验证码现在只需要验证用户已输入。因为还没讲到服务器。验证码生成。
var codeText=$("#code").val();
//去掉验证码前后空格
alert("去空格前["+codeText+"]");
codeText=$.trim(codeText);
alert("去空格后["+codeText+"]");
if (codeText==null||codeText==""){
//提示用户结果
$("span.errorMsg").text("验证码不能为空");
return false;
}
$("span.errorMsg").text("");
});
});
</script>
<style type="text/css">
.login_form {
height: 420px;
margin-top: 25px;
}
</style>
</head>
<body>
<div id="login_header">
<img class="logo_img" alt="" src="static/img/logo.gif">
</div>
<div class="login_banner">
<div id="l_content">
<span class="login_word">欢迎注册</span>
</div>
<div id="content">
<div class="login_form">
<div class="login_box">
<div class="tit">
<h1>注册尚硅谷会员</h1>
<span class="errorMsg"></span>
</div>
<div class="form">
<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" name="code" style="..." id="code"/>
<img alt="" src="static/img/code.bmp" style="...">
<br/>
<br/>
<input type="submit" value="注册" id="sub_btn"/>
</form>
</div>
</div>
</div>
</div>
</div>
</body>
</html>
regist_success.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>尚硅谷会员注册页面</title>
<!--写base标签,永远固定相对路径跳转的结果-->
<base href="http://localhost:8080/book">
<link type="text/css" rel="stylesheet" href="static/css/style.css">
<style type="text/css">
h1{
text-align: center;
margin-top: 200px;
}
h1 a {
color: red;
}
</style>
</head>
<body>
<div id="header">
<img class="logo_img" alt="" src="static/img/logo.gif">
<span class="wel_word"></span>
<div>
<span>欢迎<span class="um_span">韩总</span>光临尚硅谷书城</span>
<a href="../order/order.html">我的订单</a>
<a href="../../index.html">注销</a>
<a href="../../index.html">返回</a>
</div>
</div>
<div id="main">
<h1>注册成功!<a href="../../index.html">转到主页</a></h1>
</div>
</body>
</html>
RegistServlet
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;
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".equalsIgnoreCase(code)){
// 3、检查用户名是否可用
if (userService.existUsername(username)){
System.out.println("用户名["+username+"]已存在!");
// 跳回注册页面
req.getRequestDispatcher("/pages/user/regist.html").forward(req,resp);
}else {
// 可用 调用Service保存到数据库
userService.registUser(new User(null,username,password,email));
// 跳到注册成功束面regist_success.html
req.getRequestDispatcher("/pages/user/regist_success.html").forward(req,resp);
}
}else {
System.out.println("验证码["+code+"]错误,");
req.getRequestDispatcher("/pages/user/regist.html").forward(req,resp);
}
}
}
在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>
7.2 IDEA中Debug调试的使用
7.2.1 Debg调试代码,首先需要两个元素;断点+Debug启动服务器
1、断点,只需要在代码需要停的行的左边上单击,就可以添加和取消
2、Debug启动Tomcat运行代码:
7.2.2 测试工具栏:
7.2.3 变量窗口
变量窗口:可以查看当前方法范围内的所有有效的变量。
其他常用调试相关按钮
7.3 用户登录功能的实现
login.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>尚硅谷会员登录页面</title>
<!--马base标签,永远固定相对路径跳转的结果-->
<base href= "http://localhost:8080/book/">
<link type="text/css" rel="stylesheet" href="static/css/style.css" >
</head>
<body>
<div id="login_header">
<img class="logo_img" alt="" src="static/img/logo.gif" >
</div>
<div class="login banner">
<div id="l_content">
<span class="login_word">欢迎登录</span>
</div>
<div id="content">
<div class="login_form">
<div class="login_box">
<div class="tit">
<h1>尚硅谷会员</h1>
<a href="pages/user/regist.html">立即注册</a>
</div>
<div class="msg_cont">
<b></b>
<span class="errorMsg">请输入用户名和密码</span>
</div>
<div class="form">
<form action="loginServlet" method="post">
<label>用户名称:</label>
<input class="itxt" type="text" placeholder="请输入用户名" autocomplete="off" tabindex="1" name="username"/>
<br/>
<br/>
<label>用户密码:</label>
<input class="itxt" type="password" placeholder="请输入密码" autocomplete="off" tabindex="1" name="password"/>
<br/>
<br/>
<input type="submit" value="登录" id="sub_btn"/>
</form>
</div>
</div>
</div>
</div>
</div>
</body>
</html>
login_success.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>尚硅谷会员登录</title>
<style type="text/css">
h1{
text-align: center;
margin-top: 200px;
}
h1 a {
color: red;
}
</style>
</head>
<body>
<div id="main">
<h1>登录成功!<a href="../../index.html">转到主页</a></h1>
</div>
</body>
</html>
LoginServlet
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;
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、调用XxxService.xxx()处理业务
User loginUser = userService.login(new User(null, username, password, null));
//如果等于null,说明登录失败
if (loginUser==null){
// 跳回登录页面
req.getRequestDispatcher("/pages/user/login.html").forward(req,resp);
}else {
// 成功
// 跳到成功页面login_success.html
req.getRequestDispatcher("/pages/user/login_success.html").forward(req,resp);
}
}
}
web.xml中的配置
<servlet>
<servlet-name>LoginServlet</servlet-name>
<servlet-class>com.atguigu.web.LoginServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>LoginServlet</servlet-name>
<url-pattern>/loginServlet</url-pattern>
</servlet-mapping>