点击一级分类,显示所有商品
什么意思?给你图你就明白了。
点击:一级分类
点击一级分类后跳转到的页面:
跳转的时候是根据一级分类的id查询出对应的商品和左侧的分类,所以在一级分类的超链接后面要跟一个一级分类的id。
<li>
<a href="${ pageContext.request.contextPath }/product_queryByCid.do?
cid=<s:property value="#c.cid"/>"><s:property value="#c.cname"/></a>
|
</li>
如图,点击一级分类的“服装”,左下角出现超链接
ProductAction:
// 点击一级分类查询商品
public String queryByCid() {
//待补全
return "productList";
}
上面的方法暂时实现了跳转功能,之后再补全。
struts2:
<!-- 商品action模块 -->
<action name="product_*" method="{1}" class="productAction">
<result name="productXQ">/WEB-INF/jsp/productXQ.jsp</result>
<!-- 显示所有商品的页面 -->
<result name="productList">/WEB-INF/jsp/productList.jsp</result>
</action>
跳转到:productList.jsp页面
ok,点击一级分类的超链接,给个图看看
productList.jsp(左侧分类)
由第二张图可知,点击一级分类后显示的页面,要查询一级分类和他的二级分类,因为一级分类已经存放在session中,不必再次查询,所以页面上要想显示应该这么做:
<!-- 迭代一级分类 -->
<s:iterator value="#session.cList" var ="c">
<dl>
<dt>
<a
href="${ pageContext.request.contextPath }/image/蔬菜 - Powered By Mango Team.htm"><s:property value="#c.cname"/> </a>
</dt>
<!-- 二级分类 -->
<s:iterator value="#c.categorySeconds" var="cs">
<dd>
<a><s:property value="#cs.csname"/></a>
</dd>
</s:iterator>
</dl>
</s:iterator>
因为一级分类存在session中,所有通过#session.cList获取,二级分类有多个,所以还需要迭代显示一级分类下的所有二级分类
效果图:因为现在只做了服装这一个模块,所以下图显示为:
因为查询一级分类的时候,想要把二级分类也查询出来,所有要一级分类中实体映射文件的懒加载。由于Set集合是无序的,所以为了不让顺序每次都显示不一样,也需要加一个按照csid排序的代码
<set order-by="csid" name="categorySeconds" lazy="false">
这里有个大前提是,你必须通过首页才点击一级分类才能访问二级分类,直接通过url地址栏输入无效,因为一级分类是在indexAction中取得的,所以必须通过商城首页。
左边显示完成之后,现在开始做右边的商品列表。当然如果是服装模块,右边显示的肯定就是所有服装。现在只做服装模块,至于蔬菜、日用、电器、学习等模块以后再说,功能是一样的,就是不想录数据了。
productList.jsp(右侧商品分页)
1、通过一级分类查询到所有商品(点击一级分类)
2、分页显示
问题1:由于一级分类和二级分类是一对多,二级分类和商品是一对多,一级分类要查询到所有商品,必须得绕两个弯.
注意1:点击一级分类,要默认跳转到第一页,所以要再在一级分类后传一个page=1.
看图:
页面:
ProductAction 的queryByCid方法
// 接收一级分类的cid
private long cid;
//接收当前页数
private int page ;
//省略setter getter方法
// 点击一级分类查询商品
public String queryByCid() {
//根据一级分类查询所有商品
PageBean<Product> pageBean = productService.queryAllProductsByCid(cid,page);
//保存到值栈
ActionContext.getContext().getValueStack().set("pageBean", pageBean);
return "productList";
}
上面productService调用了queryAllProductsByCid方法,看下service层
produceService:
/***
* 根据一级分类查询所有商品
* @param cid 一级分类的cid<br>.
* @param page 当前页数<br>
* @return
*/
PageBean<Product> queryAllProductsByCid(long cid, int page);
service层实现类:
@Override
public PageBean<Product> queryAllProductsByCid(long cid, int page) {
PageBean<Product> pageBean = new PageBean<Product>();
// 每页显示的个数
int limit = 8;
pageBean.setLimit(limit);
// 当前页
pageBean.setPage(page);
// 查询的总个数
int totalCount = 0;
totalCount = findCounts(cid);
pageBean.setTotalCount(totalCount);
// 设置总页数
int totalPage = 0;
if (totalCount % limit == 0) {
totalPage = totalCount / limit;
} else {
totalPage = totalCount / limit + 1;
}
pageBean.setTotalPage(totalPage);
// 设置返回的商品集合
int begin = (page - 1) * limit;
List<Product> list = queryAllProduct(cid, begin, limit);
pageBean.setList(list);
return pageBean;
}
查询的总个数:findCounts(cid)方法
private int findCounts(long cid) {
int count= sessionFactory.getCurrentSession()
.createQuery("select p from Product p join p.categorySecond cs join cs.category c where c.cid = ?")
.setParameter(0, cid).list().size();
if(count>0){
return count;
}else{
return 0 ;
}
}
查询的所有商品集合:
private List<Product> queryAllProduct(long cid, int begin, int limit) {
List<Product> list = sessionFactory.getCurrentSession()
.createQuery("select p from Product p join p.categorySecond cs join cs.category c where c.cid = ?")
.setParameter(0, cid)
.setFirstResult(begin)
.setMaxResults(limit)
.list();
if(list!=null&&list.size()>0){
return list;
}
return null;
}
sql:
select p.* from category c,categorysecond cs,product p where c.cid = cs.cid and cs.csid = p.csid and c.cid = ?
hql:
select p from Product p join p.categorySecond cs join cs.category c where c.cid = ?
hql语句通过一级分类id查询所有商品,使用join语句通过外键关联查询。
再贴一下表关系图:
现在前台显示数据:
productList.jsp:
<s:iterator value="pageBean.list" var="pl" >
<li><a href="./京华商城分页面.htm"> <img
src="${ pageContext.request.contextPath }/<s:property value="#pl.image"/>"
width="170" height="170" style="display: inline-block;"/> <span
style='color:green'> <s:property value="#pl.pname"/> </span> <span class="price">
商城价: <s:property value="#pl.shop_price"/>/元 </span> </a>
</li>
</s:iterator>
效果图:
每页显示8个
页卡制作
首页:即第一个按钮
<!-- 首页 -->
<a class="firstPage" href="${ pageContext.request.contextPath }/product_queryByCid.do?
cid=<s:property value="cid"/>&page=1"></a>
这里要说下为什么要传给后台这两个数据,和怎么传。
1.为什么要传,因为是分页,所以根据后台action的方法,需要这两个参数,否则缺少参数会报空指针错误。
2.怎么传?page=1肯定没问题,cid怎么得到,如果你想通过#session.cList.cid,这样肯定不行,因为cList是个集合,保存的是多个对象,怎么能获取这个页面的cid呢?
解答:因为后天productAction中定义了一个属性
private long cid ;
并提供了setter,getter方法,ok。setter方法你知道肯定是为了获取页面传来的值,那么getter方法呢?对喽,getter方法就是在jsp中获取action中的值的。
因为在productAction中定义了属性驱动cid,所有cid会也会存在于值栈中,所以前台JSP页面直接:
<s:property value="cid"/>
这样就能取出cid的值,而这个cid正是首页点击一级分类传到productAction中的cid的值。
如图,鼠标滑过第一个按钮,即“首页”时左下角的超链接:
现在做最后一页:
同理,最后一页也要传一个cid,而且最后一页的页码page就是总页数
代码如下:
<!-- 最后一页 -->
<a class="lastPage" href="${ pageContext.request.contextPath }/product_queryByCid.do?
cid=<s:property value="cid"/>&page=<s:property value="pageBean.totalPage"/>"> </a>
如图:
上一页:上一页就是当前页-1.当前页怎么获取:pageBean.page就是当前页,上一页代码:
<!-- 上一页 -->
<a class="previousPage" href="${ pageContext.request.contextPath }/product_queryByCid.do?
cid=<s:property value="cid"/>&page=<s:property value="pageBean.page-1"/>"></a>
同理下一页就是当前页+1,即pageBean.page+1
<!-- 下一页 -->
<a class="previousPage" href="${ pageContext.request.contextPath }/product_queryByCid.do?
cid=<s:property value="cid"/>&page=<s:property value="pageBean.page+1"/>"></a>
ok,制作完首页,尾页,上一页和下一页,现在开始制作最后中间页卡
中间有几页应该通过interator标签循环遍历出来:
<!-- 当前页 -->
<s:iterator begin="1" end="pageBean.totalPage" var="i">
<s:if test="#i==page">
<a class="currentPage">
<s:property value="#i"/>
</a>
</s:if>
<s:else>
<a href="${ pageContext.request.contextPath }/product_queryByCid.do?
cid=<s:property value="cid"/>&page=<s:property value="#i"/>">
<s:property value="#i"/></a>
</s:else>
</s:iterator>
循环遍历的begin表示从第一页开始,end表示总页数,var=”i”表示遍历的页卡数,
page=<s:property value="#i"/>
表示点击的第几页,其中有个判断就是,如果是当前页:
<s:if test="#i==page">
就不显示点击功能,并给一个框框,表示这是当前页。
ok,到这里简单分页几页分页跳转就基本完成了,但是这里又个小问题就是,当当前的第一页时,不应该显示上一页按钮,要不然跳转了,成了-1页,所以应该加个判断:
<s:if test="page!=1">
看个图,当前这是第一页,则不显示上一页按钮:
同理下一页也是如此:
<!-- 下一页 -->
<!-- 判断当前页是不是最后一页 -->
<s:if test="pageBean.page!=pageBean.totalPage">
<a class="previousPage" href="${ pageContext.request.contextPath }/product_queryByCid.do?
cid=<s:property value="cid"/>&page=<s:property value="pageBean.page+1"/>"></a>
</s:if>
这里贴上关于显示分页的所有jsp代码:
<div class="pagination">
<!-- 首页 -->
<a class="firstPage" href="${ pageContext.request.contextPath }/product_queryByCid.do?
cid=<s:property value="cid"/>&page=1"></a>
<!-- 上一页 -->
<!-- 判断当前页如不是第一页则显示 -->
<s:if test="page!=1">
<a class="previousPage" href="${ pageContext.request.contextPath }/product_queryByCid.do?
cid=<s:property value="cid"/>&page=<s:property value="pageBean.page-1"/>"></a>
</s:if>
<!-- 当前页 -->
<s:iterator begin="1" end="pageBean.totalPage" var="i">
<s:if test="#i==page">
<a class="currentPage">
<s:property value="#i"/>
</a>
</s:if>
<s:else>
<a href="${ pageContext.request.contextPath }/product_queryByCid.do?
cid=<s:property value="cid"/>&page=<s:property value="#i"/>">
<s:property value="#i"/></a>
</s:else>
</s:iterator>
<!-- 下一页 -->
<!-- 判断当前页是不是最后一页 -->
<s:if test="pageBean.page!=pageBean.totalPage">
<a class="nextPage" href="${ pageContext.request.contextPath }/product_queryByCid.do?
cid=<s:property value="cid"/>&page=<s:property value="pageBean.page+1"/>"></a>
</s:if>
<!-- 最后一页 -->
<a class="lastPage" href="${ pageContext.request.contextPath }/product_queryByCid.do?
cid=<s:property value="cid"/>&page=<s:property value="pageBean.totalPage"/>"> </a>
</div>
最终效果图:
第一页:
中间某页:
尾页:
左侧点击一级分类右侧显示所有商品
productList.jsp:
<dt>
<a
href="${ pageContext.request.contextPath }/product_queryByCid.do?
cid=<s:property value="cid"/>&page=1">
<s:property value="#c.cname"/>
</a>
</dt>
还有一点,点击图片,跳转到详情页:
<s:iterator value="pageBean.list" var="pl" >
<li>
<!-- 点击图片进入详情 -->
<a href="${ pageContext.request.contextPath }/product_findByPid.do?pid=
<s:property value="#pl.pid"/>">
<img
src="${ pageContext.request.contextPath }/<s:property value="#pl.image"/>"
width="170" height="170" style="display: inline-block;"/> <span
style='color:green'> <s:property value="#pl.pname"/> </span> <span class="price">
商城价: <s:property value="#pl.shop_price"/>/元 </span> </a>
</li>
</s:iterator>
点击二级分类查询商品
因为一级分类查询的是所有服装商品,包括男装、女装、童装。而现在是根据二级分类id查询,所以点击男装查询出来的都是男装,点击童装查询出来的都是童装。
为二级分类设计超链接:
productList.jsp
<!-- 二级分类 -->
<s:iterator value="#c.categorySeconds" var="cs">
<dd>
<a href="${ pageContext.request.contextPath }/product_queryByCsid.do?csid=
<s:property value="#cs.csid"/>&page=1">
<s:property value="#cs.csname"/>
</a>
</dd>
</s:iterator>
功能比较简单,对应的JSP:
productListBycsid.jsp
productAction方法
//点击二级分类查询商品
public String queryByCsid(){