任务1:点击商品类别名称后分页显示该类别下的商品
1)给商品类别名称添加超链接,请求Servlet的queryByCatelog()
<a href="${pageContext.request.
contextPath}/goods.action?method=queryByCatelog&catelogId=${c.catelog_id}">
<span style="font-size:12px">${c.catelog_name }</span>
</a>
2).在GoodsDao中加入2个方法,分别查询数据集合和总记录数,实现类代码
@Override
public List<Goods> queryDataByCatelogId(PageBean<Goods> pb, int
catelogId) {
// TODO Auto-generated method stub
String sql = "select goods_id,goods_name,goods_pic,market_price
from t_goods where"
+ " catelog_id=? limit ?,?";
List<Goods> list = this.getList(Goods.class, sql,catelogId,
(pb.getCurrentPage() - 1) * pb.getPageSize(), pb.getPageSize());
return list;
}
@Override
public int queryTotalCount(int catelogId) {
// TODO Auto-generated method stub
String sql="select count(goods_id) from t_goods where catelog_id=?";
int total = this.getTotal(sql,catelogId);
return total;
}
3)在GoodsService中加入getPageBean方法,实现类的代码
@Override
public void getPageBean(PageBean<Goods> pb, int catelogId) {
// TODO Auto-generated method stub
// 调用Dao的两个方法
// 获取数据集合
List<Goods> list = goodsDao.queryDataByCatelogId(pb, catelogId);
// 获取总记录数
int totalCount = goodsDao.queryTotalCount(catelogId);
// 封装pageBean的其它属性
pb.setData(list);
pb.setTotalCount(totalCount);
}
4)在GoodsServlet中加入queryByCatelog()
// 根据商品分类来查询
public void queryByCatelog(HttpServletRequest request,
HttpServletResponse response) throws ServletException,
IOException {
// 获取分类编号参数值
int catelogId = Integer.parseInt(request.getParameter("catelogId"));
// 获取请求的页号,即要查询第几页数据,假设请求参数名currentPage
String pageStr = request.getParameter("currentPage");
// 保存请求的页号
int currentPage = 1;
if (pageStr != null) {
currentPage = Integer.parseInt(pageStr);
}
// 每页条数
int pageSize = 2;
// 调用GoodsService,传入catelogId和PageBean,得到pageBean对象
PageBean<Goods> pb=new PageBean<>();
pb.setCurrentPage(currentPage);
pb.setPageSize(pageSize);
GoodsService service=new GoodsServiceImpl();
service.getPageBean(pb, catelogId);
// 把PageBean存到request中
request.setAttribute("pb", pb);
//把分类编号存到作用域中
request.setAttribute("catelogId", catelogId);
//转发到列表页面qiantai/goods/goodsByCatelog.jsp
request.getRequestDispatcher("qiantai/goods/goodsByCatelog.jsp")
.forward(request,response);
}
5)在goodsByCatelog.jsp上使用jstl+EL展示数据,代码略
任务2:商品搜索
就是根据商品名称关键字进行模糊查询,结果需要分页显示
1)改造GoodsDao中查询商品数据集合方法和查询总记录数方法,多传一个关键字进去
// 根据页号,每页记录数,名称关键字,获取指定的页号的数据集合
List<Goods> queryData(PageBean<Goods> pb,String keyword);
// 查询总记录数
int queryTotalCount(String keyword);
实现类中的方法代码
@Override
public List<Goods> queryData(PageBean<Goods> pb,String keyword) {
// TODO Auto-generated method stub
String sql = "select goods_id,goods_name,goods_pic,market_price
from t_goods";
//如果商品名关键字不为空,就要根据关键字进行模糊查询
if(!keyword.equals("")){
sql+=" where goods_name like '%"+keyword+"%'";
}
sql+=" limit ?,?";
List<Goods> list = this.getList(Goods.class, sql,
(pb.getCurrentPage() - 1) * pb.getPageSize(), pb.getPageSize());
return list;
}
@Override
public int queryTotalCount(String keyword) {
// TODO Auto-generated method stub
String sql = "select count(goods_id) from t_goods";
//如果商品名关键字不为空,就要根据关键字进行模糊查询
if(!keyword.equals("")){
sql+=" where goods_name like '%"+keyword+"%'";
}
int total = this.getTotal(sql);
return total;
}
2)改造GoodsService的getPageBean(),多传入keyword参数
@Override
public void getPageBean(PageBean<Goods> pb,String keyword) {
// TODO Auto-generated method stub
// 调用Dao的两个方法
// 获取数据集合
List<Goods> list = goodsDao.queryData(pb,keyword);
// 获取总记录数
int totalCount = goodsDao.queryTotalCount(keyword);
// 封装pageBean的其它属性
pb.setData(list);
pb.setTotalCount(totalCount);
}
3)修改列表页面list.jsp上的超链接的请求路径
<!-- 当前页号>1时,给用户提供上一页超链接;否则直接显示“上一页” -->
<c:choose>
<c:when test="${pb.currentPage gt 1}">
<a
href="javascript:void(0)" onclick="changePageNum(${pb.currentPage-1})">上一页</a>
</c:when>
<c:otherwise>
上一页
</c:otherwise>
</c:choose>
<!-- 生成一组页号的超链接 -->
<c:forEach var="sn" begin="1" end="${pb.totalPage }">
<a
href="javascript:void(0)" onclick="changePageNum(${sn})">${sn }</a>
</c:forEach>
<!-- 当前页号<总页数时,给用户提供下一页超链接;否则直接显示“下一页” -->
<c:choose>
<c:when test="${pb.currentPage lt pb.totalPage}">
<a
href="javascript:void(0)" onclick="changePageNum(${pb.currentPage+1})">下一页</a>
</c:when>
<c:otherwise>
下一页
</c:otherwise>
</c:choose>
在超链接的js单击事件的响应函数中去提交表单
// 点击超链接的单击事件调用的函数,参数是要查询的页号
function changePageNum(pageNum){
//给存储页号的隐藏域重新赋值
$("#currentPage").val(pageNum);
//提交表单
$('#searchForm').submit();
}
修改incTop.jsp页面,在表单里加入保存页号的隐藏域,回显关键字
<form id="searchForm"
action="${pageContext.request.contextPath}/goods.action?method=queryByPage"
method="post">
<div class="topsearch">
<div class="title"></div>
<div id="page_search_left">
<!-- 使用隐藏域将要查询的页号封装起来 -->
<input type="hidden" name="currentPage" id="currentPage" value="1">
<input class="inputText" id="goodsName" size="16"
onkeypress="if(event.keyCode==13){searchFormSubmit();return false;}"
name="goodsName" type="text" value="${keyword}" />
</div>
<div id="page_search_btn">
<input type="submit" value="商品搜索"> </b>
</div>
<div id="page_search_right"></div>
<div style="clear: both"></div>
</div>
</form>
4)改造GoodsServlet,获取名称关键字,要将关键字存到request域中(为了在列表页面上回显)
// 处理分页查询商品的请求
public void queryByPage(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
// 获取请求的页号,即要查询第几页数据,假设请求参数名currentPage
String pageStr = request.getParameter("currentPage");
// 保存请求的页号
int currentPage = 1;
if (pageStr != null) {
currentPage = Integer.parseInt(pageStr);
}
// 每页条数
int pageSize = 5;
//获取前台页面传过来的商品名关键字
String keyword=request.getParameter("goodsName");
if(keyword==null){
keyword="";
}
// 封装一个pageBean对象,它只有2个数据currentPage和pageSize
PageBean<Goods> pb = new PageBean<>();
pb.setCurrentPage(currentPage);
pb.setPageSize(pageSize);
// 把每页条数和页号传给Service,获取PageBean对象
GoodsService service = new GoodsServiceImpl();
service.getPageBean(pb,keyword);
// 把PageBean存到request中
request.setAttribute("pb", pb);
//把关键字存起来,到列表页面上回显
request.setAttribute("keyword", keyword);
// 转发到列表页面qiantai/goods/list.jsp
request.getRequestDispatcher("qiantai/goods/list.jsp").forward(request,
response);
}
任务3:查看商品详情
1) 修改商品列表页面list.jsp的”购买”图片的超链接
<a href="${pageContext.request.contextPath}/goods.action?method=queryDetail&goodsId=${gd.goods_id}">
<img alt="" src="${pageContext.request.contextPath}/images/icon_buy.gif"
border=0 /></a>
同理,qiantai/index.jsp上的5个商品的图片,名称上也要加上查看详情的超链接
<a
href="${pageContext.request.contextPath}/goods.action?method=queryDetail&goodsId=${gd.goods_id}">
<!-- 商品图片 --> <img width="105" height="110"
src="${pageContext.request.contextPath}/${gd.goods_pic}" />
</a>
<a
href="${pageContext.request.contextPath}/goods.action?method=queryDetail&goodsId=${gd.goods_id}">
<font size="2"> ${gd.goods_name } </font>
</a>
goodsByCatelog.jsp页面上也加上查看详情的超链接
<a href="${pageContext.request.contextPath}/goods.action?
method=queryDetail&goodsId=${gd.goods_id}"> <img
src="${pageContext.request.contextPath}/${gd.goods_pic}" width="60"
height="60" border="0"/> </a>
<a href="${pageContext.request.contextPath}/goods.action?
method=queryDetail&goodsId=${gd.goods_id}"><img alt=""
src="${pageContext.request.contextPath}/images/icon_buy.gif" border=0/></a>
2)在GoodsDao中加入根据编号查询一个商品对象的方法
public Goods queryById(int goods_id) {
// TODO Auto-generated method stub
String sql = "select goods_id,goods_name,goods_miaoshu,market_price,mall_price,
goods_pic,goods_address,enter_date from t_goods where goods_id=?";
Goods goods = this.getBean(Goods.class, sql, goods_id);
return goods;
}
3)在GoodsService中添加获取商品对象的方法
@Override
public Goods getGoods(int goods_id) {
// TODO Auto-generated method stub
Goods goods = goodsDao.queryById(goods_id);
return goods;
}
4)在GoodsServlet中添加查看商品详情的方法
//根据商品id查看详情
public void queryDetail(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
//获取商品编号
int goods_id=Integer.parseInt(request.getParameter("goodsId"));
//调用service的方法,把商品编号传入
GoodsService service=new GoodsServiceImpl();
Goods goods = service.getGoods(goods_id);
//将商品对象存到request域中
request.setAttribute("gd", goods);
//转发到goodsDetail.jsp页面
request.getRequestDispatcher("qiantai/goods/goodsDetail.jsp")
.forward(request,response);
}
5)在 goodsDetail.jsp页面上用EL展示数据
任务4:在商品详情页面点购买时做登录判断
在页面的购买超链接上添加单击事件,在js函数中判断如果没登录,就要去登录
<script>
function buy1()
{
// 判断用户是否登录了,如果没有登录,提示他去登录
<c:if test="${empty user}">
alert("请去右边的登录板块去登录,登录后才能买宝贝!");
return;
</c:if>
//用户已登录,user不为空,允许表单提交
$('#buyForm').submit();
}
</script>
任务5:前台用户登录
1)修改登录页面userlogin.jsp上表单的请求路径
<form action="${pageContext.request.contextPath}/userLogin.action" "
name="userLogin" id="userLogin" method="post">
2)创建UserDao,添加根据用户名和密码查询的方法,实现类代码
public class UserDaoImpl extends BaseDao<User> implements Userdao {
@Override
public User queryByNameAndPwd(String username, String userpwd) {
// TODO Auto-generated method stub
String sql="select * from t_user where user_name=? and user_pwd=?";
User user = this.getBean(User.class, sql, username,userpwd);
return user;
}
}
3)创建UserService,添加登录的业务方法login
public class UserServiceImpl implements UserService {
private Userdao userDao = new UserDaoImpl();
@Override
public User login(String username, String userpwd) {
// TODO Auto-generated method stub
User user = userDao.queryByNameAndPwd(username, userpwd);
return user;
}
}
4)创建处理登录请求的UserLoginServlet
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
request.setCharacterEncoding("UTF-8");
// 获取用户名和密码
String userName = request.getParameter("userName");
String userPw = request.getParameter("userPw");
// 调用UserService的登录方法,传入用户名和密码,返回一个对象
UserService service = new UserServiceImpl();
User user = service.login(userName, userPw);
// 做判断,如果返回的用户对象不为空,说明登录成功,需要把用户对象保存在
session中,key为user
if (user != null) {
// 登录成功
HttpSession session = request.getSession();
session.setAttribute("user", user);
// 跳转到欢迎页
response.sendRedirect(request.getContextPath() + "/index.jsp");
} else {
// 登录失败,把错误信息存到request域中,再跳转到欢迎页
request.setAttribute("errorMsg", "用户名或密码错误");
request.getRequestDispatcher("goods.action?method=queryFive")
.forward(request, response);
}
}
5).在登录页面userlogin.jsp上加入是否登录成功的判断,并回显错误信息和欢迎信息
<c:choose>
<c:when test="${empty user }">
<form action="${pageContext.request.contextPath}/userLogin.action" name="userLogin" id="userLogin" method="post">
<table cellspacing="0" cellpadding="0" width="98%" align="center" border="0">
<tr>
<td align="center" colspan="2" height="10"></td>
</tr>
<tr>
<td align="right" width="30%" height="30" style="font-size: 11px;">用户名:</td>
<td align="left" width="69%"><input class="input" id="userName" title="用户名不能为空" size="16" name="userName" type="text" /></td>
</tr>
<tr>
<td align="right" height="30" style="font-size: 11px;">密 码:</td>
<td align="left"><input class="input" title="密码不能为空" type="password" size="16" id="userPw" name="userPw"/></td>
</tr>
<tr>
<td align="center" colspan="2" height="10"><font color="red"><s:property value="#request.error"/></font></td>
</tr>
<tr>
<td align="center" colspan="2" height="30">
<input type="button" value="登 录" onclick="login()" style="border:#ccc 1px solid; background-color:#FFFFFF; font-size:12px; padding-top:3px;" />
<input type="button" value="注 册" onclick="reg()" style="border:#ccc 1px solid; background-color:#FFFFFF; font-size:12px; padding-top:3px;" />
<!-- 回显错误信息 -->
<span style="color:red;font-size:13px">${errorMsg }</span>
</td>
</tr>
</table>
</form>
</c:when>
<c:otherwise>
欢迎您:${user.user_name }
<a href="javascript:void(0)" onclick="logOut()">安全退出</a>
<br/><br/><br/>
</c:otherwise>
</c:choose>
任务6:安全退出
1)把登录页面上的安全退出超链接的路径修改一下
<a href="javascript:void(0)" onclick="logOut()">安全退出</a>
2)在js函数logOut中请求Servlet
//安全退出
function logOut() {
//弹出一个是否确认退出的对话框
var flag = confirm("是否真的要退出");
if (flag) {
//请求后台logout.action,实现安全退出
location.href = "${pageContext.request.contextPath}/logout.action";
}
}
3)创建UserLogOutServlet,实现安全退出功能
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
HttpSession session = request.getSession();
//销毁session
session.invalidate();
//跳转到首页
response.sendRedirect("goods.action?method=queryFive");
}
任务7:将商品加入购物车
准备工作:
1)封装一个购物项类
/**
* 购物项类,封装购物车中一款商品的购买记录
*
* @author lujun
*
*/
public class CartItem {
// 购物项中的商品
private Goods goods;
// 购买数量
private int quantity;
// 购买的金额
private int price;
public Goods getGoods() {
return goods;
}
public void setGoods(Goods goods) {
this.goods = goods;
}
public int getQuantity() {
return quantity;
}
public void setQuantity(int quantity) {
this.quantity = quantity;
}
//金额:商品价格*购买数量
public int getPrice() {
return this.goods.getMall_price()*this.quantity;
}
}
2)封装一个购物车类
public class Cart {
// 购物项的集合,存储所有购物项,key:购物项中的商品的编号,value:购物项对象
private Map<Integer, CartItem> cartMap = new HashMap<Integer, CartItem>();
// 返回购物项的集合
public Map<Integer, CartItem> getCartMap(){
return cartMap;
}
// 添加商品项到购物车中
public void addToCart(Integer goodsId, CartItem item){
// 如果是第一次购买,购物车中没有该商品的购物项的
boolean flag=cartMap.containsKey(goodsId);
if(flag){
// 1).不是第一次买,修改该商品的购物项的数量,先获取购物项
CartItem cartItem = cartMap.get(goodsId);
// 2).修改购物项的购买数量
cartItem.setQuantity(cartItem.getQuantity()
+ item.getQuantity());
}else{
// 第1次买,将商品编号和购物项添加到Map集合中
cartMap.put(goodsId, item);
}
}
// 修改购物项的数量
public void modifyQuantity(Integer goodsId, int quantity) {
CartItem cartItem = cartMap.get(goodsId);
cartItem.setQuantity(quantity);
}
// 删除购物项
public void removeItem(Integer goodsId) {
cartMap.remove(goodsId);
}
// 清空购物项
public void clearItem() {
cartMap.clear();
}
// 获取购物项的总金额
public int getTotalPrice() {
// 保存总金额
int totalPrice = 0;
// 获取所有的CartItem
Collection<CartItem> values = cartMap.values();
for (CartItem item : values) {
totalPrice += item.getPrice();
}
return totalPrice;
}
}
将商品添加到购物车中的具体步骤
1)修改商品详情页面的表单,加入3个隐藏域,分别保存购物项需要的商品编号,名称,价格
<!-- 隐藏域,保存当前商品的编号,传到购物车页面上 -->
<input type="hidden" name="goodsId" value="${gd.goods_id }"/>
<!--隐藏域,保存商品名称 -->
<input type="hidden" name="goodsName" value="${gd.goods_name }"/>
<!--隐藏域,保存商品价格 -->
<input type="hidden" name="goodsPrice" value="${gd.mall_price }"/>
2)修改商品详情页面的表单的请求路径
<form action="${pageContext.request.contextPath}/goods.action?
method=addToCart" method="post" name="buy" id="buyForm">
3)在GoodsServlet中处理添加到购物车的方法addToCart
// 添加商品到购物车中
public void addToCart(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
// 获取参数
// 编号
int goodsId = Integer.parseInt(request.getParameter("goodsId"));
// 名称
String goodsName = request.getParameter("goodsName");
// 价格
int mallPrice = Integer.parseInt(request.getParameter("goodsPrice"));
// 购买数量
int quantity = Integer.parseInt(request.getParameter("quantity"));
// 封装商品对象
Goods goods = new Goods();
goods.setGoods_id(goodsId);
goods.setGoods_name(goodsName);
goods.setMall_price(mallPrice);
// 创建购物项对象
CartItem item = new CartItem();
item.setGoods(goods);
item.setQuantity(quantity);
// 购物车
HttpSession session = request.getSession();
// 从session中获取购物车对象,如果为空,说明是第一次添加商品到购物车
Cart cart = (Cart) session.getAttribute("cart");
if (cart == null) {
// 给当前的用户分配一个购物车
cart = new Cart();
// 将购物车保存在session中
session.setAttribute("cart", cart);
// 创建Cookie
Cookie cookie = new Cookie("JSESSIONID", session.getId());
// 设置有效期,为用户保存3天购物车
cookie.setMaxAge(3 * 24 * 60 * 60);
// 设置有效路径
cookie.setPath(request.getContextPath());
// 将Cookie发送给浏览器
response.addCookie(cookie);
}
// 添加购物项到购物车
cart.addToCart(goodsId, item);
// 跳转到myCart.jsp
response.sendRedirect("qiantai/myCart/myCart.jsp");
}
任务8:查看我的购物车
在myCart.jsp显示购物车中的购物项数据
<c:forEach var="entry" items="${cart.cartMap }">
<tr align='center' bgcolor="#FFFFFF" height="22">
<td>${entry.value.goods.goods_name }</td>
<td>${entry.value.goods.mall_price}<br /></td>
<td><input type="text" class="textBox"
value="${entry.value.quantity }" size="4" /></td>
<td>¥${entry.value.price }</td>
<td><input type="image"
onclick="deleteCartItem(${entry.key})"
src="${pageContext.request.contextPath}/images/delete_01.gif"
border="0" /></td>
</tr>
</c:forEach>
<tr>
<td colspan="6" class="Order_Total"><img hspace="5"
src="${pageContext.request.contextPath}/images/me03.gif" />
总金额:¥<span id="totalMoney">${cart.totalPrice }</span>
<%-- <img id="indicator1" src="${pageContext.request.contextPath}/images/loading.gif" style="display:none"/> --%>
</td>
</tr>
任务9:修改购买数量
1)给myCart.jsp页面上的数量的文本框添加onchange事件,调用Servlet改变数量
<input type="text" class="textBox"
onchange="modifyNum(${entry.key},this.value)"
value="${entry.value.quantity }" size="4" />
函数
<script>
//函数modifyNum(),根据商品编号修改数量
function modifyNum(goodsId,num){
//请求Servlet去修改数量
location.href="${pageContext.request.contextPath}/goods.action?
method=updateQuantity&goodsId="+goodsId+"&quantity="+num;
}
</script>
2)在GoodsServlet中添加一个修改数量的方法
//根据编号来修改购物项的数量
public void updateQuantity(HttpServletRequest request,
HttpServletResponse response) throws ServletException,
IOException {
//获取商品编号
int goodsId=Integer.parseInt(request.getParameter("goodsId"));
//获取数量
int quantity=Integer.parseInt(request.getParameter("quantity"));
//获取购物车
HttpSession session = request.getSession();
Cart cart = (Cart) session.getAttribute("cart");
//调用修改购物项的数量的方法
cart.modifyQuantity(goodsId, quantity);
// 跳转到myCart.jsp
response.sendRedirect("qiantai/myCart/myCart.jsp");
}
任务10:删除购物项
1)在myCart.jsp页面给删除图片加一个单击事件,调用函数deleteCartItem
<input type="image" onclick="deleteCartItem(${entry.key})"
src="${pageContext.request.contextPath}/images/delete_01.gif"
border="0" />
函数:
//函数deleteCartItem(),根据编号删除购物项
function deleteCartItem(goodsId){
var flag= confirm("是否要删除该购物项?");
if(flag){
//请求Servlet去删除购物项
location.href="${pageContext.request.contextPath}/goods.action?
method=deleteItem&goodsId="+goodsId;
}
}
2)GoodsServlet中加入删除购物项的方法
// 根据编号来删除购物项
public void deleteItem(HttpServletRequest request,
HttpServletResponse response) throws ServletException,
IOException {
// 获取商品编号
int goodsId = Integer.parseInt(request.getParameter("goodsId"));
// 获取购物车
HttpSession session = request.getSession();
Cart cart = (Cart) session.getAttribute("cart");
cart.removeItem(goodsId);
// 跳转到myCart.jsp
response.sendRedirect("qiantai/myCart/myCart.jsp");
}
任务11:清空购物车
1)在myCart.jsp页面给清空购物车图片加一个单击事件,调用函数clearCart
<a href="javascript:void(0)" onclick="clearCart()"><img border="0
src="${pageContext.request.contextPath}/images/Car_icon_01.gif" /></a>
函数
//清空购物车
function clearCart(){
var flag= confirm("是否要清空购物车?");
if(flag){
//请求Servlet去删除购物项
location.href="${pageContext.request.contextPath}/goods.action?
method=clearItem";
}
}
</script>
2)GoodsServlet中加入清空购物车的方法
// 清空所有购物项(清空购物车)
public void clearItem(HttpServletRequest request,
HttpServletResponse response) throws ServletException,
IOException {
// 获取购物车
HttpSession session = request.getSession();
Cart cart = (Cart) session.getAttribute("cart");
cart.clearItem();
// 跳转到myCart.jsp
response.sendRedirect("qiantai/myCart/myCart.jsp");
}
补充:解决重启浏览器后,购物车中数据消失的问题
解决办法:在添加商品到购物车的方法addToCart中加入保存Cookie的代码,把名为JSESSIONID的Cookie变为持久级别的
if (cart == null) {
// 给当前的用户分配一个购物车
cart = new Cart();
// 将购物车保存在session中
session.setAttribute("cart", cart);
// 创建Cookie
Cookie cookie = new Cookie("JSESSIONID", session.getId());
// 设置有效期,为用户保存3天购物车
cookie.setMaxAge(3 * 24 * 60 * 60);
// 设置有效路径
cookie.setPath(request.getContextPath());
// 将Cookie发送给浏览器
response.addCookie(cookie);
}