淘淘商城——day5(首页大广告位的实现)

一  课程计划

首页大广告位的实现。java

     cms系统的实现:在后台管理内容及内容分类的系统就叫作cms系统node

      发布服务nginx

    调用服务展现内容web

二 首页大广告位实现

首页的内容须要动态管理,须要后台管理功能。spring

抽取首页展现内容的共性:数据库

  1. 有一张图片
  2. 有一个连接
  3. 有一个标题
  4. 有连接的提示
  5. 价格

须要把内容进行分类,分类应该是一个树形结构。apache

在展现首页时,能够根据分类取内容信息,把内容展现到页面。编程

在后台管理内容及内容分类的系统就叫作cms系统json

三  CMS系统(内容管理系统)跨域

须要先实现内容的分类管理,再实现内容管理。

3.一、内容分类管理

3.1.一、需求分析

初始化树形视图的

     url:/content/category/list

     参数是id,当前节点id属性,应该根据此id查询子节点列表。

     返回值:包含id、text、state三个属性的json数据列表

3.1.二、Dao层

表结构:

Sql语句:

根据parentid查询节点列表

SELECT * FROM `tb_content_category` WHERE parent_id = 30;

单表查询能够实现逆向工程生成的代码。

3.1.三、Service层

功能:接收parentid。根据parentid查询节点列表,返回返回一个EasyUI异步Tree要求的节点列表。每一个节点包含三个属性id、text、state三个属性。可使用EUTreeNode实体类。

参数:id

返回值:List<EUTreeNode>

package com.taotao.service.impl;

import java.util.ArrayList;
import java.util.List;

import javax.annotation.Resource;

import org.springframework.stereotype.Service;

import com.taotao.mapper.TbContentCategoryMapper;
import com.taotao.pojo.EUTreeNode;
import com.taotao.pojo.TbContentCategory;
import com.taotao.pojo.TbContentCategoryExample;
import com.taotao.pojo.TbContentCategoryExample.Criteria;
import com.taotao.service.ContentCategoryService;
@Service
public class ContentCategoryServiceImpl implements ContentCategoryService {
	//关联dao
	@Resource
	private TbContentCategoryMapper contentCategoryMapper ;

	/*
	 * 功能:接收parentid。根据parentid查询节点列表,返回返回一个EasyUI异步Tree要求的节点列表。
	 *     每一个节点包含三个属性id、text、state三个属性。可使用EUTreeNode实体类。
	 * 参数:id   返回值:List<EUTreeNode>
	 */

	@Override
	public List<EUTreeNode> getCategoryList(Long parentid) {
		//根据parentid 查询节点列表
		TbContentCategoryExample example = new TbContentCategoryExample();
		Criteria criteria = example.createCriteria();
		//设置条件
		criteria.andParentIdEqualTo(parentid);
		//执行查询
		List<TbContentCategory> list = contentCategoryMapper.selectByExample(example);
		//建立目录树
		ArrayList<EUTreeNode> resultList = new ArrayList<>();
		//遍历
		for (TbContentCategory tbContentCategory : list) {
			//建立一个TreeNode对象
			/*
			 * EUTreeNode node = new EUTreeNode(); node.setId(tbContentCategory.getId());
			 * node.setText(tbContentCategory.getName());
			 * node.setState(tbContentCategory.getIsParent()?"closed":"open");
			 */			
			EUTreeNode node = new EUTreeNode(tbContentCategory.getId(),tbContentCategory.getName(),tbContentCategory.getIsParent()?"closed":"open");
			resultList.add(node);
		}
				
		return resultList;
	}
	

}

3.1.四、Controller层

接收页面传递过来的parentid,根据parentid查询节点列表。返回List<EUTreeNode>。须要响应json数据。

package com.taotao.controller;

import java.util.List;

import javax.annotation.Resource;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import com.taotao.pojo.EUTreeNode;
import com.taotao.service.ContentCategoryService;

@Controller
@RequestMapping("/content/category/")
public class ContentCategoryController {
	@Resource
	private ContentCategoryService contentCategoryService ;
	
	@RequestMapping("/list")
	@ResponseBody
	public List<EUTreeNode> getCategoryList(@RequestParam(value="id",defaultValue="0")Long parentId){
		return contentCategoryService.getCategoryList(parentId);
	}
	
}

