概念
上文中已经实现热销和新品的商品列表功能,本文篇幅中实现关键字搜索商品,将商品加入购物车,以及查看商品的详情信息等功能
关键字搜索实现步骤
在head.jsp头部页面中,鼠标移动至搜索图标会显示隐藏的搜索框进行输入关键信息搜索
当输入关键信息后,点击搜索,将用户输入的内容以表单提交的方法,提交给服务器,因此需要在servlet包中创建GoodsSearchServlet类接收浏览器的关键字信息进行模糊查询,同时也将查询出来的多个商品进行分页展示
package servlet;
import service.GoodsService;
import model.*;
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 java.io.IOException;
import java.net.URLEncoder;
@WebServlet(name = "goods_search",urlPatterns = "/goods_search")
public class GoodsSearchServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
private GoodsService gService = new GoodsService();
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String keyword = request.getParameter("keyword");
int pageNumber = 1;
if(request.getParameter("pageNumber") != null) {
try {
pageNumber=Integer.parseInt(request.getParameter("pageNumber") ) ;
}
catch (Exception e)
{
}
}
if(pageNumber<=0)
{
pageNumber=1;
}
Page p =gService.getSearchGoodsPage(keyword,pageNumber);
if(p.getTotalPage()==0)
{
p.setTotalPage(1);
p.setPageNumber(1);
}
else {
if(pageNumber>=p.getTotalPage()+1)
{
p =gService.getSearchGoodsPage(keyword,pageNumber);
}
}
request.setAttribute("p", p);
request.setAttribute("keyword", URLEncoder.encode(keyword,"utf-8"));
request.getRequestDispatcher("/goods_search.jsp").forward(request, response);
}
}
以上代码中,接收浏览器的参数,并判断用户是否指定了显示的页码,如果没有指定,则默认为第一页,将关键字信息以及页码发送给业务逻辑层执行,因此需要在GoodsService类中定义方法getSearchGoodsPage
//根据关键字搜索商品信息
public Page getSearchGoodsPage(String keyword, int pageNumber) {
Page p = new Page();
p.setPageNumber(pageNumber);
int totalCount = 0;
try {
// totalCount = gDao.getGoodsCount(typeId);
totalCount = gDao.getSearchCount(keyword);
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
p.SetPageSizeAndTotalCount(8, totalCount);
List list=null;
try {
// list = gDao.selectGoods(keyword, pageNo, 8);
list = gDao.selectSearchGoods(keyword,pageNumber,8);
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
p.setList(list);
return p;
}
以上代码中,需要根据关键字查询相关的商品总数量以及根据关键字,页码以及显示数量作为条件查询商品信息两个sql操作,因此需要在GoodsDao中定义对应的两个方法
public int getSearchCount(String keyword) throws SQLException {
QueryRunner r = new QueryRunner(DataSourceUtils.getDataSource());
String sql = "select count(*) from goods where name like ?";
return r.query(sql, new ScalarHandler<Long>(),"%"+keyword+"%").intValue();
}
public List<Goods> selectSearchGoods(String keyword, int pageNumber, int pageSize) throws SQLException{
QueryRunner r = new QueryRunner(DataSourceUtils.getDataSource());
String sql = "select * from goods where name like ? limit ?,?";
return r.query(sql, new BeanListHandler<Goods>(Goods.class),"%"+keyword+"%",(pageNumber-1)*pageSize,pageSize);
}
最后servlet将数据信息发送给goods_search.jsp页面显示
<%@ page language="java" contentType="text/html; charset=utf-8"
pageEncoding="utf-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<!DOCTYPE html>
<html>
<head>
<title>首页</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<link type="text/css" rel="stylesheet" href="css/bootstrap.css">
<link type="text/css" rel="stylesheet" href="css/style.css">
<script type="text/javascript" src="js/jquery.min.js"></script>
<script type="text/javascript" src="js/bootstrap.min.js"></script>
<script type="text/javascript" src="js/simpleCart.min.js"></script>
<script type="text/javascript" src="layer/layer.js"></script>
<script type="text/javascript" src="js/cart.js"></script>
</head>
<body>
<jsp:include page="/header.jsp">
<jsp:param value="8" name="flag"/>
</jsp:include>
<div class="products">
<div class="container">
<h2> 搜索 ‘${param.keyword }’的结果 </h2>
<div class="col-md-12 product-model-sec">
<c:forEach items="${p.list }" var="g">
<div class="product-grid">
<a href="${pageContext.request.contextPath }/goods_detail?id=${g.id}">
<div class="more-product"><span> </span></div>
<div class="product-img b-link-stripe b-animate-go thickbox">
<img src="${pageContext.request.contextPath }${g.cover}" class="img-responsive" alt="${g.name }" width="240" height="240">
<div class="b-wrapper">
<h4 class="b-animate b-from-left b-delay03">
<button>查看详情</button>
</h4>
</div>
</div>
</a>
<div class="product-info simpleCart_shelfItem">
<div class="product-info-cust prt_name">
<h4>${g.name }</h4>
<span class="item_price">¥ ${g.price }</span>
<input type="button" class="item_add items" value="加入购物车" onclick="buy(${g.id})">
<div class="clearfix"> </div>
</div>
</div>
</div>
</c:forEach>
<div class="clearfix"> </div>
</div>
<div>
<jsp:include page="page.jsp">
<jsp:param name="url" value="/goods_search"></jsp:param>
<jsp:param name="param" value="&keyword=${keyword}"></jsp:param>
</jsp:include>
</div>
</div>
</div>
<jsp:include page="/footer.jsp"></jsp:include>
</body>
</html>
其页面效果如下
商品详情实现步骤
查看商品详情的功能在以上各篇文章中都需要涉及,首页中的轮播图商品,热销,新品,商品分类以及商品关键字搜索,甚至后面的购物车功能中都需要查看商品的详情信息,因此这个模块很重要。
那么我们不管从哪个功能上查看的商品,如果需要查看该商品详情信息,那么必须向服务器发送请求并将该商品编号发送给服务器
因此,我们在servlet包中创建GoodsDetailServlet类,用于根据用户传递的商品编号查询商品信息
package servlet;
import model.Goods;
import service.GoodsService;
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 java.io.IOException;
@WebServlet(name = "goods_detail",urlPatterns = "/goods_detail")
public class GoodsDetailServlet extends HttpServlet {
private GoodsService gService = new GoodsService();
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
int id = Integer.parseInt(request.getParameter("id"));
Goods g = gService.getGoodsById(id);
request.setAttribute("g", g);
request.getRequestDispatcher("/goods_detail.jsp").forward(request, response);
}
}
接着servlet将接收的商品编号传递给业务逻辑层执行,需要在GoodsService类中定义执行的方法
//根据商品id查询商品信息
public Goods getGoodsById(int id) {
Goods g=null;
try {
g = gDao.getGoodsById(id);
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return g;
}
接着业务逻辑层将商品编号传递给dao层执行sql操作,并将查询的数据进行封装返回
public Goods getGoodsById(int id) throws SQLException {
QueryRunner r = new QueryRunner(DataSourceUtils.getDataSource());
String sql = "select g.id,g.name,g.cover,g.image1,g.image2,g.price,g.intro,g.stock,t.id typeid,t.name typename from goods g,type t where g.id = ? and g.type_id=t.id";
return r.query(sql, new BeanHandler<Goods>(Goods.class),id);
}
最后servlet将接收返回的数据发送给goods_detail.jsp页面显示
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<!DOCTYPE html>
<html>
<head>
<title>商品详情</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<link type="text/css" rel="stylesheet" href="css/bootstrap.css">
<link type="text/css" rel="stylesheet" href="css/style.css">
<link type="text/css" rel="stylesheet" href="css/flexslider.css">
<script type="text/javascript" src="js/jquery.min.js"></script>
<script type="text/javascript" src="js/jquery.flexslider.js"></script>
<script type="text/javascript" src="js/bootstrap.min.js"></script>
<script type="text/javascript" src="layer/layer.js"></script>
<script type="text/javascript" src="js/cart.js"></script>
<script>
$(function() {
$('.flexslider').flexslider({
animation: "slide",
controlNav: "thumbnails"
});
});
</script>
</head>
<body>
<jsp:include page="/header.jsp"></jsp:include>
<div class="single">
<div class="container">
<div class="single-grids">
<div class="col-md-4 single-grid">
<div class="flexslider">
<ul class="slides">
<li data-thumb="${g.cover}">
<div class="thumb-image"> <img src="${g.cover}" data-imagezoom="true" class="img-responsive"> </div>
</li>
<li data-thumb="${g.image1}">
<div class="thumb-image"> <img src="${g.image1}" data-imagezoom="true" class="img-responsive"> </div>
</li>
<li data-thumb="${g.image2}">
<div class="thumb-image"> <img src="${g.image2}" data-imagezoom="true" class="img-responsive"> </div>
</li>
</ul>
</div>
</div>
<div class="col-md-4 single-grid simpleCart_shelfItem">
<h3>${g.name}</h3>
<div class="tag">
<p>分类 : <a href="goods_list?typeid=${g.type.id}">${g.type.name}</a></p>
</div>
<p>${g.intro}</p>
<div class="galry">
<div class="prices">
<h5 class="item_price">¥ ${g.price}</h5>
</div>
<div class="clearfix"></div>
</div>
<div class="btn_form">
<a href="javascript:;" class="add-cart item_add" onclick="buy(${g.id})">加入购物车</a>
</div>
</div>
<div class="col-md-4 single-grid1">
<!-- <h2>商品分类</h2> -->
<ul>
<li><a href="/goods_list">全部系列</a></li>
<c:forEach items="${typeList}" var="t">
<li><a href="/goods_list?typeid=${t.id}">${t.name}</a></li>
</c:forEach>
</ul>
</div>
<div class="clearfix"> </div>
</div>
</div>
</div>
<jsp:include page="/footer.jsp"></jsp:include>
</body>
</html>
其页面效果如下
所有商品列表页面中,都能点击商品进行该查看商品详情信息页面,这里不再一一讲解。
购物车实现步骤
该项目中会存在“立即购买”和“加入购物车”的字样,这里都表示为将该商品添加至购物车,这里的购物车是临时存储,并不会添加到数据库中进行存储,只有用户注册登录之后,才能将购物车中的数据进行购买,形成购买订单信息。
那么当这些按钮被点击时,需要向服务器发送请求
被点击时,都将会触发按钮的点击事件执行buy方法,并携带当前商品编号,该方法中对加入购物车的库存进行判断,这里采用Ajax的请求方式访问服务器,并且接收服务器返回的数据信息
因此需要在servlet包中创建GoodsBuyServlet类,接收用户的加入购物车的请求
package servlet;
import model.Goods;
import model.Order;
import service.GoodsService;
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 java.io.IOException;
@WebServlet(name = "goods_buy",urlPatterns = "/goods_buy")
public class GoodsBuyServlet extends HttpServlet {
private GoodsService gService = new GoodsService();
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
Order o = null;
if(request.getSession().getAttribute("order") != null) {
o = (Order) request.getSession().getAttribute("order");
}else {
o = new Order();
request.getSession().setAttribute("order", o);
}
int goodsid = Integer.parseInt(request.getParameter("goodsid"));
Goods goods = gService.getGoodsById(goodsid);
if(goods.getStock()>0) {
o.addGoods(goods);
response.getWriter().print("ok");
}else {
response.getWriter().print("fail");
}
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
}
以上代码中,需要封装订单实体类,判断当前加入购物车的商品是否还有库存,如果有则将该商品添加至订单实体类中,并返回用户ok,否则返回用户fail,表示当前商品没有库存。在model包中创建Order实体类
package model;
import utils.PriceUtils;
import java.util.*;
public class Order {
private int id;
private float total;//总价
private int amount;// 商品总数
private int status;//1未付款/2已付款/3已发货/4已完成
private int paytype;//1微信/2支付宝/3货到付款
private String name;
private String phone;
private String address;
private Date datetime;
private User user;
private Map<Integer,OrderItem> itemMap = new HashMap<Integer,OrderItem>();
private List<OrderItem> itemList = new ArrayList<OrderItem>();
public void setUsername(String username) {
user = new User();
user.setUsername(username);
}
public void addGoods(Goods g) {
if(itemMap.containsKey(g.getId())) {
OrderItem item = itemMap.get(g.getId());
item.setAmount(item.getAmount()+1);
}else {
OrderItem item = new OrderItem(g.getPrice(),1,g,this);
itemMap.put(g.getId(), item);
}
amount++;
total = PriceUtils.add(total, g.getPrice());
}
public List<OrderItem> getItemList() {
return itemList;
}
public void setItemList(List<OrderItem> itemList) {
this.itemList = itemList;
}
public void lessen(int goodsid) {
if(itemMap.containsKey(goodsid)) {
OrderItem item = itemMap.get(goodsid);
item.setAmount(item.getAmount()-1);
amount--;
total = PriceUtils.subtract(total, item.getPrice());
if(item.getAmount()<=0) {
itemMap.remove(goodsid);
}
}
}
public void delete(int goodsid)
{
if(itemMap.containsKey(goodsid)) {
OrderItem item = itemMap.get(goodsid);
total = PriceUtils.subtract(total, item.getAmount()*item.getPrice());
amount-=item.getAmount();
itemMap.remove(goodsid);
}
}
public Map<Integer, OrderItem> getItemMap() {
return itemMap;
}
public void setItemMap(Map<Integer, OrderItem> itemMap) {
this.itemMap = itemMap;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public float getTotal() {
return total;
}
public void setTotal(float total) {
this.total = total;
}
public int getAmount() {
return amount;
}
public void setAmount(int amount) {
this.amount = amount;
}
public int getStatus() {
return status;
}
public void setStatus(int status) {
this.status = status;
}
public int getPaytype() {
return paytype;
}
public void setPaytype(int paytype) {
this.paytype = paytype;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public Date getDatetime() {
return datetime;
}
public void setDatetime(Date datetime) {
this.datetime = datetime;
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
public Order() {
super();
}
}
以上Order实体类中,为后期用户提交订单购物商品做准备,需要封装用户信息实体类User,以及多个商品子订单实体类OrderItem,因此需要创建封装该两个实体类
package model;
public class User {
private int id;
private String username;
private String email;
private String password;
private String name;
private String phone;
private String address;
private boolean isadmin=false;
private boolean isvalidate=false;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
@Override
public String toString() {
return "User [id=" + id + ", username=" + username + ", email=" + email + ", password=" + password + ", name="
+ name + ", phone=" + phone + ", address=" + address + ", isadmin=" + isadmin + ", isvalidate="
+ isvalidate + "]";
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public boolean isIsadmin() {
return isadmin;
}
public void setIsadmin(boolean isadmin) {
this.isadmin = isadmin;
}
public boolean isIsvalidate() {
return isvalidate;
}
public void setIsvalidate(boolean isvalidate) {
this.isvalidate = isvalidate;
}
public User(int id, String username, String email, String password, String name, String phone, String address,
boolean isadmin, boolean isvalidate) {
super();
this.id = id;
this.username = username;
this.email = email;
this.password = password;
this.name = name;
this.phone = phone;
this.address = address;
this.isadmin = isadmin;
this.isvalidate = isvalidate;
}
public User( String username, String email, String password, String name, String phone, String address) {
this.username = username;
this.email = email;
this.password = password;
this.name = name;
this.phone = phone;
this.address = address;
this.isadmin = false;
this.isvalidate = false;
}
public User() {
super();
}
}
package model;
public class OrderItem {
private int id;
private float price;
private int amount;
private String goodsName;
private Goods goods;
private Order order;// order_id
public void setName(String name) {
this.goodsName=name;
}
public String getGoodsName() {
return goodsName;
}
public void setGoodsName(String goodsName) {
this.goodsName = goodsName;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public float getPrice() {
return price;
}
public void setPrice(float price) {
this.price = price;
}
public int getAmount() {
return amount;
}
public void setAmount(int amount) {
this.amount = amount;
}
public Goods getGoods() {
return goods;
}
public void setGoods(Goods goods) {
this.goods = goods;
}
public Order getOrder() {
return order;
}
public void setOrder(Order order) {
this.order = order;
}
public OrderItem() {
super();
}
public OrderItem(float price, int amount, Goods goods, Order order) {
super();
this.price = price;
this.amount = amount;
this.goods = goods;
this.order = order;
}
}
其页面效果如下
点击购物车图标,进行查看当前购物车中的商品
在head.jsp头部页面中点击购物车图标,触发超链接,直接跳转至购物车页面,因为购物车的商品信息只是临时存储在Order实体类中,而并没有存储至数据库,因此不需要查询数据库
接着创建该购物车页面
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<!DOCTYPE html>
<html>
<head>
<title>购物车</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<link type="text/css" rel="stylesheet" href="css/bootstrap.css">
<link type="text/css" rel="stylesheet" href="css/style.css">
<script type="text/javascript" src="js/jquery.min.js"></script>
<script type="text/javascript" src="js/bootstrap.min.js"></script>
<script type="text/javascript" src="layer/layer.js"></script>
<script type="text/javascript" src="js/cart.js"></script>
</head>
<body>
<jsp:include page="header.jsp">
<jsp:param name="flag" value="7"></jsp:param>
</jsp:include>
<div class="cart-items">
<div class="container">
<h2>我的购物车</h2>
<c:forEach items="${order.itemMap }" var="item">
<div class="cart-header col-md-6">
<div class="cart-sec simpleCart_shelfItem">
<div class="cart-item cyc">
<a href="/goods_detail?id=${item.key}">
<img src="${pageContext.request.contextPath }${item.value.goods.cover}" class="img-responsive">
</a>
</div>
<div class="cart-item-info">
<h3><a href="/goods_detail?id=${item.key}">${item.value.goods.name}</a></h3>
<h3><span>单价: ¥ ${item.value.price}</span></h3>
<h3><span>数量: ${item.value.amount}</span></h3>
<a class="btn btn-info" href="javascript:buy(${item.key});">增加</a>
<a class="btn btn-warning" href="javascript:lessen(${item.key});">减少</a>
<a class="btn btn-danger" href="javascript:deletes(${item.key});">删除</a>
</div>
<div class="clearfix"></div>
</div>
</div>
</c:forEach>
<div class="cart-header col-md-12">
<hr>
<h3>订单总金额: ¥ ${order.total}</h3>
<a class="btn btn-success btn-lg" style="margin-left:74%" href="/order_submit">提交订单</a>
</div>
</div>
</div>
<jsp:include page="footer.jsp"></jsp:include>
</body>
</html>
其页面效果如下
以上效果图中,点击增加,则会触发JavaScript事件Buy方法,点击减少会触发lessen方法,点击删除会触发deletes方法,其代码如下
该方法会通过Ajax向服务器发送请求,从Order实体类中减少商品数量,因此需要创建GoodsLessenServlet类,其代码如下
package servlet;
import model.Order;
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 java.io.IOException;
@WebServlet(name = "goods_lessen",urlPatterns = "/goods_lessen")
public class GoodsLessenServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
Order o = (Order) request.getSession().getAttribute("order");
int goodsid = Integer.parseInt(request.getParameter("goodsid"));
o.lessen(goodsid);
response.getWriter().print("ok");
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
}
该方法会通过Ajax向服务器发送请求,从Order实体类中删除该商品,因此需要创建GoodsDeleteServlet类,其代码如下
package servlet;
import model.Order;
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 java.io.IOException;
@WebServlet(name = "goods_delete",urlPatterns = "/goods_delete")
public class GoodsDeleteServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
Order o = (Order) request.getSession().getAttribute("order");
int goodsid = Integer.parseInt(request.getParameter("goodsid"));
o.delete(goodsid);
response.getWriter().print("ok");
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
}