https://pan.baidu.com/s/1bptYGAb#list/path=%2F&parentPath=%2Fsharelink389619878-229862621083040html
第04項目:淘淘商城(SpringMVC+Spring+Mybatis) 的學習實踐總結【第五天】java
第04項目:淘淘商城(SpringMVC+Spring+Mybatis) 的學習實踐總結【第六天】node
開發環境:web
Eclipse IDE for Enterprise Java Developers
OS: Windows 10, v.10.0, x86_64 / win32
Java version: 1.8.0_221spring
須要把內容進行分類,分類應該是一個樹形結構。在展現首頁時,能夠根據分類取內容信息,把內容展現到頁面。apache
在後臺管理內容及內容分類的系統就叫作cms系統。編程
先實現內容的分類管理再實現內容管理。json
初始化樹形視圖的url:/content/category/listapp
參數是id,當前節點id屬性,應該根據此id查詢子節點列表。異步
返回值:包含id、text、state三個屬性的json數據列表
功能:接收parentid。根據parentid查詢節點列表,返回返回一個EasyUI異步Tree要求的節點列表。每一個節點包含三個屬性id、text、state三個屬性。可使用自定義的EUTreeNode。
參數:id
返回值:List<EUTreeNode>
@Service public class ContentCategoryServiceImpl implements ContentCategoryService { @Autowired private TbContentCategoryMapper contentCategoryMapper; @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); List<EUTreeNode> resultList = new ArrayList<>(); for (TbContentCategory tbContentCategory : list) { //建立一個節點 EUTreeNode node = new EUTreeNode(); node.setId(tbContentCategory.getId()); node.setText(tbContentCategory.getName()); node.setState(tbContentCategory.getIsParent()?"closed":"open"); resultList.add(node); } return resultList; } }
接收頁面傳遞過來的parentid,根據parentid查詢節點列表。返回List<EUTreeNode>。須要響應json數據。
@Controller @RequestMapping("/content/category") public class ContentCategoryController { @Autowired private ContentCategoryService contentCategoryService; @RequestMapping("/list") @ResponseBody public List<EUTreeNode> getContentCatList(@RequestParam(value="id", defaultValue="0")Long parentId) { List<EUTreeNode> list = contentCategoryService.getCategoryList(parentId); return list; } }
請求的url:/content/category/create
參數:
一、parentId父節點id
二、name:當前節點的名稱
返回值:TaotaoResult。其中包含節點pojo對象。
功能:接收兩個參數parentId父節點id、name:當前節點的名稱。向tb_content_category表中添加一條記錄。返回TaoTaoResult包含記錄的pojo對象。
須要返回主鍵信息:
須要修改mapper文件,返回主鍵信息。
<selectKey keyProperty="id" resultType="Long" order="AFTER"> SELECT LAST_INSERT_ID() </selectKey>
@Override public TaotaoResult insertContentCategory(long parentId, String name) { //建立一個pojo TbContentCategory contentCategory = new TbContentCategory(); contentCategory.setName(name); contentCategory.setIsParent(false); //'狀態。可選值:1(正常),2(刪除)', contentCategory.setStatus(1); contentCategory.setParentId(parentId); contentCategory.setSortOrder(1); contentCategory.setCreated(new Date()); contentCategory.setUpdated(new Date()); //添加記錄 contentCategoryMapper.insert(contentCategory); //查看父節點的isParent列是否爲true,若是不是true改爲true TbContentCategory parentCat = contentCategoryMapper.selectByPrimaryKey(parentId); //判斷是否爲true if(!parentCat.getIsParent()) { parentCat.setIsParent(true); //更新父節點 contentCategoryMapper.updateByPrimaryKey(parentCat); } //返回結果 return TaotaoResult.ok(contentCategory); }
Controller層
接收兩個參數parentid、name。調用Service添加記錄。返回TaotaoResult。應該返回json數據。
@RequestMapping("/create") @ResponseBody public TaotaoResult createContentCategory(Long parentId, String name) { TaotaoResult result = contentCategoryService.insertContentCategory(parentId, name); return result; }
內容管理表:
需求分析:
內容表單提交:
請求的url:/content/save
請求的方法:post
請求內容:表單中的內容
返回的結果:TaotaoResult
向tb_content表中插入數據。可使用逆向工程生成的代碼。
接收表tb_content對應的pojo對象。把pojo對象插入到tb_content表中。
返回TaotaoResult。
@Service public class ContentServiceImpl implements ContentService { @Autowired private TbContentMapper contentMapper; @Override public TaotaoResult insertContent(TbContent content) { //補全pojo內容 content.setCreated(new Date()); content.setUpdated(new Date()); contentMapper.insert(content); return TaotaoResult.ok(); } }
接收表單中的內容,使用pojo接收。要求pojo的屬性要和表單中的name一致。調用Service插入內容信息。返回TaotaoResult。Json格式的數據。
@Controller @RequestMapping("/content") public class ContentController { @Autowired private ContentService contentService; @RequestMapping("/save") @ResponseBody public TaotaoResult insertContent(TbContent content) { TaotaoResult result = contentService.insertContent(content); return result; } }
需求分析:根據內容分類id查詢內容列表。須要實現分頁。
請求url:/content/query/list
參數:page、rows、categoryId
返回值類型:EUDataGridResult
Total、rows:內容pojo列表。
//查詢內容列表並分頁 @Override public EUDataGridResult queryContentList(Long categoryId, int page, int rows) { //使用分頁插件處理分頁 PageHelper.startPage(page, rows);//使用逆向工程的條件查詢 TbContentExample example = new TbContentExample(); Criteria criteria = example.createCriteria(); criteria.andCategoryIdEqualTo(categoryId); List<TbContent> list = contentMapper.selectByExampleWithBLOBs(example); //獲取分頁插件信息 PageInfo<TbContent> pageInfo = new PageInfo<TbContent>(list); // EUDataGridResult result = new EUDataGridResult(); result.setTotal(pageInfo.getTotal()); result.setRows(list); return result; }
Controller層
@RequestMapping("/query/list") @ResponseBody public EUDataGridResult queryContentList(Long categoryId ,int page,int rows) { return contentService.queryContentList(categoryId, page, rows); }
請求url:/content/delete
請求的方法:post
請求參數:ids
返回的結果:TaotaoResult
圖片位置:content.jsp
Service層
@Override //刪除內容根據ids public TaotaoResult deleteContent(Long contentId) { //建立查詢條件 TbContentExample example = new TbContentExample(); TbContentExample.Criteria criteria = example.createCriteria(); criteria.andIdEqualTo(contentId); //執行刪除 contentMapper.deleteByExample(example); return TaotaoResult.ok(); }
Controller層
//刪除選中內容 @RequestMapping("/delete") @ResponseBody public TaotaoResult deleteContent(@RequestParam("ids")Long contentId ) { TaotaoResult result = contentService.deleteContent(contentId); return result; }
Controller層
//內容分類管理:刪除 @RequestMapping("/delete") @ResponseBody public TaotaoResult deleteContentCategory( Long id ) { TaotaoResult result = contentCategoryService.deleteContentCategory(id); return result; }
Service層
@Autowired private TbContentCategoryMapper contentCategoryMapper; @Override public TaotaoResult deleteContentCategory(long id) { deleteCategoryAndChildNode(id); return TaotaoResult.ok(); } private List<TbContentCategory> getChildNodeList(Long id) { //查詢全部父節點ID爲傳入id的內容分類 TbContentCategoryExample example = new TbContentCategoryExample(); TbContentCategoryExample.Criteria criteria = example.createCriteria(); criteria.andParentIdEqualTo(id); //查詢結果做爲返回值 return contentCategoryMapper.selectByExample(example); } // 根據ID刪除葉子分類節點和本身的節點並判斷父節點屬性 private void deleteCategoryAndChildNode(Long id) { TbContentCategory tcc = contentCategoryMapper.selectByPrimaryKey(id); // 1.刪除全部該分類下的子節點 if (tcc.getIsParent()) { // 查詢該節點下的孩子節點 List<TbContentCategory> list = getChildNodeList(id); // 刪除全部孩子節點 for (TbContentCategory contentCategory : list) { // 遞歸調用本方法本身 deleteCategoryAndChildNode(contentCategory.getId()); } } // 2.判斷刪除完成後,父節點下是否還有其餘子節點 List<TbContentCategory> list = getChildNodeList(tcc.getParentId()); if (CollectionUtils.isEmpty(list)) { TbContentCategory parentCategory = contentCategoryMapper.selectByPrimaryKey(tcc.getParentId()); parentCategory.setIsParent(false); contentCategoryMapper.updateByPrimaryKey(parentCategory); } // 3.刪除本節點 contentCategoryMapper.deleteByPrimaryKey(id); return; }
優勢:有利於seo優化。能夠在taotao-portal中對數據進行加工。
缺點:系統直接須要調用服務查詢內容信息。多了一次http請求。
系統直接服務的調用,須要使用httpclient來實現。Taotao-portal和taotao-rest是在同一個局域網內部。速度很是快,調用時間能夠忽略不計。
4.3.1 需求分析
根據內容的分類id查詢內容列表,從tb_content表中查詢。服務是一個restFul形式的服務。使用http協議傳遞json格式的數據。
4.3.2 Dao層
從tb_content表中查詢,根據內容分類id查詢。是單表查詢。可使用逆向工程生成的代碼。
4.3.3 Service層
接收內容分類id,根據分類id查詢分類列表。返回一個內容pojo列表。
參數:分類id
返回值:pojo列表
taotao-rest工程
/** * 內容管理 * @author kangy * */ @Service public class ContentServiceImpl implements ContentService { @Autowired private TbContentMapper contentMapper; @Override public List<TbContent> getContentList(long contentCid) { // 根據內容分類id查詢內容列表 TbContentExample example = new TbContentExample(); TbContentExample.Criteria criteria = example.createCriteria(); criteria.andCategoryIdEqualTo(contentCid); //執行查詢 List<TbContent> list = contentMapper.selectByExampleWithBLOBs(example); //返回結果 return list; } }
4.3.4 Controller層
發佈服務。接收查詢參數。Restful風格內容分類id應該從url中取。
/rest/content/list/{contentCategoryId}
從url中取內容分類id,調用Service查詢內容列表。返回內容列表。返回一個json格式的數據。可使用TaotaoResult包裝此列表。
@RestController @RequestMapping("/content") public class ContentController { @Autowired private ContentService contentService; @GetMapping("/list/{contentCategoryId}") 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)); } } }
package com.taotao.common.utils; 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(); } } }
http://localhost:8081/rest/content/list/89
4.4.1 什麼是httpclient
HttpClient 是 Apache 下的子項目,用來提供高效的、最新的、功能豐富的支持 HTTP 協議的客戶端編程工具包,而且它支持 HTTP 協議最新的版本和建議。
下載地址:
4.4.2 添加依賴
須要把httpclient的jar包添加到工程中。只須要在工程中添加httpclient的依賴。
<!-- httpclient --> <dependency> <groupId>org.apache.httpcomponents</groupId> <artifactId>httpclient</artifactId> </dependency>
@Test public void doGet() throws Exception { //建立一個httpclient對象 CloseableHttpClient httpClient = HttpClients.createDefault(); //建立一個GET對象 HttpGet get = new HttpGet("http://www.sogou.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(); }
@Test public void doGetWithParam() throws Exception{ //建立一個httpclient對象 CloseableHttpClient httpClient = HttpClients.createDefault(); //建立一個uri對象 URIBuilder uriBuilder = new URIBuilder("http://www.sogou.com/web"); uriBuilder.addParameter("query", "花千骨"); 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(); }
@Test public void doPost() throws Exception { CloseableHttpClient httpClient = HttpClients.createDefault(); //建立一個post對象 HttpPost post = new HttpPost("http://localhost:8082/httpclient/post.html"); //執行post請求 CloseableHttpResponse response = httpClient.execute(post); String string = EntityUtils.toString(response.getEntity()); System.out.println(string); response.close(); httpClient.close(); }
@Test public void doPostWithParam() throws Exception{ CloseableHttpClient httpClient = HttpClients.createDefault(); //建立一個post對象 HttpPost post = new HttpPost("http://localhost:8082/httpclient/post.html"); //建立一個Entity。模擬一個表單 List<NameValuePair> kvList = new ArrayList<>(); kvList.add(new BasicNameValuePair("username", "zhangsan")); kvList.add(new BasicNameValuePair("password", "123")); //包裝成一個Entity對象 StringEntity entity = new UrlEncodedFormEntity(kvList, "utf-8"); //設置請求的內容 post.setEntity(entity); //執行post請求 CloseableHttpResponse response = httpClient.execute(post); String string = EntityUtils.toString(response.getEntity()); System.out.println(string); response.close(); httpClient.close(); }
其餘項目也可能會用到httpclient,因此把工具類放到taotao-common中。
package com.taotao.common.utils; 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; } }
須要建立一個json字符串傳遞給jsp:
Json字符串如何傳遞給jsp:使用modelAndView對象把json字符串傳遞給jsp。
如何得到json字符串:得到一個廣告位對應的內容列表,須要調用taotao-rest的服務。把列表轉換成json數據格式要求的pojo對象列表。
須要使用httpclient調用taotao-rest的服務。
taotao-portal項目子模塊
package com.taotao.portal.service.impl; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; import com.taotao.common.pojo.TaotaoResult; import com.taotao.common.utils.HttpClientUtil; import com.taotao.common.utils.JsonUtils; import com.taotao.pojo.TbContent; import com.taotao.portal.service.ContentService; /** * 調用服務層服務,查詢內容列表 * * @author kangy * */ @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 { TaotaoResult taotaoResult = TaotaoResult.formatToList(result, TbContent.class); // 取內容列表 List<TbContent> list = (List<TbContent>) taotaoResult.getData(); List<Map> resultList = new ArrayList<Map>(); // 建立一個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("height", 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; } } }
package com.taotao.common.utils; import java.util.List; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.JavaType; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.taotao.common.pojo.TaotaoResult; /** * 淘淘商城自定義響應結構 */ public class JsonUtils { // 定義jackson對象 private static final ObjectMapper MAPPER = new ObjectMapper(); /** * 將對象轉換成json字符串。 * <p>Title: pojoToJson</p> * <p>Description: </p> * @param data * @return */ public static String objectToJson(Object data) { try { String string = MAPPER.writeValueAsString(data); return string; } catch (JsonProcessingException e) { e.printStackTrace(); } return null; } /** * 將json結果集轉化爲對象 * * @param jsonData json數據 * @param clazz 對象中的object類型 * @return */ public static <T> T jsonToPojo(String jsonData, Class<T> beanType) { try { T t = MAPPER.readValue(jsonData, beanType); return t; } catch (Exception e) { e.printStackTrace(); } return null; } /** * 將json數據轉換成pojo對象list * <p>Title: jsonToList</p> * <p>Description: </p> * @param jsonData * @param beanType * @return */ public static <T>List<T> jsonToList(String jsonData, Class<T> beanType) { JavaType javaType = MAPPER.getTypeFactory().constructParametricType(List.class, beanType); try { List<T> list = MAPPER.readValue(jsonData, javaType); return list; } catch (Exception e) { e.printStackTrace(); } return null; } }
@Controller public class IndexController { @Autowired private ContentService contentService; @RequestMapping("/index") public String showIndex(Model model) { String adJson = contentService.getContentlist(); model.addAttribute("ad1", adJson); return"index"; } }
==============================================
參考資料:
end