β

移动商城第五篇【前台展示、后台筛选】

Harries Blog™ 125 阅读

前台准备

web .xml

    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:beans.xml</param-value>
    </context-param>

    <servlet>
        <servlet-name>springmvc</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:springmvc.xml</param-value>
        </init-param>
    </servlet>
    <servlet-mapping>
        <servlet-name>springmvc</servlet-name>
        <url-pattern>*.do</url-pattern>
    </servlet-mapping>

    <filter>
        <filter-name>SpringCharacterEncodingFilter</filter-name>
        <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
        <init-param>
            <param-name>encoding</param-name>
            <param-value>UTF-8</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>SpringCharacterEncodingFilter</filter-name>
        <url-pattern>*.do</url-pattern>
    </filter-mapping>

springmvc

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans 

http://www.springframework.org/schema/beans/spring-beans-3.0.xsd


http://www.springframework.org/schema/context


http://www.springframework.org/schema/context/spring-context-3.0.xsd

 ">
    <context:component-scan base-package="com.rl.ecps.controller"/>
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/shop/"></property>
        <property name="suffix" value=".jsp"></property>
    </bean>
</beans>

访问首页:

@Controller
@RequestMapping("/item")
public class EbItemController {

    @RequestMapping("toIndex.do")
    public String toIndex() {
        return "index";
    }

}

移动商城第五篇【前台展示、后台筛选】

由于下面使用了iframe,于是就出现了404错误了。 src 是不能直接获取WEB-INF的JSP的。

        <iframe id="itemListIframe" src="http://www.liuhaihua.cn/archives/phoneClassification.jsp" frameBorder=0 scrolling=no width="100%" height="200%"  ></iframe>

于是乎,我们把地址修改成访问controller,controller做跳转就行了。

    <iframe id="itemListIframe" src="http://www.liuhaihua.cn/archives/${path}/item/phoneClassification.do" frameBorder=0 scrolling=no width="100%" height="200%"  ></iframe>
    @RequestMapping("phoneClassification.do")
    public String phoneClassification() {
        return "phoneClassification";
    }

设置完之后我们就可以能看到页面了。

移动商城第五篇【前台展示、后台筛选】

筛选后台

我们要做的就是, 通过前台给出的 参数 ,我们后台筛选出 数据 在前台展示。

移动商城第五篇【前台展示、后台筛选】

首先,我们来分析一下可以筛选的参数把:


移动商城第五篇【前台展示、后台筛选】

从参数上我们可以分为几类:

  • 价钱
  • 品牌
  • 基本属性参数

首先,我们把所有品牌先查询和对应的参数先查询出来吧。

    @RequestMapping("toIndex.do")
    public String toIndex(Model model) {
        List<EbBrand> ebBrands = brandService.selectBrand();
        List<EbFeature> isSelect = featureService.selectIsSelect();
        model.addAttribute("ebBrands", ebBrands);
        model.addAttribute("isSelect", isSelect);

        return "index";
    }

在页面上做展示

            <c:forEach items="${isSelect}" var="feature">
                <li style="display:none"><b>${feature.featureName}:</b>
                    <p>
                        <a href="javascript:void(0);" title="不限" class="here">不限</a>
                        <c:forEach items="${feature.selectValues}" var="val">
                            <a href="javascript:void(0);" >${val}</a>
                        </c:forEach>
                    </p>
                </li>
            </c:forEach>

移动商城第五篇【前台展示、后台筛选】

接收参数数据

    /**
     * 接收条件,查询出符合条件的商品
     * @param brandId 品牌id
     * @param price   价钱
     * @param param   被选中的参数
     * @return
     */
    @RequestMapping("listItem.do")
    public String listItem(Long brandId, String price, String param) {
        
        return "phoneClassification";
    }

参数我们已经知道了,那我们怎么写这个SQL语句呢??

我的分析是这样子的:

/**
根据价钱,品牌,被选中属性查询符合条件的商品
  涉及到的表:
.商品
.商品
.参数值
.价钱
 */
SELECT *
FROM EB_BRAND brand, EB_ITEM item, EB_PARA_VALUE para, EB_SKU sku
WHERE brand.BRAND_ID = item.BRAND_ID AND
      para.ITEM_ID = item.ITEM_ID AND
      sku.ITEM_ID = item.ITEM_ID AND
      brand.BRAND_ID = 1002 AND
      sku.SKU_PRICE BETWEEN 1 AND 800000 AND 
      para.PARA_VALUE = 'Android4.0';

