1、JavaEE 项目的三层架构
2、先创建书城需要的数据库和表
drop database if exists book;
create database 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@aiguigu.com’);
select * from t_user;
3、编写数据库表对应的 JavaBean 对象
public class User {
private Integer id;
private String username;
private String password;
private String email;
}
4、编写工具类 JdbcUtils
4.1、导入需要的 jar包(数据库和连接池需要)
导入完成之后:
4.2 在 src 源码目录编写 jdbc.properties 属性配置文件
4.3 编写 JdbcUtils 工具类
package com.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();
}
}
/*
* 获取数据库连接池中的连接
*@return 如果返回null,说明获取连接失败<br/>有值就是获取连接成功 */
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();
}
}
}
}
4.4、Jdbc测试
package com.aiguigu.test;
import com.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);
}
}
}
5、编写BaseDao(这一块不懂,得补)
package com.aiguigu.dao;
import com.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.awt.*;
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/>返回其他表示影响的行数
*/
public int update(String sql,Object ... args){
Connection connection = JdbcUtils.getConnection();
try {
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> 返回的类型的泛型*/
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 e) {
e.printStackTrace();
}finally {
JdbcUtils.close(con);
}
return null;
}
/**
* 查询返回多个 javaBean 的 sql 语句
* @param type 返回的对象类型
* @param sql 执行的sql语句
* @param args sql对应的参数值
* @param <T> 返回的类型的泛型*/
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 e) {
e.printStackTrace();
}finally {
JdbcUtils.close(con);
}
return null;
}
/**
* 执行返回一行一列的sql语句
* @param sql 执行的sql语句
* @param args sql对应的参数值*/
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;
}
}
6、编写UserDao 和测试
package com.aiguigu.dao;
import com.aiguigu.pojo.User;
public interface UserDao {
/**
* 根据用户名查询用户信息
* @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);
}
package com.aiguigu.dao.impl;
import com.aiguigu.dao.BaseDao;
import com.aiguigu.dao.UserDao;
import com.aiguigu.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());
}
}
package com.aiguigu.dao.impl;
import com.aiguigu.pojo.User;
import org.junit.Test;
import static org.junit.Assert.*;
public class UserDaoImplTest {
@Test
public void queryUserByUsername() {
UserDaoImpl userDao = new UserDaoImpl();
if (userDao.queryUserByUsername("admin") == null){
System.out.println("用户名可用");
}else {
System.out.println("用户名已存在");
}
}
@Test
public void queryUserByUsernameAndPassword() {
UserDaoImpl userDao = new UserDaoImpl();
if (userDao.queryUserByUsernameAndPassword("admin","admin") == null){
System.out.println("用户名或密码错误,登录失败");
}else {
System.out.println("查询成功");
}
}
@Test
public void saveUser() {
UserDaoImpl userDao = new UserDaoImpl();
System.out.println( userDao.saveUser(new User(null,"qweg168", "12qw6", "qwe168@qq.com")) );
}
}
编写UserService 和测试
UserService接口:
package com.aiguigu.service;
import com.aiguigu.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.aiguigu.service.impl;
import com.aiguigu.dao.UserDao;
import com.aiguigu.dao.impl.UserDaoImpl;
import com.aiguigu.pojo.User;
import com.aiguigu.service.UserService;
import com.aiguigu.test.UserDaoImplTest;
public class UserServiceImpl implements UserService {
private UserDao useDao = new UserDaoImpl();
@Override
public void registUser(User user) {
useDao.saveUser(user);
}
@Override
public User login(User user) {
return useDao.queryUserByUsernameAndPassword(user.getUsername(),user.getPassword());
}
@Override
public boolean existUsername(String username) {
if (useDao.queryUserByUsername(username) == null){
// 等于null,说明没查到,没查到表示可用
return false;
}
return true;
}
}
UserServiceImplTest:
package com.aiguigu.test;
import com.aiguigu.dao.impl.UserDaoImpl;
import com.aiguigu.pojo.User;
import com.aiguigu.service.UserService;
import com.aiguigu.service.impl.UserServiceImpl;
import org.junit.Test;
import static org.junit.Assert.*;
public class UserServiceImplTest {
UserService userService = new UserServiceImpl();
@Test
public void registUser() {
userService.registUser(new User(null,"qwe1234","qwe123",null));
}
@Test
public void login() {
System.out.println(userService.login(new User(null,"qwe1234","qwe1235",null)));
}
@Test
public void existUsername() {
if (userService.existUsername("qwe1234")){
System.out.println("用户名已存在!");
}else {
System.out.println("用户名可用!");
}
}
}
7、编写 web 层
7.1、实现用户注册的功能
分析:
编写 RegistServlet:
package com.aiguigu.web;
import com.aiguigu.dao.UserDao;
import com.aiguigu.pojo.User;
import com.aiguigu.service.UserService;
import com.aiguigu.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 {
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)){//equalsIgnoreCase:比较时忽略大小写
//正确
//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);
}
}
}
在 前端的 regist.html 页面加上 base相对路径
<!--写 base 标签,永远固定相对路径跳转 的结果-->
<base href="http://localhost:8080/book/">
修改 regist.html 里面的资源路径:
在页面运行按 F12 通过 网络来测试,有 报红的 都要修改路径
修改注册表单的提交 路径 并添加 post 方法 将表单信息发送给 servlet服务器:
验证码输入框 添加一个 name属性 便于服务器获取(这个以后优化):
后端接收参数:
对接收到的参数进行以下操作:
//2.检查 验证码是否正确 写死,要求验证码为:abcde
if ("abcde".equalsIgnoreCase(code)){//equalsIgnoreCase:比较时忽略大小写
//正确
//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);
}
到 regist,html 进行测试