前面经历了漫长的准备阶段,包括各种环境搭建,前端语言学习,项目框架搭建等等。大家可回头参照 gulimall分布式商城(一)、gulimall分布式商城(二)结合视频进行学习。好了,不说骚话了,上干货:业务开发之商品服务。
说明:本文旨在分享学习经历,有错误的地方欢迎大家指出,本人会虚心接受。原创不易,不喜勿喷。
6、业务开发之商品服务
前面我们学习了很多基础知识,包括分布式组件的运用及调试,前端框架的基本知识。在这个模块中,你可以尽情的运用上述知识,让你有真人对战的感觉,而不是一直在单机。虽然此处应用还是青铜级的,和实际工作中的高端局有差异,但你可以忽略这些,暗示自己,这就是你刚开始工作要做的事,你把这些知识吃透了,找个工作糊口完全没问题。
因为内容实在太多,笔者也不可能每段代码都给大家复刻下来,尽量赶重点说吧,最后还是得自己动手敲。还是那句话,我的就是我的,你的也许还在幼儿园。哈哈哈,开个玩笑。
6.1、三级分类
6.1.1、查询-递归树形结构获取
1)、将代码中sql下的pms_catelog.sql内容复制粘贴到sqlyog,运行完成。
2)、在CategoryController中修改查询所有数据方法
/** * 查出所有分类以及子分类,以树形结构组装起来 */ @RequestMapping("/list/tree") public R listWithTree(){ List<CategoryEntity> entities = categoryService.listWithTree(); /* * 1)箭头函数categoryEntity -> categoryEntity.getParentCid() == 0, * 表示每个传入的categoryEntity,如果其父分类的id=0,则其为一个一级分类 ; * 2)collect(Collectors.toList())表示将所有一级分类收集成一个集合List * */ entities.stream().filter((categoryEntity) -> { return categoryEntity.getParentCid() == 0; }).collect(Collectors.toList()); return R.ok().put("data", entities); }
3)、在CategoryService中生成listWithTree()方法
List<CategoryEntity> listWithTree();
4)、在CategoryServiceImpl中实现该方法
@Override public List<CategoryEntity> listWithTree() { //1.显示所有分类,没有参数传入 List<CategoryEntity> entities = baseMapper.selectList(null); //2.组装成树形结构 //1)找到所有的一级分类 /* * 1)箭头函数categoryEntity -> categoryEntity.getParentCid() == 0, * 表示每个传入的categoryEntity,如果其父分类的id=0,则其为一个一级分类 ; * 2)map将当前菜单的子分类传入,返回所有的分类 * 3)stream():通过将集合转换为这么一种叫做 “流” 的元素序列, * 通过声明性方式,能够对集合中的每个元素进行一系列并行或串行的流水线操作 * 4)Java8及以上版本中,使用stream().filter(箭头函数)来过滤一个List对象,查找符合条件的对象集合 */ List<CategoryEntity> level1Menus = entities.stream().filter((categoryEntity) ->{ return categoryEntity.getParentCid() == 0; }).map((menu) -> { //getChildrens(menu,entities):查出当前菜单menu的所有子菜单 //将当前菜单的子分类保存进入菜单 menu.setChildren(getChildrens(menu,entities)); //返回当前菜单 return menu; }).sorted((menu1, menu2) -> { //return menu1.getSort() - menu2.getSort()因sort字段没有设置非空,可能会造成空指针异常,需做判定 //三目运算符menu1.getSort()==null?0:menu1.getSort()即如果为空,则默认给其赋值为0,不为空则等于其自身 return (menu1.getSort()==null?0:menu1.getSort()) - (menu2.getSort()==null?0:menu2.getSort()); }).collect(Collectors.toList()); //返回一级菜单 return level1Menus; } /** * @param root:表示当前菜单 * @param all:表示所有菜单 * @return */ //递归查找某一个菜单的子菜单 private List<CategoryEntity> getChildrens (CategoryEntity root, List < CategoryEntity > all){ //filter():过滤当前菜单 List<CategoryEntity> children = all.stream().filter((categoryEntity) -> { return categoryEntity.getParentCid() == root.getCatId(); }).map(categoryEntity -> { //将当前菜单的子分类保存进入菜单 categoryEntity.setChildren(getChildrens(categoryEntity,all)); return categoryEntity; //2.菜单的排序,传入当前菜单menu1和后一个菜单menu2 }).sorted((menu1,menu2)->{ //用第一个菜单的排序menu1.getSort()-后一个菜单的排序menu2.getSort() return (menu1.getSort()==null?0:menu1.getSort()) - (menu2.getSort()==null?0:menu2.getSort()); }).collect(Collectors.toList());//Collectors.toList()用来结束Stream流。 return children; }
5)、访问localhost:10000/product/category/list/tree,得到数据即可。
6.1.2、网关配置路由与路径重写
1)、启动renren-fast-vue、renren-fast项目,登录
2)、在系统管理-菜单管理中新建商品管理
3)、在菜单管理中新建分类维护
4)、vscode中view/modules中新建文件夹product,在product下新建Category.vue,使用模板生成组件(在逆向生成代码时有生成前端页面,可以直接拿来使用,这里前端代码就不一一敲了)
5)、修改static/config/index.js中api请求地址
// api接口请求地址 window.SITE_CONFIG['baseUrl'] = 'http://localhost:88/api';
6)、登录renrne-fast-vue项目报错,验证码不能显示
7)、在renren-fast项目application.yml中配
8)、在gulimall-gateway中配置网关路由
#将所有带/api/** 的请求都转到renren-fast/** - id: admin_route uri: lb://renren-fast predicates: - Path=/api/** filters: - RewritePath=/api/(?<segment>.*), /renren-fast/${segment}
9)、再次访问,验证码能正常显示。登录继续报错。到了这一步不要慌,这是因为网关没有配置跨域导致的,下一节我们进行设置,确保登录成功。
6.1.3、网关统一配置跨域
1)、关于什么跨域大家自己去看文档或者百度
2)、在gulimall-gateway中新建config包,创建GulimallCrosConfiguration
@Configuration public class GulimallCrosConfiguration { @Bean public CorsWebFilter corsWebFilter(){ UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); CorsConfiguration corsConfiguration = new CorsConfiguration(); corsConfiguration.addAllowedHeader("*"); corsConfiguration.addAllowedMethod("*"); corsConfiguration.addAllowedOrigin("*"); corsConfiguration.setAllowCredentials(true); source.registerCorsConfiguration("/**",corsConfiguration); // source.registerCorsConfiguration("/**",corsConfiguration); return new CorsWebFilter(source); } }
3)、设置好跨域后,重启访问,再次报错,如下:
4)、该错误是因为renren-fast项目自身也设置了跨域,我们将其注释即可。
5)、再次重启访问,这次OK