在价钱中是一个范围,因此我们用between and 语法,而我们的参数传递过来可能是与很多的,因此只要我们使用 动态SQL 循环就行了。

因此,我们的 mapper 中的SQL是这样子的。

    <select id="listItem" parameterType="map" resultMap="listItemRM">
        SELECT item.*, sku.SKU_PRICE
        FROM EB_BRAND brand, EB_ITEM item, EB_PARA_VALUE para, EB_SKU sku
        <where>
            brand.BRAND_ID = item.BRAND_ID
            para.ITEM_ID = item.ITEM_ID AND
            sku.ITEM_ID = item.ITEM_ID AND
            <if test="brandId!=null">
                brand.BRAND_ID = #{brandId} AND
            </if>
            <if test="minPrice!=null">
                sku.SKU_PRICE BETWEEN #{minPrice} AND #{maxPrice} AND
            </if>
            <if test="paraList!=null">
                <foreach collection="paraList" item="val" >
                    para.PARA_VALUE = #{val} AND
                </foreach>
            </if>
        </where>
    </select>

由于我们的展示数据还需要价钱,返回的basemap不够用。我们就新创建了一个Map

  <resultMap type="com.rl.ecps.model.EbItem" id="listItemRM" extends="BaseResultMap">
    <result column="sku_price" property="skuPrice"/>
  </resultMap>

在实体中给予对应的属性

    private BigDecimal skuPrice;
    
    public BigDecimal getSkuPrice() {
        return skuPrice;
    }

    public void setSkuPrice(BigDecimal skuPrice) {
        this.skuPrice = skuPrice;
    }

编写Dao和Service

dao实现

    public List<EbItem> listItem(Map<String, Object> map) {
        return this.getSqlSession().selectList(nameSpace + "listItem", map);
    }

service实现

    public List<EbItem> listItem(Long brandId, String price, String param) {

        Map<String, Object> map = new HashedMap();
        map.put("brandId", brandId);

        //将价钱进行分割成两部分
        if (StringUtils.isNotBlank(price)) {
            String[] strings = price.split(",");
            map.put("minPrice", strings[0]);
            map.put("maxPrice", strings[1]);
        }

        //分割并装载到map中
        List<String> list = new ArrayList<String>();
        if (StringUtils.isNotBlank(param)) {
            String[] paras = param.split(",");
            for (String para : paras) {
                list.add(para);
            }
            map.put("paraList", list);
        }
        return itemDao.listItem(map);
    }

前台请求

移动商城第五篇【前台展示、后台筛选】

基于这么一个 需求 , 当我们点击一个条件的时候,我们要把当前所有获取的条件都获取出来。然后提交给 服务器 端就行了!

在点击选中事件上,我们获取数据

  • 其实自定义的值可以使用一个就行了。没必要分三个那么多(可以统一获取) ..
                //使用变量状态我们的数据
                var price = "";
                var brandId = "";
                var paraStr = "";

                $(".filter li a").each(function () {
                    //拿到选中的超链接
                    var clazz = $(this).attr("class");
                    if (clazz == "here") {

                        //得到他们的类型【在html中我们自定义了3个类型】
                        var myType = $(this).attr("myType");

                        //根据不同的类型,对其进行不同的操作
                        if (myType == "brand") {
                            brandId = $(this).attr("myBrandValue")
                        } else if (myType == "price") {
                            price = $(this).attr("myPriceValue");
                        } else if (myType == "para" && $(this).attr("myParaValue") != null) {

                            var val = $(this).attr("myParaValue");
                            paraStr = paraStr + val+",";
                        }
                    }
                });
                alert(price + "---" + brandId + "---" + paraStr);

移动商城第五篇【前台展示、后台筛选】

修改iframe的请求路径,把我们的参数带过去

  var iframePath = "${path}/item/listItem.do?price="+price+"&brandId="+brandId+"&paraStr="+paraStr;
                $("#itemListIframe").attr("src", iframePath);

controller

 /**
     * 接收条件,查询出符合条件的商品
     *
     * @param brandId 品牌id
     * @param price   价钱
     * @param paraStr   被选中的参数
     * @return
     */
    @RequestMapping("/listItem.do")
    public String listItem(Long brandId, String price, String paraStr, Model model) {

        // TODO 基本效果出来了,但条件查询还有问题。

        List<EbItem> items = itemService.listItem(brandId, price, paraStr);

        model.addAttribute("items", items);

        return "phoneClassification";
    }

