電商入口網站商品品類多級聯動SpringBoot+Thymeleaf實現
阿新 • • 發佈:2018-11-03
在淘寶、京東等電商網站,其入口網站都有一個商品品類的多級聯動,滑鼠移動,就顯示,因為前端不是我做的,所以不說明前端實現,只介紹後端實現。
搭建部署SpringBoot環境
配置檔案配置:
開啟了對Thymeleaf模組引擎的支援
server: port: 8081 #logging: # config: classpath:logback_spring.xml # level: # com.muses.taoshop: debug # path: /data/logs spring: datasource: # 主資料來源 shop: url: jdbc:mysql://127.0.0.1:3306/taoshop?autoReconnect=true&useUnicode=true&characterEncoding=utf8&characterSetResults=utf8&useSSL=false username: root password: root driver-class-name: com.mysql.jdbc.Driver type: com.alibaba.druid.pool.DruidDataSource # 連線池設定 druid: initial-size: 5 min-idle: 5 max-active: 20 # 配置獲取連線等待超時的時間 max-wait: 60000 # 配置間隔多久才進行一次檢測,檢測需要關閉的空閒連線,單位是毫秒 time-between-eviction-runs-millis: 60000 # 配置一個連線在池中最小生存的時間,單位是毫秒 min-evictable-idle-time-millis: 300000 # Oracle請使用select 1 from dual validation-query: SELECT 'x' test-while-idle: true test-on-borrow: false test-on-return: false # 開啟PSCache,並且指定每個連線上PSCache的大小 pool-prepared-statements: true max-pool-prepared-statement-per-connection-size: 20 # 配置監控統計攔截的filters,去掉後監控介面sql無法統計,'wall'用於防火牆 filters: stat,wall,slf4j # 通過connectProperties屬性來開啟mergeSql功能;慢SQL記錄 connection-properties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000 # 合併多個DruidDataSource的監控資料 use-global-data-source-stat: true # jpa: # database: mysql # hibernate: # show_sql: true # format_sql: true # ddl-auto: none # naming: # physical-strategy: org.hibernate.boot.entity.naming.PhysicalNamingStrategyStandardImpl # mvc: # view: # prefix: /WEB-INF/jsp/ # suffix: .jsp #新增Thymeleaf配置 thymeleaf: cache: false prefix: classpath:/templates/ suffix: .html mode: HTML5 encoding: UTF-8 content-type: text/html #Jedis配置 # jedis : # pool : # host : 127.0.0.1 # port : 6379 # password : redispassword # timeout : 0 # config : # maxTotal : 100 # maxIdle : 10 # maxWaitMillis : 100000
SpringBoot啟動類:
package com.muses.taoshop; import org.mybatis.spring.boot.autoconfigure.MybatisAutoConfiguration; import org.springframework.boot.*; import org.springframework.boot.autoconfigure.*; import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; import org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration; import org.springframework.boot.web.servlet.ServletComponentScan; import org.springframework.cache.annotation.EnableCaching; import org.springframework.scheduling.annotation.EnableAsync; import org.springframework.scheduling.annotation.EnableScheduling; import org.springframework.stereotype.*; import org.springframework.transaction.annotation.EnableTransactionManagement; import org.springframework.web.bind.annotation.*; /** * * <pre> * SpringBoot啟動配置類 * </pre> * @author nicky * @version 1.00.00 * <pre> * 修改記錄 * 修改後版本: 修改人: 修改日期: 修改內容: * </pre> */ @Controller @EnableScheduling//開啟對計劃任務的支援 @EnableTransactionManagement//開啟對事務管理配置的支援 @EnableCaching @EnableAsync//開啟對非同步方法的支援 @EnableAutoConfiguration @ServletComponentScan @SpringBootApplication(exclude={DataSourceAutoConfiguration.class, MybatisAutoConfiguration.class, DataSourceTransactionManagerAutoConfiguration.class}) public class PortalApplication { @RequestMapping("/") @ResponseBody String home() { return "portal web!"; } @RequestMapping("/doTest") @ResponseBody String doTest(){ System.out.println(Thread.currentThread().getName()); String threadName = Thread.currentThread().getName(); return threadName; } public static void main(String[] args) throws Exception { SpringApplication.run(PortalApplication.class, args); } }
寫個Controller類跳轉到入口網站:
ps:品類多級聯動思路其實就是先構建一個樹,我這裡的做法就是先查詢處理,然後通過工具類,進行遞迴遍歷,待會給出工具類程式碼,僅供參考。listCategory方法其實就是獲取所有的品類資訊
package com.muses.taoshop.web.controller.portal; import com.alibaba.fastjson.JSON; import com.muses.taoshop.item.entity.ItemBrand; import com.muses.taoshop.item.entity.ItemCategory; import com.muses.taoshop.item.entity.ItemPortal; import com.muses.taoshop.item.service.IItemBrankService; import com.muses.taoshop.item.service.IItemCategoryService; import com.muses.taoshop.item.service.IItemService; import com.muses.taoshop.util.CategoryTreeUtils; import com.muses.taoshop.web.controller.BaseController; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.util.CollectionUtils; import org.springframework.web.bind.annotation.*; import org.springframework.web.servlet.ModelAndView; import java.util.Date; import java.util.List; /** * <pre> * 入口網站控制類 * </pre> * * @author nicky * @version 1.00.00 * <pre> * 修改記錄 * 修改後版本: 修改人: 修改日期: 修改內容: * </pre> */ @Controller @RequestMapping("/portal") public class IndexController extends BaseController{ @Autowired IItemService iItemService; @Autowired IItemBrankService iItemBrankService; @Autowired IItemCategoryService iItemCategoryService; /** * 跳轉到入口網站 * @return */ @GetMapping(value = "/toIndex.do") public ModelAndView toIndex(){ info("跳轉到入口網站"); ModelAndView mv = this.getModelAndView(); mv.setViewName("index"); List<ItemPortal> items = iItemService.listItemPortal(); CategoryTreeUtils treeUtil = new CategoryTreeUtils(); List<ItemCategory> list = iItemCategoryService.listCategory(); List<ItemCategory> categories = treeUtil.buildCategoryTree(list); mv.addObject("items" , items); mv.addObject("categories" , categories); return mv; } @GetMapping(value = "/doTest") @ResponseBody public String doTest(){ List<ItemBrand> itemBrands = iItemBrankService.listItemBrand(); String str = JSON.toJSON(itemBrands).toString(); return str; } }
業務介面類:
package com.muses.taoshop.item.service;
import com.muses.taoshop.item.entity.ItemCategory;
import com.muses.taoshop.item.entity.ItemList;
import java.util.List;
/**
* <pre>
* 商品品類資訊介面
* </pre>
*
* @author nicky
* @version 1.00.00
* <pre>
* 修改記錄
* 修改後版本: 修改人: 修改日期: 2018.06.17 10:59 修改內容:
* </pre>
*/
public interface IItemCategoryService {
/**
* 查詢所有商品品類資訊
* @return
*/
List<ItemCategory> listCategory();
業務服務實現類:
package com.muses.taoshop.item.service;
import com.muses.taoshop.item.entity.ItemCategory;
import com.muses.taoshop.item.entity.ItemList;
import com.muses.taoshop.item.mapper.ItemCategoryMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
/**
* <pre>
* 商品品類資訊服務實現類
* </pre>
*
* @author nicky
* @version 1.00.00
* <pre>
* 修改記錄
* 修改後版本: 修改人: 修改日期: 2018.06.17 11:01 修改內容:
* </pre>
*/
@Service
public class ItemCategoryServiceImpl implements IItemCategoryService{
@Autowired
ItemCategoryMapper itemCategoryMapper;
/**
* 查詢所有的商品品類資訊
* @return
*/
@Override
public List<ItemCategory> listCategory() {
return itemCategoryMapper.listCategory();
}
}
Mybatis相關程式碼:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.muses.taoshop.item.mapper.ItemCategoryMapper" >
<resultMap id="BaseResultMap" type="com.muses.taoshop.item.entity.ItemCategory" >
<id column="id" property="id" jdbcType="BIGINT" />
<result column="category_name" property="categoryName" jdbcType="VARCHAR" />
<result column="sjid" property="sjid" jdbcType="BIGINT" />
<result column="last_modify_time" property="lastModifyTime" jdbcType="TIMESTAMP" />
<result column="create_time" property="createTime" jdbcType="TIMESTAMP" />
</resultMap>
<sql id="BaseColumnList" >
id,
category_name as categoryName,
sjid,
last_modify_time as lastModifyTime,
create_time as createTime
</sql>
<!-- 獲取所有的商品品類資訊-->
<select id="listCategory" resultType="ItemCategory">
SELECT
<include refid="BaseColumnList" />
FROM item_category t
</select>
</mapper>
Mapper介面類:
package com.muses.taoshop.item.mapper;
import com.muses.taoshop.item.entity.ItemCategory;
import com.muses.taoshop.item.entity.ItemList;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
@Mapper
public interface ItemCategoryMapper {
List<ItemCategory> listCategory();
}
實體類:
這裡用了lombok的jar來實現,所有不用set和get方法
package com.muses.taoshop.item.entity;
import com.alibaba.fastjson.annotation.JSONField;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;
import javax.validation.constraints.NotNull;
import java.util.Date;
import java.util.List;
/**
* <pre>
* 商品品類
* </pre>
* @author nicky
* @version 1.00.00
* <pre>
* 修改記錄
* 修改後版本: 修改人: 修改日期: 2018.06.09 21:49 修改內容:
* </pre>
*/
@Data
public class ItemCategory {
/**
* 商品品類id
*/
private Long id;
/**
* 商品品類名稱
*/
private String categoryName;
/**
* 上級id
*/
private Long sjid;
/**
* 上次修改時間
*/
@JSONField(format ="yyyy-MM-dd HH:mm:ss")
private Date lastModifyTime;
/**
* 建立時間
*/
@JSONField(format ="yyyy-MM-dd HH:mm:ss")
private Date createTime;
/**
* 子選單
*/
private List<ItemCategory> subCategorys;
}
構建品類樹的工具類:
package com.muses.taoshop.util;
import com.muses.taoshop.item.entity.ItemCategory;
import javax.mail.FetchProfile;
import java.util.ArrayList;
import java.util.List;
/**
* <pre>
* 構造一棵品類樹
* </pre>
*
* @author nicky
* @version 1.00.00
* <pre>
* 修改記錄
* 修改後版本: 修改人: 修改日期: 2018.06.24 17:12 修改內容:
* </pre>
*/
public class CategoryTreeUtils {
public List<ItemCategory> commonCategorys;
public List<ItemCategory> list = new ArrayList<ItemCategory>();
public List<ItemCategory> buildCategoryTree(List<ItemCategory> categories ) {
this.commonCategorys = categories;
for (ItemCategory c : categories){
ItemCategory category = new ItemCategory();
if(c.getSjid() == 0){
category.setSjid(c.getSjid());
category.setId(c.getId());
category.setCategoryName(c.getCategoryName());
category.setSubCategorys(treeChild(c.getId()));
list.add(category);
}
}
return list;
}
public List<ItemCategory> treeChild(long id){
List<ItemCategory> list = new ArrayList<ItemCategory>();
for(ItemCategory c : commonCategorys){
ItemCategory category = new ItemCategory();
if(c.getSjid() == id){
category.setSjid(c.getSjid());
category.setId(c.getId());
category.setCategoryName(c.getCategoryName());
category.setSubCategorys(treeChild(c.getId()));//遞迴迴圈
list.add(category);
}
}
return list;
}
}
前端程式碼:
<div class="headerNav" xmlns:th="http://www.thymeleaf.org">
<div class="layout">
<dl class="all-brands">
<dt class="all-brands-head"> <a href="#">全部商品分類</a> </dt>
<dd class="all-brands-list">
<div class="wrap" th:each="c : ${categories}">
<div class="all-sort-list">
<div class="item bo">
<h3>
<a href="" th:text="${c.categoryName}"></a></h3>
<div class="item-list clearfix">
<div class="close">x</div>
<div class="subitem" th:each="s: ${c.subCategorys}">
<dl class="fore1">
<dt th:text="${s.categoryName}"><a th:href="@{'/portal/category/toCategoryList/'+${s.id}}"></a></dt>
<dd>
<em th:each="ss : ${s.subCategorys} "><a th:href="@{'/portal/category/toCategoryList/'+${ss.id}}" th:text="${ss.categoryName}"></a></em>
</dd>
</dl>
</div>
</div>
</div>
</div>
</div>
</dd>
</dl>
</div>
</div>
</div>
實現的效果如圖:可以說是3級聯動
這是在開發中的開源專案的一個小功能,原始碼已經開源,github連結