3.1.5 效果图

3.二、添加内容分类

3.2.一、需求分析

请求的url:/content/category/create

参数:

一、parentId父节点id

二、name:当前节点的名称

返回值:TaotaoResult。其中包含节点pojo对象。

3.2.二、Dao层

可使用逆向工程的代码

3.2.三、Service层

功能:接收两个参数parentId父节点id、name:当前节点的名称。向tb_content_category表中添加一条记录。返回TaoTaoResult包含记录的pojo对象。

须要返回主键信息:

    须要修改mapper文件,返回主键信息。

/*
	 * 二 添加内容分类
	 * 功能:接收两个参数parentId父节点id、  name:当前节点的名称。
	 *     向tb_content_category表中添加一条记录。返回TaoTaoResult包含记录的pojo对象。
	 *     须要返回主键信息:  须要修改mapper文件,返回主键信息。
	 * 
	 */

    @Override
	public TaotaoResult insertContentCategory(Long parentId, String name) {
	//建立一个pojo  
	//设置内容分类表中的信息
		TbContentCategory contentCategory = new TbContentCategory();
		contentCategory.setIsParent(false);//'该类目是否为父类目,1为true,0为false',
		contentCategory.setName(name);
		contentCategory.setStatus(1);	// '状态。可选值:1(正常),2(删除)',
		contentCategory.setParentId(parentId);
		contentCategory.setSortOrder(1);//'排列序号,表示同级类目的展示次序,如数值相等,则按名称次序排列
		contentCategory.setCreated(new Date());
		contentCategory.setUpdated(new Date());
		//将补全后的数据插入到数据库
		contentCategoryMapper.insert(contentCategory);
		//int insert = contentCategoryMapper.insert(contentCategory);
		//System.out.println("---------------------"+insert);
		//查看父节点的isParent列是否为true,若是不是的话改成true
		TbContentCategory parentCat = contentCategoryMapper.selectByPrimaryKey(parentId);
		//判断是否为true
		if (!parentCat.getIsParent()) {
			parentCat.setIsParent(true);
			//更新父节点
			contentCategoryMapper.updateByPrimaryKey(parentCat);
		}
		return TaotaoResult.ok(contentCategory.getId());//返回主键信息
	}

3.2.四、Controller层

    接收两个参数parentid、name。调用Service添加记录。返回TaotaoResult。应该返回json数据。

/*
	 * 添加内容分类
	 * 接收两个参数parentid、name。调用Service添加记录。返回TaotaoResult。应该返回json数据。
	 */
	@RequestMapping("create")
	public TaotaoResult insertContentCategory(Long parentId,String  name) {
	    TaotaoResult result=contentCategoryService.insertContentCategory(parentId, name);
	     return result;
	}

3.2.5 效果

3.三、删除

3.3.一、分析

需求分析:

  请求的url:/content/category/delete/

参数:

      1  parentId

      2  Id

返回值:没有返回值,随便返回一个便可。TaotaoResult

业务逻辑:

     接收parentid、id两个参数。删除id对应的记录。须要判断parentid对应的记录下是否有子节点。若是没有子节点。须要把parentid对应的记录的isparent改为false。

注意:删除,直接是物理删除。

3.四、重名名节点

一、使节点变为可编辑状态

二、当编辑完成后会触发onAfterEdit事件

请求的url:/content/category/update

参数:idname

返回值:没有返回值,能够返回TaotaoResult。Json格式

业务逻辑:根据id更新记录的name列便可

3.二、内容管理

内容管理表:

3.2.一、内容列表

需求分析

    请求url:/content/query/list

    参数:page、rows、categoryId

返回值:

    EUDataGridResult

   Total、rows:内容pojo列表。

业务逻辑:

     根据内容分类id查询内容列表。须要实现分页。返回EUDataGridResult

3.2.二、内容添加

分析

图片上传初始化:

内容表单提交:

请求的url:/content/save

请求的方法:post

请求内容:表单中的内容。

返回的结果:TaotaoResult。

3.2.三、Dao层

向tb_content表中插入数据,使用逆向工程代码

3.2.四、Service层

接收表tb_content对应的pojo对象。把pojo对象插入到tb_content表中。返回TaotaoResult。