我们在查询的时候,发现很多相同价钱的手机都展示出来的。讲道理我们只要展示最低价钱那款就行了

移动商城第五篇【前台展示、后台筛选】

想要展示最低价那款,还是要去修改SQL语句。需要用到分组函数了。

首先我有这么一个商品

移动商城第五篇【前台展示、后台筛选】

它有两个最小销售单元,一般我们在页面上显示最便宜的那个就行了。

移动商城第五篇【前台展示、后台筛选】

我们的SQL语句可以写成这样:

SELECT min(sku.SKU_PRICE) SKU_PRICE ,item.*
      FROM  EB_ITEM item, EB_PARA_VALUE para, EB_SKU sku
      WHERE  para.ITEM_ID = item.ITEM_ID
            AND sku.ITEM_ID = item.ITEM_ID
            AND item.BRAND_ID = 3069
            AND sku.SKU_PRICE BETWEEN 1 AND 1000000
            AND para.PARA_VALUE = 'Android'
            AND item.ITEM_ID=3080
GROUP BY item.ITEM_ID,
  item.ITEM_NAME,
  item.ITEM_NO,
  item.BRAND_ID,
  item.CAT_ID,
  item.TAG_IMG_ID,
  item.TAG_IMG,
  item.IS_NEW,
  item.IS_GOOD,
  item.IS_HOT,
  item.PROMOTION,
  item.AUDIT_STATUS,
  item.SHOW_STATUS,
  item.IMGS,
  item.KEYWORDS,
  item.PAGE_DESC,
  item.ITEM_RECYCLE,
  item.ON_SALE_TIME,
  item.CHECK_TIME,
  item.UPDATE_TIME,
  item.UPDATE_USER_ID,
  item.CREATE_TIME,
  item.CHECKER_USER_ID,
  item.FULL_PATH_DEPLOY,
  item.FULL_PATH_DEPLOY_OFFER,
  item.ORIGINAL_ITEM_ID,
  item.LAST_STATUS,
  item.MERCHANT_ID,
  item.ITEM_SORT,
  item.SALES,
  item.CREATE_USER_ID,
  item.SIM_LEVEL,
  item.GIFT_DESC,
  item.GIFT_IMG,
  item.GIFT_SHOW_TYPE,
  item.IMG_SIZE1
order by item.item_id desc

修改一下Mapper中的SQL语句:

<select id="listItem" parameterType="map" resultMap="listItemRM">
        SELECT item.*, min(sku.SKU_PRICE) sku_price
        FROM  EB_ITEM item, EB_PARA_VALUE para, EB_SKU sku
        <where>
            para.ITEM_ID = item.ITEM_ID AND
            sku.ITEM_ID = item.ITEM_ID
            <if test="brandId!=null">
                AND item.BRAND_ID = #{brandId}
            </if>
            <if test="minPrice!=null">
                AND sku.SKU_PRICE BETWEEN #{minPrice} AND #{maxPrice}
            </if>
            <if test="paraList!=null">
                <foreach collection="paraList" item="val">
                    AND para.PARA_VALUE = #{val}
                </foreach>
            </if>
        </where>
        GROUP BY item.ITEM_ID,
        item.ITEM_NAME,
        item.ITEM_NO,
        item.BRAND_ID,
        item.CAT_ID,
        item.TAG_IMG_ID,
        item.TAG_IMG,
        item.IS_NEW,
        item.IS_GOOD,
        item.IS_HOT,
        item.PROMOTION,
        item.AUDIT_STATUS,
        item.SHOW_STATUS,
        item.IMGS,
        item.KEYWORDS,
        item.PAGE_DESC,
        item.ITEM_RECYCLE,
        item.ON_SALE_TIME,
        item.CHECK_TIME,
        item.UPDATE_TIME,
        item.UPDATE_USER_ID,
        item.CREATE_TIME,
        item.CHECKER_USER_ID,
        item.FULL_PATH_DEPLOY,
        item.FULL_PATH_DEPLOY_OFFER,
        item.ORIGINAL_ITEM_ID,
        item.LAST_STATUS,
        item.MERCHANT_ID,
        item.ITEM_SORT,
        item.SALES,
        item.CREATE_USER_ID,
        item.SIM_LEVEL,
        item.GIFT_DESC,
        item.GIFT_IMG,
        item.GIFT_SHOW_TYPE,
        item.IMG_SIZE1
        order by item.item_id desc
    </select>

再次查看的时候,只出现一台了。


移动商城第五篇【前台展示、后台筛选】

标准答案的SQL是使用exists关键字来进行查询的:在单表查询的情况下,看有没有符合条件的数据,如果符合,那么exists为ture

 <select id="listItem" parameterType="map" resultMap="listItemRM">
    select min(es.sku_price) sku_price, ei.*
  from eb_item ei, eb_sku es
  <where>
    ei.item_id = es.item_id
    <if test="minPrice != null">
        and es.sku_price between #{minPrice} and #{maxPrice}
    </if>
    <if test="brandId != null">
         and ei.brand_id = #{brandId}
    </if>
    <if test="paraList != null">
        <foreach collection="paraList" item="paraValue">
            and exists (select *
              from eb_para_value t
             where ei.item_id = t.item_id
               and t.para_value = #{paraValue})
        </foreach>
    </if>
  </where>
 group by ei.ITEM_ID,
          ei.ITEM_NAME,
          ei.ITEM_NO,
          ei.BRAND_ID,
          ei.CAT_ID,
          ei.TAG_IMG_ID,
          ei.TAG_IMG,
          ei.IS_NEW,
          ei.IS_GOOD,
          ei.IS_HOT,
          ei.PROMOTION,
          ei.AUDIT_STATUS,
          ei.SHOW_STATUS,
          ei.IMGS,
          ei.KEYWORDS,
          ei.PAGE_DESC,
          ei.ITEM_RECYCLE,
          ei.ON_SALE_TIME,
          ei.CHECK_TIME,
          ei.UPDATE_TIME,
          ei.UPDATE_USER_ID,
          ei.CREATE_TIME,
          ei.CHECKER_USER_ID,
          ei.FULL_PATH_DEPLOY,
         ei.FULL_PATH_DEPLOY_OFFER,
          ei.ORIGINAL_ITEM_ID,
          ei.LAST_STATUS,
          ei.MERCHANT_ID,
          ei.ITEM_SORT,
          ei.SALES,
          ei.CREATE_USER_ID,
          ei.SIM_LEVEL,
          ei.GIFT_DESC,
          ei.GIFT_IMG,
          ei.GIFT_SHOW_TYPE,
          ei.IMG_SIZE1
          order by ei.item_id desc
  </select>

总结

  • 准备前台页面,在web.xml一样是需要加载我们Core模块的bean.xml文件。需要自己手动去写一个springMVC的 配置 文件。
  • 在筛选后台的时候,接收类型可以分成三类
    • 价钱
    • 品牌Id
    • 要被筛选的条件。
  • 对于这三类,我们很容易就能够把他们显示出来。 最主要的问题是获取他们这些数据、然后根据这些数据进行查询

    • 我是这样做的:把他们关联的表一次性写出来,内连接他们的相同条件。
      • 价钱参数使用between and关键字来搜索
      • 品牌用等值连接
      • 被选中的参数用动态的SQL来进行查询
      • 还有值得注意的就是最小销售单元,一般我们只会在页面上显示最低价的那款商品。因此我们用到分组函数。
  • 对于标准答案,是将被选中的参数使用exist关键字来对其进行过滤。一个条件对应一个exist。至于他俩有什么区别我倒不知道了,知道了再回来补吧。

  • 那怎么获取这三类的值呢??可以在每个a标签上自定义类型,还有对应的值。当点击其中一个标签的时候, 遍历 这些标签,获取他们的值。
    • 价钱使用字符串来接收,是一个范围。我们接收完在后台切割就行了。
    • 品牌直接使用Long类型接收
    • 被选中的标签也可以使用字符串来接收,同样在后台切割就行了。
  • 由于我们有3个参数、Dao层使用map集合来接收。

原文

http://zhongfucheng.bitcron.com/post/ssmxiang-mu/yi-dong-shang-cheng-di-wu-pian-qian-tai-zhan-shi-hou-tai-shai-xuan

PS:如果您想和业内技术大牛交流的话,请加qq群(527933790)或者关注微信公众 号(AskHarries),谢谢!

转载请注明原文出处: Harries Blog™ » 移动商城第五篇【前台展示、后台筛选】

作者:Harries Blog™
追心中的海,逐世界的梦
原文地址:移动商城第五篇【前台展示、后台筛选】, 感谢原作者分享。

发表评论