带你逐步深入了解SSM框架——淘淘商城项目之CMS系统
1. 课程计划
1、 CMS系统实现
2、 Httpclient学习
3、 首页内容显示
2. 首页的动态实现分析
网站的首页的实现必须是动态的,可以在后台管理维护。
2.1. CMS -- 内容管理系统
思路:
1、 分析每个模块的共性
a) 链接
b) 图片
c) 标题
d) 子标题
2、 使用两张表来管理
a) 内容分类表,管理内容的大分类
b) 内容表,存储每个分类下的明细信息内容。
2.2. 首页大广告的展示流程
3. CMS 内容管理系统
3.1. 需求分析(演示功能)
内容列表
新增节点
。。。。
3.2. 数据库设计
需要一张表存储内容数据:字段:标题、url、子标题、image、内容分类id等等
需要一张表存储内容的分类信息,树形结构的表。
内容分类表:
内容表:
3.3. 内容分类列表
内容分类管理实际上是一个树形结构的管理,新增子节点、重命名、删除(级联删除所有的子节点)
3.3.1. 分析
查询内容分类列表,返回一个分类列表。
请求的url:
/content/category/list
响应的数据格式:
必须包含id、text、state三个节点。
3.3.2. Pojo定义
对应返回结果的数据类型定义一个pojo类,其中包含三个属性id、text、state。
publicclass EasyUITreeNode {
private Integerid; private Stringtext; private Stringstate; } |
3.3.3. Mapper
使用****生成的mapper映射文件和mapper接口文件。
3.3.4. Service
@Service publicclass ContentCategoryServiceImpl implements ContentCategoryService {
@Autowired private TbContentCategoryMappercontentCategoryMapper;
@Override public List<EasyUITreeNode> getContentCategoryList(longparentid) throws Exception {
//根据parentid查询内容分类列表 TbContentCategoryExample example = new TbContentCategoryExample(); Criteria criteria = example.createCriteria(); criteria.andParentIdEqualTo(parentid); List<TbContentCategory> list = contentCategoryMapper.selectByExample(example); List<EasyUITreeNode> resultList = new ArrayList<>(); for (TbContentCategorytbContentCategory : list) { EasyUITreeNode node = new EasyUITreeNode(); node.setId(tbContentCategory.getId()); node.setText(tbContentCategory.getName()); //判断是否是父节点 if (tbContentCategory.getIsParent()) { node.setState("closed"); } else { node.setState("open"); } resultList.add(node); } returnresultList; } } |
3.3.5. Controller
@Controller @RequestMapping("/content/category") publicclass ContentCategoryController {
@Autowired private ContentCategoryServicecontentCategoryService;
@RequestMapping("/list") @ResponseBody public List<EasyUITreeNode>getContentCategoryList(@RequestParam(value="id", defaultValue="0")longparentid) throws Exception { List<EasyUITreeNode> list = contentCategoryService.getContentCategoryList(parentid);
returnlist; } } |
3.4. 新增子节点
3.4.1. 需求
请求的url:/content/category/create
请求的参数:
parentId:父节点id
Name:新节点的名称
返回的数据格式:
TaotaoResult
3.4.2. Mapper
使用****生成的mapper文件。
添加主键返回:
3.4.3. Service
@Override public TaotaoResult addNode(longparentid, String name)throws Exception { Date date = new Date(); //添加一个新节点 //创建一个节点对象 TbContentCategory node = new TbContentCategory(); node.setName(name); node.setParentId(parentid); node.setIsParent(false); node.setCreated(date); node.setUpdated(date); node.setSortOrder(1); //状态。可选值:1(正常),2(删除) node.setStatus(1); //插入新节点。需要返回主键 contentCategoryMapper.insert(node); //判断如果父节点的isparent不是true修改为true //取父节点的内容 TbContentCategory parentNode = contentCategoryMapper.selectByPrimaryKey(parentid); if (!parentNode.getIsParent()) { parentNode.setIsParent(true); contentCategoryMapper.updateByPrimaryKey(parentNode); } //把新节点返回 return TaotaoResult.ok(node); } |
3.4.4. Controller
@RequestMapping("/create") @ResponseBody publicTaotaoResult addNode(Long parentId, String name) throws Exception {
TaotaoResult result = contentCategoryService.addNode(parentId,name);
returnresult; } |
3.5. 重命名节点
3.6. 删除节点
3.7. 内容列表
3.7.1. 需求
请求的url:
/content/query/list
响应的数据格式:
EasyUIResult
3.7.2. Mapper
使用逆向生成的mapper文件。
3.7.3. Service
@Service publicclass ContentServiceImpl implements ContentService {
@Autowired private TbContentMappercontentMapper;
@Override public EasyUIResult getContentList(longcatId, Integer page, Integerrows) throws Exception { //根据category_id查询内容列表 TbContentExample example = new TbContentExample(); Criteria criteria = example.createCriteria(); criteria.andCategoryIdEqualTo(catId); //分页处理 PageHelper.startPage(page,rows); List<TbContent> list = contentMapper.selectByExampleWithBLOBs(example); //取分页信息 PageInfo<TbContent> pageInfo = new PageInfo<>(list); EasyUIResult result = new EasyUIResult(pageInfo.getTotal(),list); returnresult; } } |
3.7.4. Controller
@Controller @RequestMapping("/content") publicclass ContentController {
@Autowired private ContentServicecontentService;
@RequestMapping("/query/list") @ResponseBody public EasyUIResult getContentList(LongcategoryId, Integer page, Integer rows) throws Exception { EasyUIResult result = contentService.getContentList(categoryId,page, rows);
returnresult; } } |
3.8. 添加内容
3.8.1. 需求
点击新增按钮,打开content-add.jsp
点击提交按钮,使用ajax把表单中的数据提交给服务器。
1、请求的url:
/content/save
2、请求的参数
表单中的数据
3、响应的数据格式
TaotaoResult
3.8.2. Mapper
创建一个添加内容的mapper文件,实现向tb_content表中添加数据的功能。使用****生成。
3.8.3. Service
@Override public TaotaoResult addContent(TbContentcontent) throws Exception {
//把图片信息保存至数据库 content.setCreated(new Date()); content.setUpdated(new Date()); //把内容信息添加到数据库 contentMapper.insert(content);
return TaotaoResult.ok(); }
|
3.8.4. Controller
@RequestMapping("/save") @ResponseBody publicTaotaoResult addContent(TbContent content) throws Exception { TaotaoResult result = contentService.addContent(content); returnresult; } |
3.9. 修改内容
3.10. 删除内容
4. 服务层发布服务
4.1. 需求
根据内容的分类ID查询内容列表。
请求的url:
/rest/content/category/{cid}
参数:categoryId
响应的数据格式:
TaoTaoResult
4.2. Mapper
创建一可以根据分类id查询内容列表的mapper。使用****生成的mapper即可。
4.3. Service
@Service publicclass ContentServiceImpl implements ContentService {
@Autowired private TbContentMappercontentMapper;
@Override publicTaotaoResult getContentList(longcid) throws Exception { TbContentExample example = new TbContentExample(); //添加条件 Criteria criteria = example.createCriteria(); criteria.andCategoryIdEqualTo(cid); List<TbContent> list = contentMapper.selectByExample(example); return TaotaoResult.ok(list); } } |
4.4. Controller
@Controller @RequestMapping("/content") publicclass ContentController {
@Autowired private ContentServicecontentService;
@RequestMapping("/category/{cid}") @ResponseBody publicTaotaoResult getContentList(@PathVariable Longcid) { TaotaoResult result = null; try { result = contentService.getContentList(cid); } catch (Exceptione) { e.printStackTrace(); return TaotaoResult.build(500,e.getMessage()); } returnresult; } }
|
5. 首页大广告方案
前端系统获取后端系统提供的接口,如何获取?
5.1. 方案1
jsonp跨域请求
优点:
1、 效率高,没有通过后台中转
2、 减少内网的带宽开销
缺点:
网页中无内容,不利于搜索引擎优化。
5.2. 方案二
通过后台java代码调用服务层
优点:
1、 网页中内容是变化的有利于搜索引擎优化
缺点:
1、 接口调用经过后台中转,效率较低,事实上可以忽略不计。
6. Httpclient
6.1. 什么是httpclient
HTTP 协议可能是现在 Internet 上使用得最多、最重要的协议了,越来越多的 Java 应用程序需要直接通过 HTTP 协议来访问网络资源。虽然在 JDK 的 java net包中已经提供了访问 HTTP 协议的基本功能,但是对于大部分应用程序来说,JDK库本身提供的功能还不够丰富和灵活。HttpClient 是 Apache Jakarta Common 下的子项目,用来提供高效的、最新的、功能丰富的支持 HTTP 协议的客户端编程工具包,并且它支持
HTTP 协议最新的版本和建议。
下载地址:http://hc.apache.org/
6.2. 功能介绍
以下列出的是 HttpClient 提供的主要的功能,要知道更多详细的功能可以参见 HttpClient 的主页。
(1)实现了所有 HTTP 的方法(GET,POST,PUT,HEAD 等)
(2)支持自动转向
(3)支持 HTTPS 协议
(4)支持代理服务器等
6.3. 导入依赖
6.4. 执行GET请求
publicclass DoGET {
publicstatic void main(String[]args) throws Exception {
// 创建Httpclient对象 CloseableHttpClient httpclient = HttpClients.createDefault();
// 创建http GET请求 HttpGet httpGet = new HttpGet("http://www.baidu.com/");
CloseableHttpResponse response = null; try { // 执行请求 response = httpclient.execute(httpGet); // 判断返回状态是否为200 if (response.getStatusLine().getStatusCode() == 200) { String content = EntityUtils.toString(response.getEntity(),"UTF-8"); System.out.println("内容长度:" +content.length()); // FileUtils.writeStringToFile(new File("C:\\baidu.html"), content); } } finally { if (response !=null) { response.close(); } httpclient.close(); } } } |
6.5. 执行GET带参数
publicclass DoGETParam {
publicstatic void main(String[]args) throws Exception {
// 创建Httpclient对象 CloseableHttpClient httpclient = HttpClients.createDefault();
// 定义请求的参数 URI uri = new URIBuilder("http://www.baidu.com/s").setParameter("wd","java").build();
System.out.println(uri);
// 创建http GET请求 HttpGet httpGet = new HttpGet(uri);
CloseableHttpResponse response = null; try { // 执行请求 response = httpclient.execute(httpGet); // 判断返回状态是否为200 if (response.getStatusLine().getStatusCode() == 200) { String content = EntityUtils.toString(response.getEntity(),"UTF-8"); System.out.println(content); } } finally { if (response !=null) { response.close(); } httpclient.close(); } } } |
6.6. 执行post请求
publicclass DoPOST {
publicstatic void main(String[]args) throws Exception {
// 创建Httpclient对象 CloseableHttpClient httpclient = HttpClients.createDefault();
// 创建http POST请求 HttpPost httpPost = new HttpPost("http://www.oschina.net/");
CloseableHttpResponse response = null; try { // 执行请求 response = httpclient.execute(httpPost); // 判断返回状态是否为200 if (response.getStatusLine().getStatusCode() == 200) { String content = EntityUtils.toString(response.getEntity(),"UTF-8"); System.out.println(content); } } finally { if (response !=null) { response.close(); } httpclient.close(); } } } |
6.7. 带参数的post请求
publicclass DoPOSTParam {
publicstatic void main(String[]args) throws Exception {
// 创建Httpclient对象 CloseableHttpClient httpclient = HttpClients.createDefault();
// 创建http POST请求 HttpPost httpPost = new HttpPost("http://www.oschina.net/search");
// 设置2个post参数,一个是scope、一个是q List<NameValuePair> parameters = new ArrayList<NameValuePair>(0); parameters.add(new BasicNameValuePair("scope","project")); parameters.add(new BasicNameValuePair("q","java")); // 构造一个form表单式的实体 UrlEncodedFormEntity formEntity = new UrlEncodedFormEntity(parameters); // 将请求实体设置到httpPost对象中 httpPost.setEntity(formEntity);
CloseableHttpResponse response = null; try { // 执行请求 response = httpclient.execute(httpPost); // 判断返回状态是否为200 if (response.getStatusLine().getStatusCode() == 200) { String content = EntityUtils.toString(response.getEntity(),"UTF-8"); System.out.println(content); } } finally { if (response !=null) { response.close(); } httpclient.close(); } } } |
6.8. 封装HttpClient通用工具类
publicclass HttpClientUtil {
publicstatic String doGet(String url, Map<String, String> param) {
// 创建Httpclient对象 CloseableHttpClient httpclient = HttpClients.createDefault();
String resultString = ""; CloseableHttpResponse response = null; try { // 创建uri URIBuilder builder = new URIBuilder(url); if (param !=null) { for (Stringkey : param.keySet()) { builder.addParameter(key, param.get(key)); } } URI uri = builder.build();
// 创建http GET请求 HttpGet httpGet = new HttpGet(uri);
// 执行请求 response = httpclient.execute(httpGet); // 判断返回状态是否为200 if (response.getStatusLine().getStatusCode() == 200) { resultString = EntityUtils.toString(response.getEntity(),"UTF-8"); } } catch (Exceptione) { e.printStackTrace(); } finally { try { if (response !=null) { response.close(); } httpclient.close(); } catch (IOExceptione) { e.printStackTrace(); } } returnresultString; }
publicstatic String doGet(String url) { returndoGet(url, null); }
publicstatic String doPost(String url, Map<String, String> param) { // 创建Httpclient对象 CloseableHttpClient httpClient = HttpClients.createDefault(); CloseableHttpResponse response = null; String resultString = ""; try { // 创建Http Post请求 HttpPost httpPost = new HttpPost(url); // 创建参数列表 if (param !=null) { List<NameValuePair>paramList = new ArrayList<>(); for (Stringkey : param.keySet()) { paramList.add(new BasicNameValuePair(key,param.get(key))); } // 模拟表单 UrlEncodedFormEntityentity = new UrlEncodedFormEntity(paramList); httpPost.setEntity(entity); } // 执行http请求 response = httpClient.execute(httpPost); resultString = EntityUtils.toString(response.getEntity(),"utf-8"); } catch (Exceptione) { e.printStackTrace(); } finally { try { response.close(); } catch (IOExceptione) { // TODO Auto-generated catch block e.printStackTrace(); } }
returnresultString; }
publicstatic String doPost(String url) { returndoPost(url, null); } }
|
7. 实现大广告位
7.1. 需求分析
在首页展示大广告位需要一个json数据来实现。
index.jsp
只需要生成此格式的json数据就可以了:
7.2. Mapper
取广告位信息,不需要mapper。
7.3. Service
调用服务层的服务根据内容分类id查询内容管理系统的内容。
需要一个描述数据结构的pojo类
publicclass ADItem {
private Integerheight; private Integerwidth; private Stringsrc; private IntegerheightB; private IntegerwidthB; private StringsrcB; private Stringalt; private Stringhref; } |
@Service publicclass ADServiceImpl implements AdService {
@Value("${REST_BASE_URL}") private StringREST_BASE_URL; @Value("${INDEX_AD1_URL}") private StringINDEX_AD1_URL;
@Override public String getAdItemList()throws Exception { //调用服务层的服务查询打广告位的数据 String result = HttpClientUtil.doGet(REST_BASE_URL +INDEX_AD1_URL); //把json数据转换成对象 TaotaoResult taotaoResult = TaotaoResult.formatToList(result, TbContent.class); List<ADItem> itemList = new ArrayList<>(); if (taotaoResult.getStatus() == 200 ) { List<TbContent> contentList = (List<TbContent>) taotaoResult.getData(); for (TbContenttbContent : contentList) { ADItem item = new ADItem(); item.setHeight(240); item.setWidth(670); item.setSrc(tbContent.getPic()); item.setHeightB(240); item.setWidth(550); item.setSrcB(tbContent.getPic2()); item.setAlt(tbContent.getTitleDesc()); item.setHref(tbContent.getUrl()); itemList.add(item); } } return JsonUtils.objectToJson(itemList); } } |
7.4. Controller
@Controller publicclass PageController {
@Autowired private AdServiceadService;
@RequestMapping("/index") public String showIndex(Modelmodel) throws Exception { String adResult = adService.getAdItemList(); model.addAttribute("ad1", adResult);
return"index"; } } |
7.5. Jsp页面