package com.taotao.service.impl;

import java.util.Date;

import javax.annotation.Resource;

import org.springframework.stereotype.Service;


import com.taotao.mapper.TbContentMapper;
import com.taotao.pojo.TaotaoResult;
import com.taotao.pojo.TbContent;
import com.taotao.service.ContentService;
@Service
public class ContentServiceImpl implements ContentService {

	@Resource
	private TbContentMapper contentMapper;
	
	/*
	 * 内容添加:
	 *     接收表tb_content对应的pojo对象。把pojo对象插入到tb_content表中。返回TaotaoResult。
	 * 	( 接收tb_content对象调用Mapper,补全实体类须要的数据       向tb_content表中添加数据,返回TaoTaoResult)
	 */
	@Override
	public TaotaoResult insertContent(TbContent content) {
		//补全pojo内容
		content.setCreated(new Date());
		content.setUpdated(new Date());
		//将修改后的数据插入到数据库
		contentMapper.insert(content);
		return TaotaoResult.ok();
	}
	
}

3.2.五、Controller层

      接收表单中的内容,使用pojo接收。要求pojo的属性要和表单中的name一致。调用Service插入内容信息。返回TaotaoResult。Json格式的数据。

package com.taotao.controller;

import javax.annotation.Resource;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import com.taotao.pojo.TaotaoResult;
import com.taotao.pojo.TbContent;
import com.taotao.service.ContentService;

@Controller
@RequestMapping("/content")
public class ContentController {
	
	
	@Resource
	private ContentService contentService;
	
	/*
	 * 添加内容
	 *   接收表单中的内容,使用pojo接收。要求pojo的属性要和表单中的name一致
	 *   。调用Service插入内容信息。返回TaotaoResult。Json格式的数据。
	 * 
	 */
	@RequestMapping("/save")
	@ResponseBody
	public TaotaoResult insertContent(TbContent content) {		
		return contentService.insertContent(content);
	}
	
	
}

3.2.6 效果展现

   先开启nginx,才能进行http服务,在游览器上上传访问图片

四 展现首页大广告位

4.一、首页大广告位方案

4.1.一、方案一

jsonp跨域请求

        须要当首页加载完毕后,大广告位就应该显示。没有触发事件。不是太合适。

优势:不须要二次请求,页面直接加载内容数据。减小门户系统的压力。

缺点:须要延迟加载。不利于seo优化。

4.1.二、方案二(咱们使用的方法)

优势:有利于seo优化。能够在taotao-portal中对数据进行加工。

缺点:系统直接须要调用服务查询内容信息。多了一次http请求。

      系统直接服务的调用,须要使用  httpclient(系统之间进行交互)来实现。Taotao-portal和taotao-rest是在同一个局域网内部。速度很是快,调用时间能够忽略不计。

展现首页内容功能,使用方案二实现。

4.二、展现流程

4.三、内容服务发布

4.3.一、需求分析

    根据内容的分类id查询内容列表,从tb_content表中查询。服务是一个restFul形式的服务。使用http协议传递json格式的数据。

4.3.二、Dao层

从tb_content表中查询,根据内容分类id查询。是单表查询。可使用逆向工程生成的代码。

4.3.三、Service层

    在rest项目中建立

接收内容分类id,根据分类id查询分类列表。返回一个内容pojo列表。

参数:分类id

返回值:pojo列表

package com.taotao.rest.service.impl;

import java.util.List;

import javax.annotation.Resource;

import org.springframework.stereotype.Service;

import com.taotao.mapper.TbContentMapper;
import com.taotao.pojo.TbContent;
import com.taotao.pojo.TbContentExample;
import com.taotao.pojo.TbContentExample.Criteria;
import com.taotao.rest.service.ContentService;
@Service
public class ContentServiceImpl implements ContentService {
	
	@Resource
	private TbContentMapper contentMapper;

	/*
	 * 查询内容列表:
	 *    接收内容分类id,根据分类id查询分类列表。返回一个内容pojo列表。
	 *    参数:分类id 返回值:pojo列表
	 */
	
