黑马淘淘商城第四天 前台系统搭建、商城首页展示、Cms系统的实现、前台内容动态展示

    技术2022-07-17  84

    1. 课程计划

    第四天: 1、前台系统搭建 2、商城首页展示 3、Cms系统的实现 a) 内容分类管理 b) 内容管理 4、前台内容动态展示

    2. 商城首页展示

    系统架构: 页面位置:

    2.1. 工程搭建

    可以参考taotao-manager-web工程搭建

    2.2. 功能分析

    请求的url:/index Web.xml中的欢迎页配置: 参数:没有 返回值:String 逻辑视图 1:首页展示步骤

    @Controller public class IndexController { @RequestMapping("/index") public String showIndex() { return "index"; } }

    web.xml(伪静态,方便搜索引擎检索) 当访问http://localhost:8082/item 返回状态码406 后台异常如下,why? 2:讨论 控制器如下:

    @RequestMapping("/item") @ResponseBody public TaotaoResult result(){ return TaotaoResult.ok(); }

    3:总结: 让dispacherServlet拦截所有的请求,要做伪静态,只需要在 @ RequestMapping (“/item.html”)

    3. 首页动态展示分析

    内容信息要从数据库中获得

    3.1. 动态展示分析 商城首页动态展示分析. 1:需求分析 分析并找出首页页面内容的规律: 1:每一块内容都有一个树形分类 2:每一个叶子节点都有相关具体内容 3:每一个具体内容的属性一般包含(标题、副标题、url、……) 2:数据表分析 根据上面分析数据表设计如下: 1:tb_content_category 管理树形分类 2: tb_content管理具体内容(字段是不确定的,初始可以给些通用字段如标题等) 通过欢迎页显示首页 当你在浏览器只输入http://localhost:8080/项目名 (当然如果在webapps中你的项目名为ROOT,你可以直接访问http://localhost:8080/) 这两种访找欢迎页面,一般先去找里面的文件问方式,都没有去请求具体的内容,都是为了 文件后缀分两种: 1:.jsp 不会经过dispatcherServlet, 找到就显示 找不到404 2:非.jsp 例如login.html 要经过dispatcherServlet, dispatcherServlet能接收,走dispatcherServlet,不能接收找login.html,找不到就报404 总结:如果首页是静态页面就不走dispatcherServlet 如果是动态的,必须走dispatcherServlet,这时候把index.jsp藏到WEB-INF里面

    1、内容需要进行分类 2、分类下有子分类,需要动态管理。 3、分类下有内容列表 4、单点的内容信息 a) 有图片 b) 有链接 c) 有标题 d) 有价格 e) 包含大文本类型,可以作为公告

    需要一个内容分类表和一个内容表。内容分类和内容表是一对多的关系。 内容分类表,需要存储树形结构的数据。 内容分类表:tb_content_category 内容表:tb_content

    需要有后台来维护内容信息。Cms系统。 需要创建一个内容服务系统。可以参考taotao-manager创建。 Taotao-content:聚合工程打包方式pom |–taotao-content-interface jar |–taotao-content-Service war

    4. 内容服务系统创建

    4.1. Taotao-content 4.1.1. Pom文件

    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>com.taotao</groupId> <artifactId>taotao-parent</artifactId> <version>0.0.1-SNAPSHOT</version> </parent> <groupId>com.taotao</groupId> <artifactId>taotao-content</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>pom</packaging> <dependencies> <dependency> <groupId>com.taotao</groupId> <artifactId>taotao-common</artifactId> <version>0.0.1-SNAPSHOT</version> </dependency> </dependencies> <!-- 配置tomcat插件 --> <build> <plugins> <plugin> <groupId>org.apache.tomcat.maven</groupId> <artifactId>tomcat7-maven-plugin</artifactId> <configuration> <port>8083</port> <path>/</path> </configuration> </plugin> </plugins> </build> </project>

    4.2. taotao-content-interface 4.2.1. Pom文件

    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>com.taotao</groupId> <artifactId>taotao-content</artifactId> <version>0.0.1-SNAPSHOT</version> </parent> <artifactId>taotao-content-interface</artifactId> <dependencies> <dependency> <groupId>com.taotao</groupId> <artifactId>taotao-manager-pojo</artifactId> <version>0.0.1-SNAPSHOT</version> </dependency> </dependencies> </project>

    4.3. taotao-content-service 4.3.1. Pom文件

    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>com.taotao</groupId> <artifactId>taotao-content</artifactId> <version>0.0.1-SNAPSHOT</version> </parent> <artifactId>taotao-content-service</artifactId> <packaging>war</packaging> <dependencies> <dependency> <groupId>com.taotao</groupId> <artifactId>taotao-manager-dao</artifactId> <version>0.0.1-SNAPSHOT</version> </dependency> <dependency> <groupId>com.taotao</groupId> <artifactId>taotao-content-interface</artifactId> <version>0.0.1-SNAPSHOT</version> </dependency> <!-- spring的依赖 --> <!-- Spring --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-beans</artifactId> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-aspects</artifactId> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jms</artifactId> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context-support</artifactId> </dependency> <!-- dubbo相关 --> <dependency> <groupId>com.alibaba</groupId> <artifactId>dubbo</artifactId> <!-- 排除依赖 --> <exclusions> <exclusion> <groupId>org.springframework</groupId> <artifactId>spring</artifactId> </exclusion> <exclusion> <groupId>org.jboss.netty</groupId> <artifactId>netty</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>org.apache.zookeeper</groupId> <artifactId>zookeeper</artifactId> </dependency> <dependency> <groupId>com.github.sgroschupf</groupId> <artifactId>zkclient</artifactId> </dependency> </dependencies> </project>

    4.4. 框架整合 参考taotao-manager

    5. Cms系统实现

    5.1. 内容分类管理 5.1.1. 展示内容分类 功能分析 请求的url:/content/category/list 请求的参数:id,当前节点的id。第一次请求是没有参数,需要给默认值“0” 响应数据:List(@ResponseBody) Json数据。 [{id:1,text:节点名称,state:open(closed)}, {id:2,text:节点名称2,state:open(closed)}, {id:3,text:节点名称3,state:open(closed)}] 业务逻辑: 1、取查询参数id,parentId 2、根据parentId查询tb_content_category,查询子节点列表。 3、得到List 4、把列表转换成List

    Dao层 使用逆向工程

    Service 参数:long parentId 返回值:List

    @Service public class ContentCategoryServiceImpl implements ContentCategoryService { @Autowired private TbContentCategoryMapper contentCategoryMapper; @Override public List<EasyUITreeNode> getContentCategoryList(long parentId) { // 1、取查询参数id,parentId // 2、根据parentId查询tb_content_category,查询子节点列表。 TbContentCategoryExample example = new TbContentCategoryExample(); //设置查询条件 Criteria criteria = example.createCriteria(); criteria.andParentIdEqualTo(parentId); //执行查询 // 3、得到List<TbContentCategory> List<TbContentCategory> list = contentCategoryMapper.selectByExample(example); // 4、把列表转换成List<EasyUITreeNode>ub List<EasyUITreeNode> resultList = new ArrayList<>(); for (TbContentCategory tbContentCategory : list) { EasyUITreeNode node = new EasyUITreeNode(); node.setId(tbContentCategory.getId()); node.setText(tbContentCategory.getName()); node.setState(tbContentCategory.getIsParent()?"closed":"open"); //添加到列表 resultList.add(node); } return resultList; } }

    发布服务

    注意1:这是一个新进程端口要改 2 : ref类名首字母小写 3:添加taotao-content-interface依赖

    表现层

    引用服务

    Taotao-manager-web 依赖taotao-content-interface模块 Controller

    @Controller @RequestMapping("/content/category") public class ContentCategoryController { @Autowired private ContentCategoryService contentCategoryService; @RequestMapping("/list") @ResponseBody public List<EasyUITreeNode> getContentCatList( @RequestParam(value="id", defaultValue="0") Long parentId) { List<EasyUITreeNode> list = contentCategoryService.getContentCategoryList(parentId); return list; } } .商品上传图片异常问题.avi A: taotao-manager-web中新增商品上传图片异常问题补充说明 在新增商品上传图片过度的时候,由于超过了数据库image字段最大限制: 所以,当超过最大限制的时候,再插入就会发生如下异常: 解决方式: 1>数据增大该字段; 2>页面限制上传图片数量;(推荐) 怎么限制?

    5.1.2. 新增节点 功能分析 请求的url:/content/category/create 请求的参数: Long parentId String name 响应的结果: json数据,TaotaoResult,其中包含一个对象,对象有id属性,新生产的内容分类id 业务逻辑: 1、接收两个参数:parentId、name 2、向tb_content_category表中插入数据。 a) 创建一个TbContentCategory对象 b) 补全TbContentCategory对象的属性 c) 向tb_content_category表中插入数据 3、判断父节点的isparent是否为true,不是true需要改为true。 4、需要主键返回。 5、返回TaotaoResult,其中包装TbContentCategory对象

    Dao层 可以使用逆向工程。 需要添加主键返回: 注意:修改完代码后,需要向本地仓库安装taotao-manager-dao包 Service层 参数:parentId、name 返回值:返回TaotaoResult,其中包装TbContentCategory对象

    @Override public TaotaoResult addContentCategory(long parentId, String name) { // 1、接收两个参数:parentId、name // 2、向tb_content_category表中插入数据。 // a)创建一个TbContentCategory对象 TbContentCategory tbContentCategory = new TbContentCategory(); // b)补全TbContentCategory对象的属性 tbContentCategory.setIsParent(false); tbContentCategory.setName(name); tbContentCategory.setParentId(parentId); //排列序号,表示同级类目的展现次序,如数值相等则按名称次序排列。取值范围:大于零的整数 tbContentCategory.setSortOrder(1); //状态。可选值:1(正常),2(删除) tbContentCategory.setStatus(1); tbContentCategory.setCreated(new Date()); tbContentCategory.setUpdated(new Date()); // c)向tb_content_category表中插入数据 contentCategoryMapper.insert(tbContentCategory); // 3、判断父节点的isparent是否为true,不是true需要改为true。 TbContentCategory parentNode = contentCategoryMapper.selectByPrimaryKey(parentId); if (!parentNode.getIsParent()) { parentNode.setIsParent(true); //更新父节点 contentCategoryMapper.updateByPrimaryKey(parentNode); } // 4、需要主键返回。 // 5、返回TaotaoResult,其中包装TbContentCategory对象 return TaotaoResult.ok(tbContentCategory); }

    表现层 请求的url:/content/category/create 请求的参数: Long parentId String name 响应的结果: json数据,TaotaoResult

    @RequestMapping("/create") @ResponseBody public TaotaoResult createCategory(Long parentId, String name) { TaotaoResult result = contentCategoryService.addContentCategory(parentId, name); return result; }

    5.1.3. 内容分类重命名、删除 重命名 请求的url:/content/category/update 参数:id,当前节点id。name,重命名后的名称。 业务逻辑:根据id更新记录。 返回值:返回TaotaoResult.ok()

    作业。 (1)在taotao-content-interface定义接口,在taotao-content-service中实现接口

    public TaotaoResult updateContentCategory(long nodeId, String updateName) { TbContentCategory tbContentCategory=new TbContentCategory(); tbContentCategory.setId(nodeId); tbContentCategory.setName(updateName); contentCategoryMapper.updateByPrimaryKeySelective(tbContentCategory); return TaotaoResult.ok(tbContentCategory); }

    (2)在taotao-manager-web中创建响应修改节点名称请求方法

    /** * 修改指定节点 * * @param id 父节点id * @param name 要插入节点节点名称 * @return TaotaoResult */ @RequestMapping("/content/category/update") @ResponseBody public TaotaoResult renameCategoryNode(Long id, String name) { return contentCategoryService.updateContentCategory(id, name); }

    删除节点 请求的url:/content/category/delete/ 参数:id,当前节点的id。 响应的数据:json。TaotaoResult。 业务逻辑: 1、根据id删除记录。 2、判断父节点下是否还有子节点,如果没有需要把父节点的isparent改为false 3、如果删除的是父节点,子节点要级联删除。 两种解决方案: 1)如果判断是父节点不允许删除。 2)递归删除。 作业。 B: 内容分类删除操作 (1) 在taotao-content-interface定义接口,在taotao-content-service中实现接口

    public TaotaoResult deleteContentCategory(long nodeId) { //如果删除的节点没有同辈节点,那么它的父节点此时就变成了叶子节点了,需要设置isParent为false TbContentCategory deletedNode = contentCategoryMapper.selectByPrimaryKey(nodeId); Long parentId = deletedNode.getParentId(); //递归删除删除所有节点 deleteNodeRecursion(nodeId); List<TbContentCategory> queryAllChildrenNode = queryContentCategoryByParentId(parentId); if(queryAllChildrenNode.isEmpty()){ TbContentCategory updatedParentNode=new TbContentCategory(); updatedParentNode.setId(parentId); updatedParentNode.setIsParent(false); contentCategoryMapper.updateByPrimaryKey(updatedParentNode); } return TaotaoResult.ok(null); } /** * 递归删除所有子节点 * @param nodeId * @return */ public void deleteNodeRecursion(long nodeId){ //查询出该节点下所有子节点,判断该节点下所有子节点是否为空 List<TbContentCategory> queryAllChildrenNode = queryContentCategoryByParentId(nodeId); for (TbContentCategory tbContentCategory : queryAllChildrenNode) { deleteNodeRecursion(tbContentCategory.getId()); } //如果是叶子节点就删除该节点 contentCategoryMapper.deleteByPrimaryKey(nodeId); } /** * 查询出所有指定节点下面的所有子节点 * @param nodeId * @return */ private List<TbContentCategory> queryContentCategoryByParentId(long nodeId){ TbContentCategoryExample contentCategoryExample=new TbContentCategoryExample(); Criteria criteria = contentCategoryExample.createCriteria(); criteria.andParentIdEqualTo(nodeId); return contentCategoryMapper.selectByExample(contentCategoryExample); }

    5.2. 内容管理 5.2.1. 功能点分析 1、内容列表查询(作业) 2、新增内容 3、编辑内容(作业) 4、删除内容(作业)

    5.2.2. 内容列表查询 请求的url:/content/query/list 参数:categoryId 分类id 响应的数据:json数据 {total:查询结果总数量,rows[{id:1,title:aaa,subtitle:bb,…}]} EasyUIDataGridResult 描述商品数据List 查询的表:tb_content 业务逻辑: 根据内容分类id查询内容列表。要进行分页处理。

    5.2.3. 新增内容 功能分析 新增内容,必须指定一个内容分类。 提交表单请求的url:/content/save 参数:表单的数据。使用pojo接收TbContent 返回值:TaotaoResult(json数据) 业务逻辑: 1、把TbContent对象属性补全。 2、向tb_content表中插入数据。 3、返回TaotaoResult

    Dao 逆向工程

    Service 参数:TbContent 返回值:TaotaoResult

    @Service public class ContentServiceImpl implements ContentService { @Autowired private TbContentMapper contentMapper; @Override public TaotaoResult addContent(TbContent content) { //补全属性 content.setCreated(new Date()); content.setUpdated(new Date()); //插入数据 contentMapper.insert(content); return TaotaoResult.ok(); } }

    发布服务 引用服务 Toatao-manager-web工程中引用。

    Controller

    提交表单请求的url:/content/save 参数:表单的数据。使用pojo接收TbContent 返回值:TaotaoResult(json数据)

    @Controller public class ContentController { @Autowired private ContentService contentService; @RequestMapping("/content/save") @ResponseBody public TaotaoResult addContent(TbContent content) { TaotaoResult result = contentService.addContent(content); return result; } }

    6. 首页轮播图展示

    Taotao-portal-web工程中,动态展示内容信息。

    6.1. 功能分析

    只需要动态生成一个json数据,轮播图就可以动态展示: Json数据格式:

    [ { "srcB": "http://image.taotao.com/images/2015/03/03/2015030304360302109345.jpg", "height": 240, "alt": "", "width": 670, "src": "http://image.taotao.com/images/2015/03/03/2015030304360302109345.jpg", "widthB": 550, "href": "http://sale.jd.com/act/e0FMkuDhJz35CNt.html?cpdad=1DLSUE", "heightB": 240 } ]

    从tb_content表中取数据,根据内容分类id查询列表。内容分类id固定,需要配置在属性文件中。 List 图片的width、height配置在属性文件中。 Alt属性从title中取。 Src->pic srcB->pic2 Href->url

    需要创建一个pojo转换成页面需要的json数据格式。

    public class Ad1Node { private String srcB; private String height; private String alt; private String width; private String src; private String widthB; private String href; private String heightB; }

    6.2. Dao层

    从tb_content表中取数据,根据内容分类id查询列表。 可以使用逆向工程

    6.3. Service层 参数:long categoryId 返回值:List

    @Override public List<TbContent> getContentList(long cid) { //根据cid查询内容列表 TbContentExample example = new TbContentExample(); //设置查询条件 Criteria criteria = example.createCriteria(); criteria.andCategoryIdEqualTo(cid); //执行查询 List<TbContent> list = contentMapper.selectByExample(example); return list; }

    发布服务 6.4. 表现层 Taotao-portal-web中实现。 6.4.1. 引用服务 .在taotao-portal-web中修改resource.properties文件 #home page advertisement AD1_CONTENT_CID=89 AD1_WIDTH=670 AD1_WIDTH_B=550 AD1_HEIGHT=240 AD1_HEIGHT_B=240

    6.4.2. Controller 在首页展示之前,对数据进行处理,然后展示首页,需要在IndexController中实现。

    @Controller public class IndexController { @Autowired private ContentService contentService; @Value("${AD1_CID}") private Long AD1_CID; @Value("${AD1_HEIGHT}") private Integer AD1_HEIGHT; @Value("${AD1_WIDTH}") private Integer AD1_WIDTH; @Value("${AD1_HEIGHT_B}") private Integer AD1_HEIGHT_B; @Value("${AD1_WIDTH_B}") private Integer AD1_WIDTH_B; @RequestMapping("/index") public String showIndex(Model model) { //取轮播图的内容信息 List<TbContent> contentList = contentService.getContentList(AD1_CID); //转换成Ad1NodeList List<Ad1Node> ad1List = new ArrayList<>(); for (TbContent tbContent : contentList) { Ad1Node node = new Ad1Node(); node.setAlt(tbContent.getTitle()); node.setHeight(AD1_HEIGHT); node.setHeightB(AD1_HEIGHT_B); node.setWidth(AD1_WIDTH); node.setWidthB(AD1_WIDTH_B); node.setHref(tbContent.getUrl()); node.setSrc(tbContent.getPic()); node.setSrcB(tbContent.getPic2()); //添加到列表 ad1List.add(node); } //把数据传递给页面。 model.addAttribute("ad1", JsonUtils.objectToJson(ad1List)); return "index"; } }
    Processed: 0.019, SQL: 9