模块1:一级分类
用户成功登陆之后,会跳转到首页,现在我们来制作一级分类。
先看一张商城首页的图:
图是从网上找的,那个被红框框住的就是一级分类。
点击一级分类后跳转到一个新的页面,这个页面左边是所有一级分类和二级分类的列表,右边是二级分类的所有商品。
点击一级分类后跳转的页面:
左边蓝字是一级分类,黑字是一级分类下的二级分类,右边是所有商品,分页显示。
准备工作
这里阐明一下表关系:
一级分类表对二级分类表是一对多关系
二级分类表对商品表是一对多关系
一级分类实体:
//一级分类
@SuppressWarnings("serial")
public class Category implements Serializable {
private long cid; // id
private String cname; // 一级分类名称
// 一级分类中存放二级分类的集合:
private Set<CategorySecond> categorySeconds = new HashSet<CategorySecond>();
//省略setter getter方法
一级分类映射文件:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="com.shopping.category.entity.Category" table="category">
<id name="cid">
<generator class="native"/>
</id>
<property name="cname"/>
<!-- 配置二级分类的集合 -->
<set order-by="csid" name="categorySeconds" lazy="false">
<key column="cid"/>
<one-to-many class="com.shopping.categorySecond.entity.CategorySecond"/>
</set>
</class>
</hibernate-mapping>
二级分类实体:
SuppressWarnings("serial")
public class CategorySecond implements Serializable {
private long csid; //id
private String csname; //二级分类名称
// 所属一级分类.存的是一级分类的对象.
private Category category; //一级分类对象
// 配置商品集合,一对多
private Set<Product> products = new HashSet<Product>();
//省略setter getter方法
二级分类映射文件:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="com.shopping.categorySecond.entity.CategorySecond" table="categorysecond">
<id name="csid">
<generator class="native"/>
</id>
<property name="csname"/>
<!-- 二级分类与一级分类的guanlian -->
<many-to-one name="category" lazy="false" class="com.shopping.category.entity.Category" column="cid"></many-to-one>
<!-- 二级分类与商品的关联 -->
<set name="products">
<key column="csid"/>
<one-to-many class="com.shopping.product.entity.Product"/>
</set>
</class>
</hibernate-mapping>
商品实体:
@SuppressWarnings("serial")
public class Product implements Serializable{
private long pid; //商品id
private String pname; //商品名称
private Double market_price; //市场价
private Double shop_price; //商城价
private String image; //图片路径
private String pdesc; //商品描述
private Integer is_hot; //是否热门商品
private Date pdate; //上架时间
// 二级分类的外键:使用二级分类的对象.
private CategorySecond categorySecond;
//省略setter getter方法
商品映射文件:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="com.shopping.product.entity.Product" table="product">
<id name="pid">
<generator class="native"/>
</id>
<property name="pname"/>
<property name="market_price"/>
<property name="shop_price"/>
<property name="image"/>
<property name="pdesc"/>
<property name="is_hot"/>
<property name="pdate"/>
<many-to-one name="categorySecond" lazy="false" class="com.shopping.categorySecond.entity.CategorySecond" column="csid"/>
</class>
</hibernate-mapping>
数据库生成的表结构:
一级分类
IndexAction ,重新改造shopping方法,在访问首页的时候就查询所有一级分类
JSP:
<!-- 遍历一级分类 -->
<s:iterator value="#session.cList" var="c">
<li>
<a href="./蔬菜分类.htm"><s:property value="#c.cname"/></a>
|
</li>
</s:iterator>
IndexAction:
@SuppressWarnings("serial")
@Controller
@Scope("prototype")
public class IndexAction extends ActionSupport {
// 注入一级分类service
@Autowired
private CategoryService categoryService;
// 用户访问首页,跳转到WEB-INF下的JSP首页面
public String shopping() throws Exception {
// 首页跳转,查询所有一级分类
List<Category> cList = categoryService.queryAll();
/***
* 可以把查询出来的数据放在值栈或者sesson中<br>
* 因为一级分类每个页面都有,为了不用每次跳转页面都查询<br>
* 最好把它放入session中.<br>
* 主要原因就是每个页面都有一级分类,这是关键.
*/
if(cList!=null&&cList.size()>0){
//将一级分类存入session中
ActionContext.getContext().getSession().put("cList",cList);
}
return "index";
}
}
这里说明下为什么把查询到的一级分类存储在session中,一级分类是很多页面都有的,也就是说,一级分类在head.jsp中,为了避免每次点击商城的超链接都去值栈中查询一级分类,所有把它放在了session中。
由代码可知,上面调用了一个queryAll方法,这是方法是BaseDao中的。CategoryService中继承了BaseDao。所以可以直接用。
现在我们在数据库中存几条测试数据,入下图:
访问服务器:
由上可以看出,访问商城首页可以取出所有一级分类。
模块2:热门商品查询
首页上热门商品的查询,默认只显示10个
思路:
通过QBC查询,根据上传时间的倒序排序,效果如下图:
JSP:
<ul class="tabContent" style="display: block;">
<!-- 热门商品 -->
<s:iterator value="hList" var="h">
<li>
<a target="_blank">
<img src="${ pageContext.request.contextPath }/<s:property value="#h.image"/>"
style="display: block;" /></a>
</li>
</s:iterator>
</ul>
IndexAction:
// 查询热门商品
List<Product> hList = productService.queryHotProduct();
if (hList != null && hList.size() > 0) {
//保存到值栈中
ActionContext.getContext().getValueStack().set("hList", hList);
}
由上代码调用了一个queryHotProduct()
ProductService:
public interface ProductService extends BaseDao<Product>{
/***
* 商城首页查询热门商品
* @return
*/
List<Product> queryHotProduct();
}
ProductServiceImpl:
@Transactional
@Service
public class ProductServiceImpl extends BaseDaoImpl<Product> implements
ProductService {
@SuppressWarnings("unchecked")
@Override
public List<Product> queryHotProduct() {
Criteria criteria = sessionFactory.getCurrentSession().createCriteria(
Product.class);
criteria.setFirstResult(0);
criteria.setMaxResults(10);
// 查询热门的商品,条件is_host = 1
criteria.add(Restrictions.eq("is_hot", 1));
// 倒序排序输出:
criteria.addOrder(Order.desc("pdate"));
List<Product> pList = criteria.list();
System.out.println("热门商品个数:"+pList.size());
return pList;
}
}
数据库中product中的数据,博主亲自录入的,录不动了就先这么多
通过上图可以看到,image的路径是product/1/…
product是一个在项目WebRoot下的文件夹
图片都保存在product文件夹中
重启服务器,访问首页:
模块3:最新商品
同理和最热商品一样。
只是不用设置查询条件.
JSP:
<!-- 遍历最新商品 -->
<s:iterator value="nList" var="n">
<li><a target="_blank"><img
src="${ pageContext.request.contextPath }/<s:property value="#n.image"/>"
style="display: block;"/>
</a></li>
</s:iterator>
IndexAction:
// 查询最新商品
List<Product> nList = productService.queryNewProduct();
if (nList != null && nList.size() > 0) {
// 保存到值栈中
ActionContext.getContext().getValueStack().set("nList", nList);
}
queryNewProduct()方法在service中。
service层:
/***
* 查询最新商品
* @return
*/
List<Product> queryNewProduct();
service层实现类:
@Override
public List<Product> queryNewProduct() {
Criteria criteria = sessionFactory.getCurrentSession().createCriteria(
Product.class);
criteria.setFirstResult(0);
criteria.setMaxResults(10);
// 倒序排序输出:
criteria.addOrder(Order.desc("pdate"));
List<Product> nList = criteria.list();
return nList;
}
重启服务器,访问页面
这里提一下整体IndexAction上的代码
package com.shopping.index.action;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Controller;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionSupport;
import com.shopping.category.entity.Category;
import com.shopping.category.service.CategoryService;
import com.shopping.product.entity.Product;
import com.shopping.product.service.ProductService;
@SuppressWarnings("serial")
@Controller
@Scope("prototype")
public class IndexAction extends ActionSupport {
// 注入一级分类service
@Autowired
private CategoryService categoryService;
// 注入商品service
@Autowired
private ProductService productService;
// 用户访问首页,跳转到WEB-INF下的JSP首页面
public String shopping() throws Exception {
// 首页跳转,查询所有一级分类
List<Category> cList = categoryService.queryAll();
if (cList != null && cList.size() > 0) {
// 将一级分类存入session中
ActionContext.getContext().getSession().put("cList", cList);
}
// 查询热门商品
List<Product> hList = productService.queryHotProduct();
if (hList != null && hList.size() > 0) {
// 保存到值栈中
ActionContext.getContext().getValueStack().set("hList", hList);
}
// 查询最新商品
List<Product> nList = productService.queryNewProduct();
if (nList != null && nList.size() > 0) {
// 保存到值栈中
ActionContext.getContext().getValueStack().set("nList", nList);
}
return "index";
}
}