编写分类查询
實現商品分類查詢
商城的核心自然是商品,而商品多了以后,肯定要進行分類,并且不同的商品會有不同的品牌信息,我們需要依次去完成:商品分類、品牌、商品的開發。
導入數據
我們先看商品分類表:
CREATE TABLE `tb_category` (`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '類目id',`name` varchar(20) NOT NULL COMMENT '類目名稱',`parent_id` bigint(20) NOT NULL COMMENT '父類目id,頂級類目填0',`is_parent` tinyint(1) NOT NULL COMMENT '是否為父節點,0為否,1為是',`sort` int(4) NOT NULL COMMENT '排序指數,越小越靠前',PRIMARY KEY (`id`),KEY `key_parent_id` (`parent_id`) USING BTREE ) ENGINE=InnoDB AUTO_INCREMENT=1424 DEFAULT CHARSET=utf8 COMMENT='商品類目表,類目和商品(spu)是一對多關系,類目與品牌是多對多關系';因為商品分類會有層級關系,因此這里我們加入了parent_id字段,對本表中的其它分類進行自關聯。
實現功能
在瀏覽器頁面點擊“分類管理”菜單:
根據這個路由路徑到路由文件(src/route/index.js),可以定位到分類管理頁面:
由路由文件知,頁面是src/pages/item/Category.vue
商品分類使用了樹狀結構,而這種結構的組件vuetify并沒有為我們提供,這里自定義了一個樹狀組件。不要求實現或者查詢組件的實現,只要求可以參照文檔使用該組件即可:
url異步請求
點擊商品管理下的分類管理子菜單,在瀏覽器控制臺可以看到:
頁面中沒有,只是發起了一條請求:http://api.learn.com/api/item/category/list?pid=0
?
大家可能會覺得很奇怪,我們明明是使用的相對路徑:/item/category/list,講道理發起的請求地址應該是:
http://manage.learn.com/item/category/list
但實際卻是:
http://api.learn.com/api/item/category/list?pid=0
這是因為,我們有一個全局的配置文件,對所有的請求路徑進行了約定:
?
路徑是http://api.learn.com,并且默認加上了/api的前綴,這恰好與我們的網關設置匹配,我們只需要把地址改成網關的地址即可,因為我們使用了nginx反向代理,這里可以寫域名。
接下來,我們要做的事情就是編寫后臺接口,返回對應的數據即可。
實體類
在learn-item-interface中添加category實體類:
內容:
@Table(name="tb_category") public class Category {@Id@GeneratedValue(strategy=GenerationType.IDENTITY)private Long id;private String name;private Long parentId;private Boolean isParent; // 注意isParent生成的getter和setter方法需要手動加上Isprivate Integer sort;// getter和setter略 }需要注意的是,這里要用到jpa的注解,因此我們在learn-item-iterface中添加jpa依賴
<dependency><groupId>javax.persistence</groupId><artifactId>persistence-api</artifactId><version>1.0</version> </dependency>controller
編寫一個controller一般需要知道四個內容:
-
請求方式:決定我們用GetMapping還是PostMapping
-
請求路徑:決定映射路徑
-
請求參數:決定方法的參數
-
返回值結果:決定方法的返回值
在剛才頁面發起的請求中,我們就能得到絕大多數信息:
-
請求方式:Get,插敘肯定是get請求
-
請求路徑:/api/item/category/list。其中/api是網關前綴,/item是網關的路由映射,真實的路徑應該是/category/list
-
請求參數:pid=0,根據tree組件的說明,應該是父節點的id,第一次查詢為0,那就是查詢一級類目
-
返回結果:??
根據前面tree組件的用法我們知道,返回的應該是json數組:
-
對應的java類型可以是List集合,里面的元素就是類目對象了。也就是List<Category>
添加Controller:
controller代碼:
@Controller @RequestMapping("category") public class CategoryController {@Autowiredprivate CategoryService categoryService;/*** 根據父id查詢子節點* @param pid* @return*/@GetMapping("list")public ResponseEntity<List<Category>> queryCategoriesByPid(@RequestParam("pid") Long pid) {if (pid == null || pid.longValue() < 0) {// 響應400,相當于ResponseEntity.status(HttpStatus.BAD_REQUEST).build();return ResponseEntity.badRequest().build();}List<Category> categories = this.categoryService.queryCategoriesByPid(pid);if (CollectionUtils.isEmpty(categories)) {// 響應404return ResponseEntity.notFound().build();}return ResponseEntity.ok(categories);} }service
一般service層我們會定義接口和實現類,不過這里我們就偷懶一下,直接寫實現類了:
@Service public class CategoryService {@Autowiredprivate CategoryMapper categoryMapper;/*** 根據parentId查詢子類目* @param pid* @return*/public List<Category> queryCategoriesByPid(Long pid) {Category record = new Category();record.setParentId(pid);return this.categoryMapper.select(record);} }mapper
我們使用通用mapper來簡化開發:
public interface CategoryMapper extends Mapper<Category> { }要注意,我們并沒有在mapper接口上聲明@Mapper注解,那么mybatis如何才能找到接口呢?
我們在啟動類上添加一個掃描包功能:
@SpringBootApplication @EnableDiscoveryClient @MapperScan("com.learn.item.mapper") // mapper接口的包掃描 public class ItemServiceApplication {public static void main(String[] args) {SpringApplication.run(ItemServiceApplication.class, args);} }啟動并測試
我們不經過網關,直接訪問:http://localhost:8081/category/list
然后試試網關是否暢通:http://api.learn.com/api/item/category/list
一切OK!
然后刷新后臺管理頁面查看:
發現報錯了!
瀏覽器直接訪問沒事,但是這里卻報錯,什么原因?
這其實是瀏覽器的同源策略造成的跨域問題。
總結
- 上一篇: 使用域名访问后台页面
- 下一篇: 品牌查询后台代码