书城项目
- 1.搭建项目环境
- 2.创建数据库以及t_user表
- 3.创建user表对应的Bean对象
- 4.JdbcUtils工具类
- 5.编写BasicDAO(所以Dao类的父类)
- 6.编写userDAO接口
- 7.编写userDAO接口的实现类UserDaoImpl
- 8.编写业务层 userService接口
- 9.编写业务层 userService实现类(UserServiceImpl)
- 10.实现用户注册功能
- 11.实现用户登录功能
- 当前src结构
- 12 将页面文件jsp动态化
- 13 抽取页面的公共内容
- 14 将base标签动态化
- 15 表单错误信息的回显
- 16 代码优化 合并loginServlet和registServlet
- 17 抽取baseServlet程序
- 18 编写Bean工具类
- 19 用el表达式实现表单回显
1.搭建项目环境
- Web
- Service
- Dao
- Bean
- Utils
- Test
- 页面资源文件
2.创建数据库以及t_user表
-- 检查数据库是否存在 存在就删除
DROP DATABASE IF EXISTS Book
-- 创建book数据库
CREATE DATABASE Book
use Book
-- 创建t_user表
-- id,username,password,email
CREATE TABLE t_user(
id INT PRIMARY KEY auto_increment,
`username` VARCHAR(32) NOT NULL UNIQUE,
`password` VARCHAR(32) NOT NULL,
`email` VARCHAR(200) NOT NULL
)
SELECT * FROM t_user;
--往t_user添加数据
INSERT INTO t_user(`username`,`password`,`email`)
VALUES('admin',"admin","2630235503@qq.com")
3.创建user表对应的Bean对象
package com.xh.Bean;
public class User {
private Integer id;
private String username;
private String password;
private String email;
//有参与无参构造函数
public User(Integer id, String username, String password, String email) {
this.id = id;
this.username = username;
this.password = password;
this.email = email;
}
public User() {
}
//get set 方法
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;
}
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", username='" + username + '\'' +
", password='" + password + '\'' +
", email='" + email + '\'' +
'}';
}
4.JdbcUtils工具类
- 引入驱动文件到WEB-INF/libs下
- 设置连接池配置文件
编写DruidUtils类
package com.xh.Utils;
import com.alibaba.druid.pool.DruidDataSourceFactory;
import org.junit.Test;
import javax.sql.DataSource;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;
public class DruidUtils {
static DataSource dataSource;
//在static代码块中初始化
static {
try {
//读取配置文件
Properties properties = new Properties();
// properties.load(new FileInputStream("com/xh/Utils/druid.properties"));
InputStream resourceAsStream = DruidUtils.class.getClassLoader().getResourceAsStream("com/xh/Utils/druid.properties");
properties.load(resourceAsStream);
dataSource = DruidDataSourceFactory.createDataSource(properties);
} catch (Exception e) {
//将编译异常转换成运行异常 交给调用者处理
throw new RuntimeException(e);
}
}
//连接方法
public static Connection getConnection(){
try {
return dataSource.getConnection();
} catch (SQLException e) {
//将编译异常转换成运行异常 交给调用者处理
throw new RuntimeException(e);
}
}
//关闭资源方法
//Result 结果集
//Statement PreparedStatement
//Connection 连接
//因为 PreparedStatement是Statement子类 写Statement即可
//如果需要关闭就输入对象,否则输入NULL
public static void close(ResultSet result, Statement statement, Connection connection){
try {
if (result !=null){
result.close();
}
if (statement != null){
statement.close();
}
if (connection != null){
connection.close();
}
}catch(Exception e){
throw new RuntimeException(e);
}
}
}
5.编写BasicDAO(所以Dao类的父类)
package com.xh.Dao.impl;
import com.xh.Utils.DruidUtils;
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 org.junit.Test;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.List;
/**
* 开发basic_DAO 是其他DAO的父类
*/
public class BasicDAO<T>{
QueryRunner qr = new QueryRunner();
//开发dml语句,针对任意表
public int update(String sql,Object... parameters){
Connection connection = null;
try {
//获得连接
connection = DruidUtils.getConnection();
//执行sql语句
int update = qr.update(connection, sql, parameters);
return update;
} catch (SQLException e) {
throw new RuntimeException(e);
}finally {
//释放资源
DruidUtils.close(null,null,connection);
}
}
@Test
public void testUpdate(){
int update = this.update("update diningTable set state ='空' where id = 1");
}
//开发查询返回多条记录 针对任意表
public List<T> queryMultiply(String sql, Class<T> clazz , Object... parameters){
Connection connection = null;
try {
//获得连接
connection = DruidUtils.getConnection();
//执行sql语句
return qr.query(connection,sql,new BeanListHandler<T>(clazz),parameters);
} catch (SQLException e) {
throw new RuntimeException();
}finally {
//释放资源
DruidUtils.close(null,null,connection);
}
}
//开发查询返回一条记录 针对任意表
public T querySingle(String sql, Class<T> clazz, Object... parameters){
Connection connection = null;
try {
//获得连接
connection = DruidUtils.getConnection();
//执行sql语句
return qr.query(connection,sql,new BeanHandler<T>(clazz),parameters);
} catch (SQLException e) {
throw new RuntimeException();
}finally {
//释放资源
DruidUtils.close(null,null,connection);
}
}
//查询单行单列的方法,即返回单值的方法
public Object queryScalar(String sql, Object... parameters) {
Connection connection = null;
try {
connection = DruidUtils.getConnection();
return qr.query(connection, sql, new ScalarHandler(), parameters);
} catch (SQLException e) {
throw new RuntimeException(e); //将编译异常->运行异常 ,抛出
} finally {
DruidUtils.close(null, null, connection);
}
}
}
6.编写userDAO接口
package com.xh.Dao;
import com.xh.Bean.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);
/**
* 根据user对象创建用户对象
* @param user
* @return 返回受影响的行数
*/
public int saveUser(User user);
}
7.编写userDAO接口的实现类UserDaoImpl
package com.xh.Dao.impl;
import com.xh.Bean.User;
import com.xh.Dao.UserDao;
public class UserDaoImpl extends BasicDAO<User> implements UserDao {
@Override
public User queryUserByUsername(String username) {
String sql = "select * from t_user where username=?";
return querySingle(sql,User.class,username);
}
@Override
public User queryUserByUsernameAndPassword(String username, String password) {
String sql = "select * from t_user where username=? and password=?";
return querySingle(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());
}
}
8.编写业务层 userService接口
package com.xh.Service;
import com.xh.Bean.User;
public interface UserService {
/**
* 检查用户名是否可用
* @param username
* @return 用户存在返回true 不存在返回false
*/
public boolean existsUsername(String username);
/**
* 注册用户
* @param username
* @param password
* @param email
* @return 创建成功返回true 失败返回false
*/
public boolean rigistUser(String username,String password,String email);
/**
* 登录
* @param username
* @param password
* @return 登录成功返回用户对象 不存在返回null
*/
public User login(String username,String password);
}
9.编写业务层 userService实现类(UserServiceImpl)
package com.xh.Service.impl;
import com.xh.Bean.User;
import com.xh.Dao.UserDao;
import com.xh.Dao.impl.UserDaoImpl;
import com.xh.Service.UserService;
public class UserServiceImpl implements UserService {
UserDao userDao = new UserDaoImpl();
@Override
public boolean existsUsername(String username) {
User user = userDao.queryUserByUsername(username);
if (user == null){
return false;
}
return true;
}
@Override
public boolean rigistUser(String username, String password, String email) {
User user = new User(username, password, email);
int result = userDao.saveUser(user);
if (result<1){
return false;
}
return true;
}
@Override
public User login(String username, String password) {
return userDao.queryUserByUsernameAndPassword(username, password);
}
}
10.实现用户注册功能
RegistServlet程序
package com.xh.Web;
import com.xh.Bean.User;
import com.xh.Service.UserService;
import com.xh.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.验证验证码信息是否正确
if (!("abcd".equalsIgnoreCase(code))){
System.out.println("验证码["+code+"]不正确");
//跳回注册页面
req.getRequestDispatcher("/pages/user/regist.html").forward(req, resp);
return;
}
//3.验证用户名是否可用
if (userService.existsUsername(username)){
System.out.println("用户["+username+"]已存在");
//跳回注册页面
req.getRequestDispatcher("/pages/user/regist.html").forward(req, resp);
return;
}
//4.注册用户
if (!(userService.rigistUser(username,password,email))){
System.out.println("用户注册失败");
//失败跳回注册页面
req.getRequestDispatcher("/pages/user/regist.html").forward(req, resp);
return;
}
req.getRequestDispatcher("/pages/user/regist_success.html").forward(req, resp);
return;
}
}
在web.xml中配置RegistServlet
<servlet>
<servlet-name>RegistServlet</servlet-name>
<servlet-class>com.xh.Web.RegistServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>RegistServlet</servlet-name>
<url-pattern>/RegistServlet</url-pattern>
</servlet-mapping>
11.实现用户登录功能
RegistServlet程序
package com.xh.Web;
import com.xh.Service.UserService;
import com.xh.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 {
//获得请求信息
String username = req.getParameter("username");
String password = req.getParameter("password");
//验证账号密码
if (userService.login(username,password)==null){
System.out.println("用户名或密码错误");
req.getRequestDispatcher("/pages/user/login.html").forward(req,resp);
return;
}
req.getRequestDispatcher("/pages/user/login_success.html").forward(req,resp);
}
}
在web.xml中配置LoginServlet
<servlet>
<servlet-name>LoginServlet</servlet-name>
<servlet-class>com.xh.Web.LoginServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>LoginServlet</servlet-name>
<url-pattern>/LoginServlet</url-pattern>
</servlet-mapping>
当前src结构
12 将页面文件jsp动态化
- 将文件后缀改为jsp文件
- 在所有jsp文件顶部添加page标签
13 抽取页面的公共内容
- head中的base标签,css样式,jQuery标签
编写head.jsp文件:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<base href="/">
<link type="text/css" rel="stylesheet" href="static/css/style.css" >
<script type="text/javascript" src="static/script/jquery-3.6.0.min.js"></script>
在每个页面中静态引用head.jsp文件:
<%-- 静态包含 base标签 css样式引入标签 jquery文件引入标签 --%>
<%@include file="/pages/common/head.jsp"%>
- 登录成功后的菜单
编写login_sucess_menu.jsp文件:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<div>
<span>欢迎<span class="um_span">韩总</span>光临尚硅谷书城</span>
<a href="pages/order/order.jsp">我的订单</a>
<a href="index.jsp">注销</a>
<a href="index.jsp">返回</a>
</div>
在页面中引用login_sucess_menu.jsp文件:
<%--静态包含 登录成功之后的菜单--%>
<%@include file="/pages/common/login_sucess_menu.jsp"%>
- 所有页面的页脚
在页面中编写footer.jsp文件:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<div id="bottom">
<span>
尚硅谷书城.Copyright ©2015
</span>
</div>
在页面中引用footer.jsp文件:
<%-- 静态包含页脚页面--%>
<%@include file="/pages/common/footer.jsp"%>
- manger模块的菜单
编写manager_menu菜单:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<div>
<a href="book_manager.jsp">图书管理</a>
<a href="order_manager.jsp">订单管理</a>
<a href="../../index.jsp">返回商城</a>
</div>
在页面中静态引用manager_menu菜单:
<%-- 静态包含页脚页面--%>
<%@include file="/pages/common/footer.jsp"%>
14 将base标签动态化
我们原本的base标签:
<base href="http://localhost:8080/Book/">
浏览器获得相对路径时为:
会从客户端本地获取文件 而不是服务端获取。
所以我们需要将base标签动态化,以正常的从服务端获取文件
15 表单错误信息的回显
在登录或者注册页面,如果失败我们希望将错误信息返回给jsp页面。如登录界面失败时,将失败信息回传给jsp页面,jsp页面进行操作
**思路:**在servlet程序中,使用response域,将失败信息和用户名放入域中。jsp页面读取域数据,如果有错误信息就将其打印。
16 代码优化 合并loginServlet和registServlet
原因: 在正式开发中,我们一般一个模块使用一个servlet程序。如user模块,我们只使用一个userServlet程序,该程序负责对user模块的请求进行响应
**思路:**我们将loginServlet和registServlet的请求操作封装成方法,放到userServlet中。并在jsp页面表单中设置隐藏域jsp<hidden name="action" values="(页面名)">
。userServlet的请求方法通过判断action的值,调用对应的业务方法。
**优化一:**通过反射优化action的值的判断
**原因:**我们原先通过if else语句 判断action值应该调用的业务方法。如果以后我们要增加新的业务方法,要继续编写新的if else语句,代码的复用性不高
**思路:**观察可以发现,action值与业务方法名是相同的。我们可以通过反射,用action值获得业务方法然后执行。
这样我们新增业务方法时,只需要编写新的业务方法,并把jsp页面中的action值设置为业务方法名。也可以使用反射获得对应的业务方法,不需要编写新的if else语句
17 抽取baseServlet程序
**原因:**观察可以发现,我们每个Servlet的程序的请求方法,都是判断action值然后调用对应的业务方法
思路我们可以创建一个baseServlet程序让所有的servlet程序继承他。baseServlet程序中编写(判断action值然后调用对应的业务方法)
18 编写Bean工具类
- 导入第三方包
- 通过第三方包的方法 将请求参数放入bean对象中。
19 用el表达式实现表单回显