	@Override
	public List<TbContent> getContentList(Long contentCid) {
		//根据内容分类id查询内容列表
		TbContentExample example = new TbContentExample();
		//设置条件
		Criteria criteria = example.createCriteria();
		criteria.andCategoryIdEqualTo(contentCid);
		//执行查询
		List<TbContent> list = contentMapper.selectByExample(example);		
		return list;
	}
}

4.3.四、Controller层

     发布服务。接收查询参数。Restful风格内容分类id应该从url中取。

/rest/content/list/{contentCategoryId}

    从url中取内容分类id,调用Service查询内容列表。返回内容列表。返回一个json格式的数据。可使用TaotaoResult包装此列表。

package com.taotao.rest.controller;

import java.util.List;

import javax.annotation.Resource;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import com.taotao.pojo.TaotaoResult;
import com.taotao.pojo.TbContent;
import com.taotao.rest.service.ContentService;
import com.taotao.util.ExceptionUtil;

@Controller
@RequestMapping("/content")
public class ContentController {
	@Resource
	private ContentService contentService;
	
	
	/*
	 * 发布服务。接收查询参数。Restful风格内容分类id应该从url中取。 
	 * /rest/content/list/{contentCategoryId}
	 * 从url中取内容分类id,调用Service查询内容列表。返回内容列表。返回一个json格式的数据。
	 * 可使用TaotaoResult包装此列表。
	 */
	
	@RequestMapping("/list/{contentCategoryId}")
	@ResponseBody
	public TaotaoResult getConTentList(@PathVariable Long contentCategoryId) {
		try {
			List<TbContent> list = contentService.getContentList(contentCategoryId);
			return TaotaoResult.ok(list);
		} catch (Exception e) {
			e.printStackTrace();
			return TaotaoResult.build(500, ExceptionUtil.getStackTrace(e));
		
		}
		
	}
	
}

ExceptionUtil  工具类

package com.taotao.util;

import java.io.PrintWriter;
import java.io.StringWriter;

public class ExceptionUtil {

	/**
	 * 获取异常的堆栈信息
	 * 
	 * @param t
	 * @return
	 */
	public static String getStackTrace(Throwable t) {
		StringWriter sw = new StringWriter();
		PrintWriter pw = new PrintWriter(sw);

		try {
			t.printStackTrace(pw);
			return sw.toString();
		} finally {
			pw.close();
		}
	}
}

4.3.五、测试

咱们可使用工具测试

http://localhost:8081/rest/content/list/89

 

4.四、Httpclient的使用

4.4.一、什么是httpclient

      HttpClient 是 Apache Jakarta Common 下的子项目,用来提供高效的、最新的、功能丰富的支持 HTTP 协议的客户端编程工具包,而且它支持 HTTP 协议最新的版本和建议。
下载地址:http://hc.apache.org/

4.4.二、添加依赖

须要把httpclient的jar包添加到工程中。只须要在工程中添加httpclient的依赖。

4.4.三、使用httpclient执行get请求(无参数)

package com.taotao.test;

import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.junit.Test;


public class Test1 {
	
	@Test
	public void doGet() throws Exception {
		//建立一个httpclient对象
		CloseableHttpClient httpClient = HttpClients.createDefault();
		//建立一个GET对象
		HttpGet get = new HttpGet("http://www.baidu.com");
		//执行请求
		CloseableHttpResponse response = httpClient.execute(get);
		//取响应的结果
		int statusCode = response.getStatusLine().getStatusCode();
		System.out.println(statusCode);
		HttpEntity entity = response.getEntity();
		String string = EntityUtils.toString(entity, "utf-8");
		System.out.println(string);
		//关闭httpclient
		response.close();
		httpClient.close();
	}
}

4.4.四、带参数get请求

package com.taotao.test;

import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.junit.Test;

public class Test2 {
	@Test
	public void doGetWithParam() throws Exception{
		//建立一个httpclient对象
		CloseableHttpClient httpClient = HttpClients.createDefault();
		//建立一个uri对象
		URIBuilder uriBuilder = new URIBuilder("http://www.baidu.com/s");
		uriBuilder.addParameter("wd", "苏大强");
		HttpGet get = new HttpGet(uriBuilder.build());
		//执行请求
		CloseableHttpResponse response = httpClient.execute(get);
		//取响应的结果
		int statusCode = response.getStatusLine().getStatusCode();
		System.out.println(statusCode);
		HttpEntity entity = response.getEntity();
		String string = EntityUtils.toString(entity, "utf-8");
		System.out.println(string);
		//关闭httpclient
		response.close();
		httpClient.close();
	}
	
	
	
}

