乐优商城(02)–商品分类
一、创建数据库
导入sql文件,运行之
得到以下数据表:
二、页面实现
2.1、url请求分析
找到页面Category.vue,目录路径为:src/pages/item/Category.vue
商品分类使用了树状结构,而这种结构的组件vuetify并没有提供,这里自定义了一个树状组件:
<template>
<v-card>
<v-flex xs12 sm10>
<v-tree url="/item/category/list"
:isEdit="isEdit"
@handleAdd="handleAdd"
@handleEdit="handleEdit"
@handleDelete="handleDelete"
@handleClick="handleClick"
/>
</v-flex>
</v-card>
</template>
修改url请求配置,按下图进行修改
点击商品管理下的分类管理子菜单,在浏览器控制台可以看到:
2.2、后台接口实现
-
在
leyou-item-iterface
导入依赖<dependency> <groupId>javax.persistence</groupId> <artifactId>persistence-api</artifactId> <version>1.0</version> </dependency>
-
实体类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方法需要手动加上Is private Integer sort; // getter和setter略 }
-
controller
编写一个controller一般需要知道四个内容:
- 请求方式:决定我们用GetMapping还是PostMapping
- 请求路径:决定映射路径
- 请求参数:决定方法的参数
- 返回值结果:决定方法的返回值
-
请求方式:Get
-
请求路径:/api/item/category/list。其中/api是网关前缀,/item是网关的路由映射,真实的路径应该是/category/list
-
请求参数:pid=0,根据tree组件的说明,应该是父节点的id,第一次查询为0,那就是查询一级类目
-
返回结果:json数组
@RestController @RequestMapping("/category") public class CategoryController { @Autowired private CategoryService categoryService; /** * 根据父节点 id查询商品类目 * @param pid * @return */ @GetMapping("/list") public ResponseEntity<List<Category>> queryCategoryByPid(@RequestParam("pid") Long pid){ //验证参数是否合法 if (null == pid || pid < 0){ //直接返回请求出错 return ResponseEntity.badRequest().build(); } List<Category> categories = this.categoryService.queryCategoryByPid(pid); if (CollectionUtils.isEmpty(categories)){ return ResponseEntity.notFound().build();//没有找到返回404 } return ResponseEntity.ok(categories); } }
-
service层
-
接口代码
/** * 分类业务层接口 */ public interface CategoryService { /** * 根据父节点 id查询商品类目 * @param pid * @return */ List<Category> queryCategoryByPid(Long pid); }
-
实现类代码
/** * 分类业务实现类 */ @Service public class CategoryServiceImpl implements CategoryService { @Autowired private CategoryMapper categoryMapper; /** * 根据父节点 id查询商品类目 * * @param pid * @return */ @Override public List<Category> queryCategoryByPid(Long pid) { Category category = new Category(); category.setParentId(pid); return this.categoryMapper.select(category); } }
-
-
mapper层代码
使用通用mapper简化开发
/** * category类的通用mapper */ public interface CategoryMapper extends Mapper<Category> { }
要注意,并没有在mapper接口上声明@Mapper注解,在启动类上添加一个扫描包功能:
@SpringBootApplication @EnableDiscoveryClient @MapperScan("com.leyou.item.mapper") //注意一定要选择tk.mybatis包的注解 public class LeyouItemApplication { public static void main(String[] args) { SpringApplication.run(LeyouItemApplication.class,args); } }
-
启动测试,记得启动nginx
-
不经过网关直接访问:http://localhost:8081/category/list?pid=0
-
经过网关测试:http://api.leyou.com/api/item/category/list?pid=0
-
后台管理页面查看,发现跨域问题
-
2.3、解决跨域问题
2.3.1、问题说明
跨域:浏览器对于javascript的同源策略的限制 。
以下情况都属于跨域:
跨域原因说明 | 示例 |
---|---|
域名不同 | www.jd.com 与 www.taobao.com |
域名相同,端口不同 | www.jd.com:8080 与 www.jd.com:8081 |
二级域名不同 | item.jd.com 与 miaosha.jd.com |
如果域名和端口都相同,但是请求路径不同,不属于跨域,如:
www.jd.com/item
www.jd.com/goods
http和https也属于跨域
而我们刚才是从manage.leyou.com
去访问api.leyou.com
,这属于二级域名不同,跨域了。
为什么有跨域问题?
跨域不一定都会有跨域问题。
因为跨域问题是浏览器对于ajax请求的一种安全限制:一个页面发起的ajax请求,只能是与当前页域名相同的路径,这能有效的阻止跨站攻击。
因此:跨域问题 是针对ajax的一种限制。
解决跨域问题的方案
-
Jsonp
最早的解决方案,利用script标签可以跨域的原理实现。
限制:
- 需要服务的支持
- 只能发起GET请求
-
nginx反向代理
思路是:利用nginx把跨域反向代理为不跨域,支持各种请求方式
缺点:需要在nginx进行额外配置,语义不清晰
-
CORS
规范化的跨域请求解决方案,安全可靠。
优势:
- 在服务端进行控制是否允许跨域,可自定义规则
- 支持各种请求方式
缺点:
- 会产生额外的请求
CORS解决跨域
CORS是一个W3C标准,全称是"跨域资源共享"(Cross-origin resource sharing)。
它允许浏览器向跨源服务器,发出XM