书城项目阶段二:用户注册和登陆的实现
需求 1:用户注册
1)访问注册页面
2)填写注册信息,提交给服务器
3)服务器应该保存用户
4)当用户已经存在----提示用户注册 失败,用户名已存在
5)当用户不存在-----注册成功
需求 2:用户登陆
1)访问登陆页面
2)填写用户名密码后提交
3)服务器判断用户是否存在
4)如果登陆失败 —>>>> 返回用户名或者密码错误信息
5)如果登录成功 —>>>>
JavaEE项目的三层框架
分层的目的时为了解耦。解耦就是为了降低代码的耦合都,方便项目后期维护和升级。
web层 | com.atguigu.web/servlet/controller | |
service层 | com.atguigu.service.impl | Service 接口包、实现类 |
dao层 | com.atguigu.dao.imp | Dao 接口包、实现类 |
实体Bean层 | com.atguigu.pojo/entity/domain/bean | JavaBean接口实现类 |
测试包 | com.atguigu.test/junit | |
工具类 | com.atguigu.test/junit | |
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对象
public class User {
private Integer id;
private String username;
private String password;
private String email;
}
3、编写工具类JdbcUtils
3.1导入需要的jar包(数据库和连接池需要)
druid-1.1.9.jar
mysql-connector-java-5.1.7-bin.jar
3.2 在src源码目录下编写jdbc.properties属性配置文件,放在resources目录下
username=root
password=123456
url=jdbc:mysql://localhost:3306/book?characterEncoding=UTF-8
driverClassName=com.mysql.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);
//System.out.println(dataSource.getConnection());
} catch (Exception e) {
e.printStackTrace();
}
}
//获取数据库连接池中的连接
//return 如果返回空,说明获取连接失败,有值就是连接成功
public static Connection getConnection(){
Connection conn = null;
try {
conn = dataSource.getConnection();
} catch (Exception e) {
e.printStackTrace();
}
return conn;
}
//关闭连接,放回数据库连接池
public static void close(Connection conn){
if(conn != null){
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
3.4 JdbcUtils测试
package com.atguigu.test;
import com.atguigu.utils.JdbcUtils;
import org.junit.jupiter.api.Test;
import java.sql.Connection;
public class JdbcUtilsTest {
@Test
public void testJdbcUtils(){
for (int i = 0; i < 30; i++) {
Connection connection = JdbcUtils.getConnection();
System.out.println(connection);
JdbcUtils.close(connection);
}
}
}
4、编写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 {
private QueryRunner queryRunner = new QueryRunner();
//update方法用来执行Insert、update、delete语句
//如果返回-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对应的参数值
* @return
* @param <T> 返回类型的泛型
*/
public <T> T queryForOne(Class<T> type,String sql,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语句
public <T> List<T> queryForList(Class<T> type,String sql,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语句
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;
import com.atguigu.pojo.User;
public interface UserDao {
//根据用户名查询用户信息
//如果返回null,说明没有这个用户
public User queryUserByUsername(String name);
//根据用户名和密码查询用户信息
//如果返回null,说明用户名或密码错误
public User queryUserByUsernameAndPassword(String username, String password);
//保护用户信息
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测试
package com.atguigu.test;
import com.atguigu.dao.UserDao;
import com.atguigu.dao.impl.UserDaoImpl;
import com.atguigu.pojo.User;
import org.junit.jupiter.api.Test;
import static org.junit.Assert.*;
public class UserDaoTest {
UserDao userDao = new UserDaoImpl();
@Test
public void queryUserByUsername() {
if(userDao.queryUserByUsername("admin") == 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,"lw123","123456","lw@qq.com")));
}
}
web阶段使用Base(路径写到工程名http://localhost:8080/工程名)+相对。Base标签一般写到Title下面
框架之后,使用绝对路径
6、编写UserService和测试
UserService接口
package com.atguigu.service;
import com.atguigu.pojo.User;
public interface UserService {
public void registUser(User user);
public User login(User user);
/**
* 检查用户名是否可用
* @param username
* @return 返回true表示用户名已存在,false表示用户名可用
*/
public boolean existUsername(String username);
}
UserServiceImplements实现类
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 {
//用Dao对象操作数据库
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) {
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;
import static org.junit.Assert.*;
public class UserServiceTest {
UserService userService = new UserServiceImpl();
@Test
public void registUser() {
userService.registUser(new User(null,"lala","lala666","lala@163.com"));
}
@Test
public void login() {
System.out.println(userService.login(new User(null,"admin","admin",null)));
}
@Test
public void existUsername() {
if(userService.existUsername("admin")){
System.out.println("用户名已存在!");
}else{
System.out.println("用户名可用!");
}
}
}
7、编写web层
实现用户注册功能
当用户在注册页面输入完成后,就会点击提交按钮,把参数都发送给服务器,去注册保存。
7.1 RegistServlet程序:
-
获取请求参数
-
检验验证码是否正确
-
正确
检查用户名是否存在
存在 返回注册页面
不存在 调用Service保存到数据库并返回注册成 功页面
-
不正确
返回注册页面
-
package com.atguigu.web;
import com.atguigu.pojo.User;
import com.atguigu.service.UserService;
import com.atguigu.service.impl.UserServiceImpl;
import javax.servlet.*;
import javax.servlet.http.*;
import java.io.IOException;
public class RegistServlet 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");
String email = request.getParameter("email");
String code = request.getParameter("code");
//2、检查验证码是否正确 == 写死 要求验证码为:abcde
if("abcde".equalsIgnoreCase(code)){
//检查用户名是否可用
if(userService.existUsername(username)){
//存在不可用,跳回注册页面
System.out.println("用户名["+username+"]已存在!");
request.getRequestDispatcher("/pages/user/regist.html").forward(request,response);
}else{
//可用,调用Service保存数据库中
userService.registUser(new User(null,username,password,email));
request.getRequestDispatcher("/pages/user/regist_success.html").forward(request,response);
}
}else{
//不正确,跳回注册页面,请求转发
System.ou.println("验证码["+code+"]错误!");
request.getRequestDispatcher("/pages/user/regist.html").forward(request,response);
}
}
}
7.2修改regist.html和regist_success.html页面
-
添加Base标签(永远固定相对路径的跳转结果)
<base href="http://localhost:8080/bookstore/">
-
修改base标签对页面中所有相对路径的影响
-
修改注册表单的提交地址和请求方式
7.3 编写LoginServlet程序
- 获取请求参数
- 调用Service方法处理业务,userService.login( )登录
- 根据login( )方法返回的结果判断是否登录成功,若用户名和密码匹配都正确,跳转到登录成功页面,否则,跳转到登录页面
package com.atguigu.web;
import com.atguigu.pojo.User;
import com.atguigu.service.UserService;
import com.atguigu.service.impl.UserServiceImpl;
import javax.servlet.*;
import javax.servlet.http.*;
import java.io.IOException;
public class LoginServlet extends HttpServlet {
UserService userService = new UserServiceImpl();
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String username = request.getParameter("username");
String password = request.getParameter("password");
User loginUser = userService.login(new User(null, username, password, null));
if(loginUser == null){
request.getRequestDispatcher("/pages/user/login.html").forward(request,response);
}else{
request.getRequestDispatcher("/pages/user/login_success.html").forward(request,response);
}
}
}
st(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String username = request.getParameter("username");
String password = request.getParameter("password");
User loginUser = userService.login(new User(null, username, password, null));
if(loginUser == null){
request.getRequestDispatcher("/pages/user/login.html").forward(request,response);
}else{
request.getRequestDispatcher("/pages/user/login_success.html").forward(request,response);
}
}
}