二、商品管理的准备工作
商品表:
CREATE TABLE `product` (
`pid` INT(10) PRIMARY KEY AUTO_INCREMENT,#主键自增
`pname` VARCHAR(50) NOT NULL,#商品名字
`color` VARCHAR(50),#颜色
`price` DOUBLE NOT NULL,#价格
`description` VARCHAR(500),#描述
`pic` VARCHAR(200),#商品图片
`state` INT(5) DEFAULT '0', # 0:正常 1:热门 2:为你推荐 3:新品 4:小米明星单品
`version` VARCHAR(50),#型号
`product_date` DATETIME,#生产日期
cid INT(10) # 所属的分类
) ;
包结构搭建:
pojo、dao、service、servlet(配置web.xml!!!!!!!!!!!!!!!!!!!!)
三、商品分页查询
后台代码略:
显示分类名称功能:
分析图:
代码实现:
service中:
private CategoryDao cd = new CategoryDao();
public PageBean<Product> selectPlist(PageBean<Product> pb) {
List<Product> plist = pd.selectPlist(pb);
//遍历plist获取cid的值
for(Product pro:plist) {
//获取cid的值
int cid = pro.getCid();
//根据cid查询Category对象
Category category = cd.selectByCid(cid+"");
//将category对象封装到Product里
pro.setCategory(category);
}
pb.setResult(plist);
//查询总记录数
int totalCount = pd.selecCount();
pb.setTotalCount(totalCount);
return pb;
}
product_list.jsp:
显示分类名称:
${p.category.cname}
四、添加商品
4.1 跳转到添加商品页面
问题:直接跳还是要走服务器?
标准:看跳转过去的页面要不要回显数据?
需求:走服务器查出所有的分类信息回显到下拉列表中?
代码实现:
product_list.jsp:
<li onclick="toAdd()" style="cursor: pointer;" id="addProduct" ><span><img src="${pageContext.request.contextPath}/admin/images/t01.png" /></span>添加商品</li>
<script type="text/javascript">
//跳转到添加商品页面
function toAdd(){
location.href = "/dami/product?method=toAdd";
}
</script>
ProductServlet:
//跳转到添加商品页面
protected void toAdd(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//1、获取数据
//2、调用业务
CategoryService cs = new CategoryService();
//查询所有分类信息
List<Category> clist = cs.findAll();
//3、结果的展示
request.setAttribute("clist", clist);
request.getRequestDispatcher("/admin/product_add.jsp").forward(request, response);
}
CategoryService:
public List<Category> findAll() {
// TODO Auto-generated method stub
return cd.findAll();
}
CategoryDao:
public List<Category> findAll() {
String sql = "select * from category";
try {
return qr.query(sql, new BeanListHandler<Category>(Category.class));
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return null;
}
}
product_add.jsp
<!-- 商品分类信息 -->
<li>
<label>商品分类</label>
<select name="cid" class="dfinput">
<option value="0">===请选择===</option>
<c:if test="${not empty clist}">
<c:forEach items="${clist}" var="c">
<option value="${c.cid}">${c.cname}</option>
</c:forEach>
</c:if>
</select>
</li>
4.2 添加商品
因为涉及到了图片的上传,注意浏览器、服务的操作步骤
代码略
五、删除单个商品
product_list.jsp
<a href="javascript:void(0)" onclick="deleteByPid(${p.pid})">删除</a>
//根据pid删除商品
function deleteByPid(pid){
if(confirm("是否确认要删除该商品呢???")){
location.href = "/dami/product?method=deleteByPid&pid="+pid;
}
}
Servlet:
//根据pid删除商品
protected void deleteByPid(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//1、获取数据
String pid = request.getParameter("pid");
//2、调用业务
ProductService ps = new ProductService();
ps.deleteByPid(pid);
//3、结果的展示
response.sendRedirect("/dami/product?method=selectPlist&pageNumber=1");
}
Service:
public void deleteByPid(String pid) {
pd.deleteByPid(pid);
}
Dao:
public void deleteByPid(String pid) {
String sql = "DELETE FROM product WHERE pid = ?";
try {
qr.update(sql, pid);
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
六、首页的头部
<a class="mix" href="/xiaomi/login.jsp">登录</a>
访问项目的路径:项目名目前是写死的状态 存在的问题:一旦项目名改变了,那么页面路径中所有的名字都要更改
解决:动态获取项目名
Servlet中
String path = request.getContextPath();
Jsp
${pageContext.request.contextPath}
头部信息展示问题:
分析图:
代码实现:
login.jsp 改一处代码:
else if(msg == "1"){
//跳转到首页
location.href= "${pageContext.request.contextPath}/index.jsp";
}
UserServelt中:
if((phoneNumber + code).equals(sessionCode)) {
//验证码正确
msg = "1";
//登录成功
request.getSession().setAttribute("qianUser", user);
}
index.jsp的头部:
<div class="right">
<c:if test="${empty qianUser}">
<a class="mix" href="${pageContext.request.contextPath}/login.jsp">登录</a>
<a href="${pageContext.request.contextPath}/register.jsp">注册</a>
</c:if>
<c:if test="${not empty qianUser}">
<span style="color:red">欢迎您:${qianUser.name}</span>
</c:if>
<a class="max" href="">消息通知</a>
<a href="trolley.html"><img src="img/cart.jpg" alt=""></a>
</div>
七、首页动态展示分类名称
目前的问题:
登录成功后直接跳转到了index.jsp ,导致在首页无法动态显示分类名称
所以,登录成功后需要先跳转到服务器查询分类的数据
代码实现:
login.jsp
location.href= "${pageContext.request.contextPath}/product?method=toIndex";
ProductServet:
//跳转到首页
protected void toIndex(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//1、获取数据(暂无)
//2、调用业务
//查询所有分类
CategoryService cs = new CategoryService();
List<Category> clist = cs.findAll();
request.setAttribute("clist", clist);
//3、结果的展示
request.getRequestDispatcher("/index.jsp").forward(request, response);
}
因为需要根据order_number的值进行排序显示,所以需要在原来的sql加上order by 进行排序
public List<Category> findAll() {
String sql = "select * from category order by order_number asc";
try {
return qr.query(sql, new BeanListHandler<Category>(Category.class));
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return null;
}
}
问题:
目前是只有登录成功才会执行查询所有分类并动态展示在首页,直接访问index.jsp数据显示不出来
解决思路:
在用户访问index.jsp之前,就将数据查出来存到域对象中(服务器启动时)
使用的技术:监听器
监听器:监听到某种行为去做一些事情
某种行为:服务器启动
做事情:执行contextInitialized()
解决的代码:
@WebListener
public class MyListener implements ServletContextListener {
public void contextDestroyed(ServletContextEvent arg0) {
// TODO Auto-generated method stub
}
//服务器启动时执行该方法
public void contextInitialized(ServletContextEvent arg0) {
System.out.println("服务器启动啦");
ServletContext context = arg0.getServletContext();
//1、获取数据(暂无)
//2、调用业务
//查询所有分类
CategoryService cs = new CategoryService();
List<Category> clist = cs.findAll();
context.setAttribute("clist", clist);
}
}
login.jsp
location.href= "${pageContext.request.contextPath}/index.jsp";
八、首页动态展示前五条小米明星单品
分析:
- 什么时候查
和查询分类数据一样,都是在服务器启动时查 - 执行的sql
SELECT * FROM product WHERE state = 4 LIMIT 0,5;
代码实现:
在监听器的方法中加:
//查询前五条小米明星单品
ProductService ps = new ProductService();
List<Product> plist = ps.findAllProduct();
context.setAttribute("starList", plist);
Service:
public List<Product> findAllProduct() {
// TODO Auto-generated method stub
return pd.findAllProduct();
}
Dao:
public List<Product> findAllProduct() {
String sql = "SELECT * FROM product WHERE state = 4 LIMIT 0,5";
try {
return qr.query(sql, new BeanListHandler<Product>(Product.class));
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return null;
}
}
index.jsp进行数据的展示:
<c:if test="${not empty starList}">
<c:forEach items="${starList}" var="star">
<div style="background-color: #fff;width: 234px;height:320px;float: left;margin-left: 11px; ">
<a href="${pageContext.request.contextPath}/product?method=toProductDetail&pid=${star.pid}" target="_blank">
<img class="time_min" style="width:234px;height: 234px;" src="/xm_upload/${star.pic}" alt="">
</a>
<div style="clear: both;"></div>
<div style="width: 234px;height: 85px;">
<div style="width: 234px;height: 20px;line-height: 20px;text-align: center;font-size: 14px;font-family: Arial;
color:red">
${star.pname}
</div>
<div style="width: 234px;height: 30px;line-height: 30px;text-align: center;color: #ff6700;font-size: 14px;font-family: Arial">
<span style="color: #000">${star.price} 起始价 </span>
</div>
</div>
</div>
</c:forEach>
</c:if>
九、点击商品跳转到商品详情页面
思路:
点击商品---跳转到服务器--- 根据商品的id查询出该商品---存到域对象中---跳转到product_detail.js中取出数据展示
代码实现:
index.jsp
<a href="${pageContext.request.contextPath}/product?method=toProductDetail&pid=${star.pid}" target="_blank">
<img class="time_min" style="width:234px;height: 234px;" src="/xm_upload/${star.pic}" alt="">
</a>
Servlet:
//跳转到商品详情页面
protected void toProductDetail(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//1、获取数据;
String pid = request.getParameter("pid");
//2、调用业务
ProductService ps = new ProductService();
Product p = ps.findByPid(pid);
//3、结果的展示t.s
request.setAttribute("product", p);
request.getRequestDispatcher("/product_detail.jsp").forward(request, response);
}
service:
public Product findByPid(String pid) {
// TODO Auto-generated method stub
return pd.findByPid(pid);
}
Dao:
public Product findByPid(String pid) {
String sql = "SELECT * FROM product WHERE pid = ?";
try {
return qr.query(sql, new BeanHandler<Product>(Product.class),pid);
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return null;
}
}
product_detail.jsp 显示数据:
<h3>商品名称:${product.pname}</h3>
<p class="plus5_no3_right_p2">
<span class="plus5_no3_right_span2">「${product.description}」</span>
</p>
十、购物车逻辑分析
封装JavaBean的购物车分析图:
封装JavaBean对象:
CartItem:
//购物项
public class CartItem implements Serializable{
//商品对象
private Product product;
//购买数量
private int count;
//小计
private double subTotal;
//计算小计
public double getSubTotal() {
return subTotal = (getProduct().getPrice()) * getCount();
}
...
}
Cart:
public class Cart implements Serializable{
/* 如何选用集合 :
*
* 需求:
* 1、要求是有序的
* 2、从购物车中移除商品方便
*
* 三大集合:
* List:有序可以重复
* Set:无序不可以重复
* Map:key-value remove(key)
*
* */
//key: pid value:CartItem
private LinkedHashMap<String, CartItem> cartMap = new LinkedHashMap<String, CartItem>();
//总价格
private double total;
//计算总价格
public double getTotal() {
total = 0.0;
Set<String> keys = cartMap.keySet();
for(String key:keys) {
CartItem cartItem = cartMap.get(key);
total += cartItem.getSubTotal();
}
return total;
}
}