本次练习基于how2j尝试开发一个购物车
1.创建一个购物车(cart)数据库,用于存放购物车的数据:
(1)在MySQL-Front的SQL编辑器中输入以下SQL语句:
登录时会自动进入我们上一次使用的数据库,我这里是“how2java”,创建好cart数据库后重新登录,选择新的数据库。
– 创建名为cart的数据库
create database cart;
以注释为分界,依次插入SQL语句
(1)在其中建立一个用于存储商品数据的表product,插入4条数据;
(2)在其中建立一个用于存储用户数据的表user,插入1条数据;
(3)在其中建立一个用于存储商品数据的表product,插入4条数据;
sql代码如下:
-- 如果product表已经存在,则删除
DROP TABLE IF EXISTS `product`;
-- 创建名为product的表,包含id、name、price三个字段
CREATE TABLE `product` (
`id` int(11) DEFAULT NULL,
`name` varchar(50) DEFAULT NULL,
`price` float DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- 向product表中插入四条记录
insert into product values(1,'黑色的丝袜',500);
insert into product values(2,'充气娃娃',2500);
insert into product values(3,'皮鞭',180);
insert into product values(4,'蜡烛',0.20);
-- 创建名为user的表,包含id、name、password三个字段
-- 使用InnoDB存储引擎,使用utf8字符集
create table user(
id int,
name varchar(50),
password varchar(50)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- 向user表中插入一条记录,id为1,name为tom,password为123
insert into user values(1,'tom','123');
-- 创建名为order_的表,包含id、uid两个字段
-- id为自增长字段,作为主键
create table order_(
id int AUTO_INCREMENT,
uid int,
primary key(id)
);
-- 创建名为orderitem的表,包含id、pid、num、oid四个字段
-- id为自增长字段,作为主键
create table orderitem(
id int AUTO_INCREMENT,
pid int,
num int,
oid int,
primary key(id)
);
(2)运行结果&&操作流程:
2.创建一个动态的Web项目:
(1)新建一个Dynamic Web Project,命名为”cart“
(2)为当前项目导入所需的包:
参照这篇博客的"1.为新建的项目导入支持MVC的jar包"
3.应用MVC思想构建产品模块:
(1)M:
在Java Resource的src下new两个class,分别名为Product和ProductDAO,分别放在bean包和dao包下,
bean包下的文件用来定义事物的属性和方法
dao包下的文件用来使视图层与数据库进行交互
代码如下:
Product.java:
package bean;
public class Product {
private int id; // 商品ID
private String name; // 商品名称
private float price; // 商品价格
public int getId() { // 获取商品ID
return id;
}
public void setId(int id) { // 设置商品ID
this.id = id;
}
public String getName() { // 获取商品名称
return name;
}
public void setName(String name) { // 设置商品名称
this.name = name;
}
public float getPrice() { // 获取商品价格
return price;
}
public void setPrice(float price) { // 设置商品价格
this.price = price;
}
}
ProductDAO.java:
package dao;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import bean.Product;
public class ProductDAO {
public static void main(String[] args) {
System.out.println(new ProductDAO().ListProduct().size());
}
public List<Product> ListProduct() {
List<Product> products = new ArrayList<Product>(); // 创建商品列表
try {
Class.forName("com.mysql.jdbc.Driver"); // 加载MySQL驱动
Connection c = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/Cart?characterEncoding=UTF-8",
"root", "admin"); // 建立数据库连接
String sql = "select * from product order by id desc"; // SQL查询语句
PreparedStatement ps = c.prepareStatement(sql); // 创建PreparedStatement对象
ResultSet rs = ps.executeQuery(); // 执行查询操作
while (rs.next()) { // 遍历查询结果
Product product = new Product(); // 创建商品对象
int id = rs.getInt(1); // 获取商品ID
String name = rs.getString(2); // 获取商品名称
float price = rs.getFloat(3); // 获取商品价格
product.setId(id); // 设置商品ID
product.setName(name); // 设置商品名称
product.setPrice(price); // 设置商品价格
products.add(product); // 将商品添加到商品列表中
}
ps.close(); // 关闭PreparedStatement对象
c.close(); // 关闭数据库连接
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return products; // 返回商品列表
}
}
(2)V:
在WebContent下新建listHero.jsp文件,
代码如下:
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8" import="java.util.*"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<!-- 建立一个表格,用于显示商品信息 -->
<table align='center' border='1' cellspacing='0'>
<tr>
<td>id</td> <!-- 商品ID列 -->
<td>名称</td> <!-- 商品名称列 -->
<td>价格</td> <!-- 商品价格列 -->
<td>购买</td> <!-- 购买按钮列 -->
</tr>
<c:forEach items="${products}" var="product" varStatus="st">
<!-- 遍历商品列表,显示每个商品的信息 -->
<tr>
<td>${product.id}</td> <!-- 显示商品ID -->
<td>${product.name}</td> <!-- 显示商品名称 -->
<td>${product.price}</td> <!-- 显示商品价格 -->
<td>
<!-- 提交表单,将商品ID和购买数量传递给后台处理 -->
<form action="addOrderItem" method="post">
数量<input type="text" value="1" name="num"> <!-- 购买数量输入框 -->
<input type="hidden" name="pid" value="${product.id}"> <!-- 隐藏域,保存商品ID -->
<input type="submit" value="购买"> <!-- 提交按钮 -->
</form>
</td>
</tr>
</c:forEach>
</table>
(3)C:
在src下新建servlet类,取名为"ProductListServlet",放在servlet包下,注意数据库的名称、登录名、密码要与本机的一致
代码如下:
package dao;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import bean.Product;
public class ProductDAO {
public static void main(String[] args) {
System.out.println(new ProductDAO().ListProduct().size());
}
public List<Product> ListProduct() {
List<Product> products = new ArrayList<Product>(); // 创建商品列表
try {
Class.forName("com.mysql.jdbc.Driver"); // 加载MySQL驱动
Connection c = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/cart?characterEncoding=UTF-8",
"root", "admin"); // 建立数据库连接
String sql = "select * from product order by id desc"; // SQL查询语句
PreparedStatement ps = c.prepareStatement(sql); // 创建PreparedStatement对象
ResultSet rs = ps.executeQuery(); // 执行查询操作
while (rs.next()) { // 遍历查询结果
Product product = new Product(); // 创建商品对象
int id = rs.getInt(1); // 获取商品ID
String name = rs.getString(2); // 获取商品名称
float price = rs.getFloat(3); // 获取商品价格
product.setId(id); // 设置商品ID
product.setName(name); // 设置商品名称
product.setPrice(price); // 设置商品价格
products.add(product); // 将商品添加到商品列表中
}
ps.close(); // 关闭PreparedStatement对象
c.close(); // 关闭数据库连接
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return products; // 返回商品列表
}
}
(4)运行结果:
运行ProductListHero.java:
4.应用MVC思想构建用户模块:
(1)M:
在bean和dao包下,分别new两个class,取名为User和UserDAO代码如下:
User.java:
package bean;
public class User {
private int id; // 用户ID
private String name; // 用户名
private String password; // 密码
public int getId() { // 获取用户ID
return id;
}
public void setId(int id) { // 设置用户ID
this.id = id;
}
public String getName() { // 获取用户名
return name;
}
public void setName(String name) { // 设置用户名
this.name = name;
}
public String getPassword() { // 获取密码
return password;
}
public void setPassword(String password) { // 设置密码
this.password = password;
}
}
UserDAO.java:
package dao;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import bean.User;
public class UserDAO {
public static void main(String[] args) {
//测试getUser方法是否能正确返回用户id
System.out.println(new UserDAO().getUser("tom", "123").getId());
}
public User getUser(String name, String password) {
User result = null;
try {
//加载MySQL数据库驱动程序
Class.forName("com.mysql.jdbc.Driver");
//连接MySQL数据库
Connection c = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/cart?characterEncoding=UTF-8",
"root", "admin");
//SQL查询语句
String sql = "select * from user where name = ? and password = ?";
//创建PreparedStatement对象
PreparedStatement ps = c.prepareStatement(sql);
//设置查询参数
ps.setString(1, name);
ps.setString(2, password);
//执行查询并返回结果集
ResultSet rs = ps.executeQuery();
//如果结果集非空,则将查询结果封装成User对象
if (rs.next()){
result = new User();
result.setId(rs.getInt(1));
result.setPassword(password);
result.setName(name);
}
//关闭PreparedStatement对象
ps.close();
//关闭数据库连接
c.close();
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return result;
}
}
(2)V:
在WebContent下新建一个jsp文件,取名为login,login.jsp代码如下:
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8" import="java.util.*"%>
<!-- 指定页面的语言为java,内容类型为HTML,字符集为UTF-8,导入java.util包 -->
<!DOCTYPE html>
<!-- 声明文档类型为HTML5 -->
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<!-- 指定页面编码为UTF-8 -->
<form action="login" method="post">
<!-- 创建表单,提交到login页面,使用POST方法提交 -->
账号: <input type="text" name="name"> <br>
<!-- 创建账号输入框 -->
密码: <input type="password" name="password"> <br>
<!-- 创建密码输入框 -->
<input type="submit" value="登录">
<!-- 创建提交按钮 -->
</form>
(3)C:
在servelet包下new一个servlet,取名为UserLoginServlet,代码如下:
package servlet;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import bean.User;
import dao.UserDAO;
@WebServlet("/login")
public class UserLoginServlet extends HttpServlet {
protected void service(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String name = request.getParameter("name");
String password = request.getParameter("password");
User user = new UserDAO().getUser(name, password);
if (null != user) {
request.getSession().setAttribute("user", user);
response.sendRedirect("listProduct");
} else
response.sendRedirect("login.jsp");
}
}
(4)运行结果:
5.应用MVC思想构建购物车模块
(1)M:
在bean包下new一个名为OrdeItem的class,Ordertem.java的代码如下:
package bean;
public class OrderItem {
// 订单项ID
private int id;
// 商品信息
private Product product;
// 购买数量
private int num;
// 获取订单项ID
public int getId() {
return id;
}
// 设置订单项ID
public void setId(int id) {
this.id = id;
}
// 获取商品信息
public Product getProduct() {
return product;
}
// 设置商品信息
public void setProduct(Product product) {
this.product = product;
}
// 获取购买数量
public int getNum() {
return num;
}
// 设置购买数量
public void setNum(int num) {
this.num = num;
}
}
修改ProductDAO.java,修改后的代码如下:
package dao;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import bean.Product;
public class ProductDAO {
public static void main(String[] args) {
System.out.println(new ProductDAO().getProduct(1).getName()); // 测试 getProduct 方法
}
public Product getProduct(int id) { // 获取指定 id 的商品信息
Product result = null;
try {
Class.forName("com.mysql.jdbc.Driver"); // 加载 JDBC 驱动
Connection c = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/cart?characterEncoding=UTF-8",
"root", "admin"); // 建立数据库连接
String sql = "select * from product where id = ?"; // SQL 查询语句
PreparedStatement ps = c.prepareStatement(sql); // 创建 PreparedStatement 对象
ps.setInt(1, id); // 设置查询参数
ResultSet rs = ps.executeQuery(); // 执行查询操作
if (rs.next()) { // 如果查询结果非空
result = new Product(); // 创建 Product 对象
result.setId(id); // 设置商品 id
String name = rs.getString(2); // 获取商品名称
float price = rs.getFloat(3); // 获取商品价格
result.setName(name); // 设置商品名称
result.setPrice(price); // 设置商品价格
}
ps.close(); // 关闭 PreparedStatement 对象
c.close(); // 关闭数据库连接
} catch (ClassNotFoundException e) { // 如果找不到 JDBC 驱动
e.printStackTrace(); // 打印异常信息
} catch (SQLException e) { // 如果 SQL 查询出错
e.printStackTrace(); // 打印异常信息
}
return result; // 返回查询结果
}
public List<Product> ListProduct() { // 获取所有商品信息
List<Product> products = new ArrayList<Product>(); // 创建 Product 对象列表
try {
Class.forName("com.mysql.jdbc.Driver"); // 加载 JDBC 驱动
Connection c = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/cart?characterEncoding=UTF-8",
"root", "admin"); // 建立数据库连接
String sql = "select * from product order by id desc"; // SQL 查询语句
PreparedStatement ps = c.prepareStatement(sql); // 创建 PreparedStatement 对象
ResultSet rs = ps.executeQuery(); // 执行查询操作
while (rs.next()) { // 遍历查询结果
Product product = new Product(); // 创建 Product 对象
int id = rs.getInt(1); // 获取商品 id
String name = rs.getString(2); // 获取商品名称
float price = rs.getFloat(3); // 获取商品价格
product.setId(id); // 设置商品 id
product.setName(name); // 设置商品名称
product.setPrice(price); // 设置商品价格
products.add(product); // 将 Product 对象添加到列表中
}
ps.close(); // 关闭 PreparedStatement 对象
c.close(); // 关闭数据库连接
} catch (ClassNotFoundException e) { // 如果找不到 JDBC 驱动
e.printStackTrace(); // 打印异常信息
} catch (SQLException e) { // 如果 SQL 查询出错
e.printStackTrace(); // 打印异常信息
}
return products; // 返回查询结果列表
}
}
(2)V:
在WebContent下新建文件“listOrderItem.jsp”,代码如下“:
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8" import="java.util.*" isELIgnored="false"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<h1 align="center" >购物车</h1>
<!-- 创建一个表格,设置表格属性为居中对齐,边框为1,单元格间距为0 -->
<table align='center' border='1' cellspacing='0'>
<!-- 创建表头 -->
<tr>
<td>商品名称</td>
<td>单价</td>
<td>数量</td>
<td>小计</td>
</tr>
<!-- 遍历订单项列表,将订单项信息填充到表格中 -->
<c:forEach items="${ois}" var="oi" varStatus="st">
<tr>
<td>${oi.product.name}</td>
<td>${oi.product.price}</td>
<td>${oi.num}</td>
<td>${oi.product.price*oi.num}</td>
</tr>
</c:forEach>
</table>
(3)C:
在servelt包下新建servlet文件"OrderIteAddServlet.java",代码如下:
package servlet;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import bean.OrderItem;
import bean.Product;
import dao.ProductDAO;
@WebServlet("/addOrderItem")
public class OrderItemAddServlet extends HttpServlet {
protected void service(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// 获取用户提交的数量和产品ID
int num = Integer.parseInt(request.getParameter("num"));
int pid = Integer.parseInt(request.getParameter("pid"));
// 根据产品ID获取对应的产品信息
Product p = new ProductDAO().getProduct(pid);
// 创建订单项对象
OrderItem oi = new OrderItem();
// 设置订单项数量和对应的产品信息
oi.setNum(num);
oi.setProduct(p);
// 获取当前用户的所有订单项
List<OrderItem> ois = (List<OrderItem>) request.getSession().getAttribute("ois");
// 如果当前用户还没有订单项,则创建一个新的订单项列表
if (null == ois) {
ois = new ArrayList<OrderItem>();
request.getSession().setAttribute("ois", ois);
}
// 遍历当前用户的所有订单项,如果有相同的产品则合并数量
boolean found = false;
for (OrderItem orderItem : ois) {
if (orderItem.getProduct().getId() == oi.getProduct().getId()) {
orderItem.setNum(orderItem.getNum() + oi.getNum());
found = true;
break;
}
}
// 如果当前用户没有相同的产品,则添加新的订单项
if (!found)
ois.add(oi);
// 跳转到订单项列表页面
response.sendRedirect("listOrderItem");
}
}
在servlet包下新建servlet文件"OrderItemListServlet.java",代码如下:
package servlet;
import java.io.IOException;
import java.util.List;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import bean.Product;
import dao.ProductDAO;
@WebServlet("/listOrderItem")
public class OrderItemListServlet extends HttpServlet
{
// 重写service方法
protected void service(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// 转发请求到listOrderItem.jsp页面
request.getRequestDispatcher("listOrderItem.jsp").forward(request, response);
}
}
(4)运行结果:
运行ProductListServlet.java,单击购买
5.应用MVC思想构建订单模块:
(1)M:
在bean包下新建一个class,取名为"Order"
Order.java代码如下:
package bean;
public class Order {
int id;
User user;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
}
(2)V:
在dao包下新建一个class,取名为orderDAO,
orderDAO.java代码如下:
package dao;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import bean.Order;
public class OrderDAO {
public void insert(Order o) {
try {
// 加载MySQL的JDBC驱动程序
Class.forName("com.mysql.jdbc.Driver");
// 获取数据库连接
Connection c = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/cart?characterEncoding=UTF-8",
"root", "admin");
// 定义插入订单的SQL语句
String sql = "insert into order_ values(null,?)";
// 创建PreparedStatement对象
PreparedStatement ps = c.prepareStatement(sql);
// 设置订单所属用户的ID
ps.setInt(1, o.getUser().getId());
// 执行插入操作
ps.execute();
// 获取插入后自动生成的订单ID
ResultSet rs = ps.getGeneratedKeys();
if (rs.next()) {
int id = rs.getInt(1);
o.setId(id);
}
// 关闭PreparedStatement对象
ps.close();
// 关闭数据库连接
c.close();
} catch (ClassNotFoundException e) {
// 处理JDBC驱动程序未找到的异常
e.printStackTrace();
} catch (SQLException e) {
// 处理SQL异常
e.printStackTrace();
}
}
}
继续在dao包下新建一个class,取名为OrderItemDAO,
代码如下:
package dao;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import bean.OrderItem;
import bean.Product;
public class OrderItemDAO {
public static void main(String[] args) {
}
public void insert(OrderItem oi) {
try {
// 加载数据库驱动
Class.forName("com.mysql.jdbc.Driver");
// 建立数据库连接
Connection c = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/cart?characterEncoding=UTF-8",
"root", "admin");
// SQL语句,插入订单项数据
String sql = "insert into orderitem values(null,?,?,?)";
// 创建PreparedStatement对象,用于执行SQL语句
PreparedStatement ps = c.prepareStatement(sql);
// 设置SQL语句参数,分别为商品ID、数量和所属订单ID
ps.setInt(1,oi.getProduct().getId());
ps.setInt(2,oi.getNum());
ps.setInt(3,oi.getOrder().getId());
// 执行SQL语句
ps.execute();
// 关闭PreparedStatement对象
ps.close();
// 关闭数据库连接
c.close();
} catch (ClassNotFoundException e) {
// 处理ClassNotFoundException异常
e.printStackTrace();
} catch (SQLException e) {
// 处理SQLException异常
e.printStackTrace();
}
}
}
(3)C:
在servlet包下新建一个servlet,取名为OrderCreateServlet,代码如下:
package servlet;
import java.io.IOException;
import java.util.List;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import bean.Order;
import bean.OrderItem;
import bean.User;
import dao.OrderDAO;
import dao.OrderItemDAO;
@WebServlet("/createOrder")
public class OrderCreateServlet extends HttpServlet {
protected void service(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// 获取当前用户
User u = (User) request.getSession().getAttribute("user");
if(null==u){
response.sendRedirect("login.jsp"); // 如果用户未登录,则跳转到登录页面
return;
}
Order o = new Order(); // 创建订单对象
o.setUser(u); // 设置订单的用户信息
new OrderDAO().insert(o); // 将订单对象插入到数据库中
List<OrderItem> ois = (List<OrderItem>) request.getSession().getAttribute("ois"); // 获取购物车中的订单项列表
for (OrderItem oi : ois) {
oi.setOrder(o); // 设置订单项所属的订单信息
new OrderItemDAO().insert(oi); // 将订单项插入到数据库中
}
ois.clear(); // 清空购物车中的订单项列表
response.setContentType("text/html; charset=UTF-8");
response.getWriter().println("订单创建成功"); // 输出订单创建成功信息
}
}
6.运行购物车:
(1)运行"ProductListServlet.java",查看商品信息,运行效果如下:
(2)购买4号商品“蜡烛”,修改购买数量为“1”0:
点击购买后,结果如下:
(3)点击生成订单,提示未登录要输入账号密码
输入
tom
123
点击登录,登录并回到商品列表页面,此时提示已经登录,出现“当前用户:tom”的提示文字
(4)将4号产品的数量修改为“0”,再次点击购买
修改为“0”的原因:我们要买的数量为“10”,由于在未登录时,我们向此次会话中已经存入了我们要买10个的数据,成功登录后,当前User也是属于这个会话,买10个的数据默认与这个User链接起来。
订单创建成功:
7.总结:
做Hero的时候已经把各自能遇到的bug都遇到过了,所以这次一出现报错就知道是哪里出了问题,做的是真的顺。