4.五、Httpclient封装成工具类

其余项目也可能会用到httpclient,因此把工具类放到taotao-common中。

五 大广告位展现

5.一、需求分析

须要建立一个json字符串传递给jsp:

      Json字符串如何传递给jsp:使用modelAndView对象把json字符串传递给jsp。

      如何得到json字符串:得到一个广告位对应的内容列表,须要调用taotao-rest的服务。把列表转换成json数据格式要求的pojo对象列表。须要使用httpclient调用taotao-rest的服务。

5.二、Dao层

      没有

5.三、Service层

       根据内容分类id查询分类的内容列表,须要使用httpclient(系统之间进行交互)调用taotao-rest的服务。获得一个json字符串。

      须要把字符串转换成java对象taotaoResult对象。从taotaoResult对象中取data属性,获得内容列表。把内容列表转换成jsp页面要求的json格式。返回一个json字符串。

参数:没有参数

返回值:json字符串。

#ji chu url
REST_BASE_URL=http://localhost:8081/rest
# da guanggao wei url
REST_INDEX_AD_URL=/content/list/89
package com.taotao.portal.service.impl;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.http.impl.client.HttpClients;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import com.taotao.pojo.TaotaoResult;
import com.taotao.pojo.TbContent;
import com.taotao.portal.service.ContentService;
import com.taotao.util.HttpClientUtil;
import com.taotao.util.JsonUtils;
@Service
public class ContentServiceImpl implements ContentService {
	
	@Value("${REST_BASE_URL}")
	private String REST_BASE_URL;
	@Value("REST_INDEX_AD_URL")
	private String 	REST_INDEX_AD_URL;
	
	/*大广告位展现
	 *       根据内容分类id查询分类的内容列表,须要使用httpclient调用taotao-rest的服务。获得一个json字符串。
	 * 须要把字符串转换成java对象taotaoResult对象。从taotaoResult对象中取data属性,获得内容列表。
	 * 把内容列表转换成jsp页面要求的json格式。返回一个json字符串。
	 *	            参数:没有参数   返回值:json字符串。
	 */
	@Override
	public String getContentList() {
		//调用服务层的服务
		String result = HttpClientUtil.doGet(REST_BASE_URL+REST_INDEX_AD_URL);
		//把字符串转换为TaotaoResult对象
		try {
			TaotaoResult taotaoResult = TaotaoResult.formatToList(result,TbContent.class);
			//从taotaoResult对象中取data属性,获得内容列表
			List<TbContent> list=(List<TbContent>) taotaoResult.getData();
			ArrayList<Map> resultList = new ArrayList<>();
			// 建立一个jsp页面要求的pojo列表(把内容列表转换成jsp页面要求的json格式。返回一个json字符串。)
			for (TbContent tbContent : list) {
				Map map = new HashMap<>();
				map.put("src", tbContent.getPic());
				map.put("height", 240);
				map.put("width", 670);
				map.put("srcB", tbContent.getPic2());
				map.put("widthB", 550);
				map.put("heightB", 240);
				map.put("href", tbContent.getUrl());
				map.put("alt", tbContent.getSubTitle());
				resultList.add(map);
			}
			return JsonUtils.objectToJson(resultList);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}
	
	
}

 

5.四、Controller层

    在taotao-portal项目中的IndexController中,展现首页返回一个逻辑视图,须要把首页大广告位的json数据传递给jsp。

package com.taotao.portal.controller;

import javax.annotation.Resource;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;

import com.taotao.portal.service.ContentService;

@Controller
public class IndexController {
	
	@Resource
	private ContentService contentService;
	
	//跳转页面
	@RequestMapping("/index")
	public String toIndex(Model model) {
		String adJson = contentService.getContentList();
		model.addAttribute("ad1", adJson);
		return "index";
	}
}

5.5 截图留念

先去为大广告   添加内容管理

而后访问门户网站

 

点击图片就能够直接跳转页面(由于内容管理表中有个字段是url)