1.Cms系统内容的增删改查
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <div class="easyui-panel" title="Nested Panel" data-options="'100%',minHeight:500,noheader:true,border:false" style="padding:10px;"> <div class="easyui-layout" data-options="fit:true"> <div data-options="region:'west',split:false" style="250px;padding:5px"> <ul id="contentCategoryTree" class="easyui-tree" data-options="url:'/content/category/list',animate: true,method : 'GET'"> </ul> </div> <div data-options="region:'center'" style="padding:5px"> <table class="easyui-datagrid" id="contentList" data-options="toolbar:contentListToolbar,singleSelect:false,collapsible:
true,pagination:true,method:'get',pageSize:20,url:'/content/query/list',queryParams:{categoryId:0}"> <thead> <tr> <th data-options="field:'id',30">ID</th> <th data-options="field:'title',120">内容标题</th> <th data-options="field:'subTitle',100">内容子标题</th> <th data-options="field:'titleDesc',120">内容描述</th> <!-- <th data-options="field:'content',120">内容描述</th> --> <th data-options="field:'url',60,align:'center',formatter:JINGXI.formatUrl">内容连接</th> <th data-options="field:'pic',50,align:'center',formatter:JINGXI.formatUrl">图片</th> <th data-options="field:'pic2',50,align:'center',formatter:JINGXI.formatUrl">图片2</th> <th data-options="field:'created',130,align:'center',formatter:JINGXI.formatDateTime">创建日期</th> <th data-options="field:'updated',130,align:'center',formatter:JINGXI.formatDateTime">更新日期</th> </tr> </thead> </table> </div> </div> </div> <script type="text/javascript"> $(function(){ var tree = $("#contentCategoryTree"); var datagrid = $("#contentList"); tree.tree({ onClick : function(node){ if(tree.tree("isLeaf",node.target)){ datagrid.datagrid('reload', { categoryId :node.id }); } } }); }); var contentListToolbar = [{ text:'新增', iconCls:'icon-add', handler:function(){ var node = $("#contentCategoryTree").tree("getSelected"); if(!node || !$("#contentCategoryTree").tree("isLeaf",node.target)){ $.messager.alert('提示','新增内容必须选择一个内容分类!'); return ; } TT.createWindow({ url : "/content-add" }); } },{ text:'编辑', iconCls:'icon-edit', handler:function(){ var ids = TT.getSelectionsIds("#contentList"); if(ids.length == 0){ $.messager.alert('提示','必须选择一个内容才能编辑!'); return ; } if(ids.indexOf(',') > 0){ $.messager.alert('提示','只能选择一个内容!'); return ; } TT.createWindow({ url : "/content-edit", onLoad : function(){ var data = $("#contentList").datagrid("getSelections")[0]; $("#contentEditForm").form("load",data); // 实现图片 if(data.pic){ $("#contentEditForm [name=pic]").after("<a href='"+data.pic+"' target='_blank'><img src='"+data.pic+"' width='80' height='50'/></a>"); } if(data.pic2){ $("#contentEditForm [name=pic2]").after("<a href='"+data.pic2+"' target='_blank'><img src='"+data.pic2+"' width='80' height='50'/></a>"); } /* alert(data.content); */ contentEditEditor.html(data.content); } }); } },{ text:'删除', iconCls:'icon-cancel', handler:function(){ var ids = TT.getSelectionsIds("#contentList"); if(ids.length == 0){ $.messager.alert('提示','未选中商品!'); return ; } $.messager.confirm('确认','确定删除ID为 '+ids+' 的内容吗?',function(r){ if (r){ var params = {"ids":ids}; $.post("/content/delete",params, function(data){ if(data.status == 200){ $.messager.alert('提示','删除内容成功!',undefined,function(){ $("#contentList").datagrid("reload"); }); } }); } }); } }]; </script>
1.1 dao层
单表查询,引用mybatis的方向工程
1.2 service层
@Service public class ContentServiceImpl implements ContentService { @Autowired private TbContentMapper tbContentMapper; @Override public EasyUIDataGridResult getContentList(int page, int rows, long categoryId) { TbContentExample example=new TbContentExample(); PageHelper.startPage(page, rows); Criteria critria=example.createCriteria(); critria.andCategoryIdEqualTo(categoryId); List<TbContent> list=tbContentMapper.selectByExampleWithBLOBs(example); EasyUIDataGridResult result=new EasyUIDataGridResult(); result.setRows(list); //取记录的总条数 PageInfo<TbContent> pageInfo =new PageInfo<>(list); result.setTotal(pageInfo.getTotal()); return result; } @Override public JingXiResult createContent(TbContent tbContent) { JingXiResult result=new JingXiResult(); tbContent.setCreated(new Date()); tbContent.setUpdated(new Date()); int i=tbContentMapper.insert(tbContent); /*if(i == 1){ try{ HttpClientUtil.doGet("http://localhost:8082/rest" + "/cache/sync/content/89" + tbContent.getCategoryId()); }catch(Exception e){ e.printStackTrace(); } return JingXiResult.ok(); }*/ return result; } @Override public JingXiResult editContent(TbContent tbcontent) { JingXiResult result=new JingXiResult(); long id=tbcontent.getId(); tbcontent.setUpdated(new Date()); int i=tbContentMapper.updateByPrimaryKey(tbcontent); if(i == 1){ return JingXiResult.ok(); } return result; } @Override public JingXiResult deleteContent(String ids) { String a[] =ids.split(","); for(int i=0;i<a.length;i++){ tbContentMapper.deleteByPrimaryKey(Long.parseLong(ids)); } return JingXiResult.ok(); } }
1.3 controller层
@Controller public class ContentController { @Autowired private ContentService contentService; @RequestMapping("/content/query/list") @ResponseBody public EasyUIDataGridResult showlist(int page,int rows,long categoryId){ EasyUIDataGridResult result=contentService.getContentList(page, rows, categoryId); return result; } @RequestMapping("/content/save") @ResponseBody public JingXiResult create(TbContent tbContent){ JingXiResult result=contentService.createContent(tbContent); return result; } @RequestMapping("/rest/content/edit") @ResponseBody public JingXiResult edit(TbContent tbContent){ /*System.out.println(tbContent.getTitle()+"." +tbContent.getId()+"."+tbContent.getCategoryId()+"."+tbContent.getContent());*/ JingXiResult result=contentService.editContent(tbContent); return result; } @RequestMapping("/content/delete") @ResponseBody public JingXiResult delete(String ids){ JingXiResult result=contentService.deleteContent(ids); return result; } }
2. 大广告位的展示
2.1 跨域问题的解决
在jingxi-portal页面要调用jingxi-rest中的服务。
方案一:jsonp 跨域请求
需要当首页加载完毕后,大广告位就应该显示。没有触发事件。不是太合适。
优点:不需要二次请求,页面直接加载内容数据。减少门户系统的压力。
缺点:需要延迟加载。不利于 seo 优化。
方案二:使用httpclient实现
优点:有利于 seo 优化。可以在 jingxi-portal 中对数据进行加工。缺点:系统直接需要调用服务查询内容信息,多了一次 http 请求。
系统直接服务的调用,需要使用 httpclient 来实现。jingxi-portal 和 jingxi-rest 是在同一个局域网内部。速度非常快,调用时间可以忽略不计。
展示首页内容功能,使用方案二实现。
2.2 httpclient的使用
2.2.1 什么是 httpclient?
HttpClient 是 Apache Jakarta Common 下的子项目,用来提供高效的、
最新的、功能丰富的支持 HTTP 协议的客户端编程工具包,并且它支持 HTTP 协议最新的版本和建议。
2.2.2 httpclient的使用?
添加依赖需要把 httpclient 的 jar 包添加到工程中,只需要在工程中添加 httpclient 的依赖。
2.2.3 Httpclient 封装成工具类
其他项目也可能会用到 httpclient,所以把工具类放到 jingxi-common 中。
package com.jingxi.common.util; import java.io.IOException; import java.net.URI; import java.util.ArrayList; import java.util.List; import java.util.Map; import org.apache.http.NameValuePair; import org.apache.http.client.entity.UrlEncodedFormEntity; import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.client.methods.HttpGet; import org.apache.http.client.methods.HttpPost; import org.apache.http.client.utils.URIBuilder; import org.apache.http.entity.ContentType; import org.apache.http.entity.StringEntity; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClients; import org.apache.http.message.BasicNameValuePair; import org.apache.http.util.EntityUtils; public class HttpClientUtil { public static 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 (String key : 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 (Exception e) { e.printStackTrace(); } finally { try { if (response != null) { response.close(); } httpclient.close(); } catch (IOException e) { e.printStackTrace(); } } return resultString; } public static String doGet(String url) { return doGet(url, null); } public static 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 (String key : param.keySet()) { paramList.add(new BasicNameValuePair(key, param.get(key))); } // 模拟表单 UrlEncodedFormEntity entity = new UrlEncodedFormEntity(paramList); httpPost.setEntity(entity); } // 执行http请求 response = httpClient.execute(httpPost); resultString = EntityUtils.toString(response.getEntity(), "utf-8"); } catch (Exception e) { e.printStackTrace(); } finally { try { response.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } return resultString; } public static String doPost(String url) { return doPost(url, null); } public static String doPostJson(String url, String json) { // 创建Httpclient对象 CloseableHttpClient httpClient = HttpClients.createDefault(); CloseableHttpResponse response = null; String resultString = ""; try { // 创建Http Post请求 HttpPost httpPost = new HttpPost(url); // 创建请求内容 StringEntity entity = new StringEntity(json, ContentType.APPLICATION_JSON); httpPost.setEntity(entity); // 执行http请求 response = httpClient.execute(httpPost); resultString = EntityUtils.toString(response.getEntity(), "utf-8"); } catch (Exception e) { e.printStackTrace(); } finally { try { response.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } return resultString; } }
3. jingxi-rest服务的发布
需求分析:根据内容的分类 id 查询内容列表,从 tb_content 表中查询,服务是一个 restFul 形式的服务,使用 http 协议传递 json 格式的数据。
3.1 Dao 层:
从 tb_content 表中查询,根据内容分类 id 查询,使用逆向工程生成的代码。
3.2 service层:
@Service public class ContentServiceImpl implements ContentService { @Autowired private TbContentMapper contentMapper; @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; } }
3.3 controller层
@Controller public class ContentController { @Autowired private ContentService contentService; @RequestMapping("/content/list/{contentCategoryId}") @ResponseBody public JingXiResult getContentList(@PathVariable Long contentCategoryId){ try{ List<TbContent> list=contentService.getContentList(contentCategoryId); return JingXiResult.ok(list); }catch(Exception e){ e.printStackTrace(); return JingXiResult.build(500,ExceptionUtil.getStackTrace(e)); } }
4 在jingxi-portal调用jingxi-rest服务
4.1 在jingxi-protal中添加属性文件
4.2 Service 层:
根据内容分类 id 查询分类的内容列表,需要使用 httpclient 调用 jingxi-rest 的服务得到一个 json 字符串,把内容列表转换成 jsp 页面要求的 json 格式。返回一个 json 字符串。
@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; @Override public String getContentList() { //调用服务层的服务 String result = HttpClientUtil.doGet(REST_BASE_URL + REST_INDEX_AD_URL); //把字符串转换成TaotaoResult try { JingXiResult jingXiResult = JingXiResult.formatToList(result, TbContent.class); //取内容列表 List<TbContent> list = (List<TbContent>) jingXiResult.getData(); List<Map> resultList = new ArrayList<>(); //创建一个jsp页码要求的pojo列表
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; } }
4.3 Controller 层:
展示首页返回一个逻辑视图,需要把首页大广告位的 json 数据传递给 jsp。
效果: