1. 程式人生 > >框架 day78 濤濤商城專案-CMS內容管理,httpclient使用,首頁ad展示

框架 day78 濤濤商城專案-CMS內容管理,httpclient使用,首頁ad展示

淘淘商城第六天

                             講師:入雲龍

1  首頁大廣告位的實現分析


首頁的內容需要動態管理,需要後臺管理功能。

抽取首頁展示內容的共性:

1、有一張圖片

2、有一個連線

3、有一個標題

4、有連結的提示

5、價格

需要把內容進行分類,分類應該是一個樹形結構。

在展示首頁時,可以根據分類取內容資訊,把內容展示到頁面。

在後臺管理內容及內容分類的系統就叫做cms系統。

2  Cms系統


先實現內容的分類管理再實現內容管理。

2.1    內容分類管理

2.1.1  內容分類初始化

2.1.1.1 需求分析


初始化樹形檢視的url:/content/category/list


引數是id,當前節點id屬性,應該根據此id查詢子節點列表。

返回值:包含id、text、state三個屬性的json資料列表

2.1.1.2 Dao層

需要一張表儲存內容資料:欄位:標題、url、子標題、image、內容分類id等等

需要一張表儲存內容的分類資訊,樹形結構的表。

表結構:

內容分類表


內容表


Sql語句:

根據parentid查詢節點列表

SELECT * FROM `tb_content_category` WHEREparent_id = 30;

單表查詢可以實現逆向工程生成的程式碼。

2.1.1.3 Service層

功能:接收parentid。根據parentid查詢節點列表,返回返回一個EasyUI非同步Tree要求的節點列表。每個節點包含三個屬性id、text、state三個屬性。可以使用EUTreeNode。

引數:id

返回值:List<EUTreeNode>

@Service

public class ContentCategoryServiceImpl implements ContentCategoryService {

     @Autowired

     private TbContentCategoryMappercontentCategoryMapper;

     @Override

     public List<EUTreeNode> getCategoryList(longparentId) {

          //根據parentid

查詢節點列表

          TbContentCategoryExample example =new TbContentCategoryExample();

          Criteria criteria = example.createCriteria();

          criteria.andParentIdEqualTo(parentId);

          //執行查詢

          List<TbContentCategory> list =contentCategoryMapper.selectByExample(example);

          List<EUTreeNode> resultList =new ArrayList<>();

          for (TbContentCategorytbContentCategory : list) {

               //建立一個節點

               EUTreeNode node =new EUTreeNode();

               node.setId(tbContentCategory.getId());

               node.setText(tbContentCategory.getName());

               node.setState(tbContentCategory.getIsParent()?"closed":"open");

               resultList.add(node);

          }

          returnresultList;

     }

}

2.1.1.4 Controller

接收頁面傳遞過來的parentid,根據parentid查詢節點列表。返回List<EUTreeNode>。需要響應json資料。

@Controller

@RequestMapping("/content/category")

public class ContentCategoryController {

    @Autowired

    private ContentCategoryServicecontentCategoryService;

    @RequestMapping("/list")

     @ResponseBody

    public List<EUTreeNode> getContentCatList(@RequestParam(value="id", defaultValue="0")LongparentId) {

         List<EUTreeNode> list =contentCategoryService.getCategoryList(parentId);

         returnlist;

    }

}

2.1.2  內容分類新增

2.1.2.1 需求分析


請求的url:/content/category/create

引數:

1、parentId父節點id

2、name:當前節點的名稱

返回值:TaotaoResult。其中包含節點pojo物件。

2.1.2.2 Dao層

可以使用逆向工程生成的程式碼

2.1.2.3 Service層

功能:接收兩個引數parentId父節點id、name:當前節點的名稱。向tb_content_category表中新增一條記錄。返回TaoTaoResult包含記錄的pojo物件。

需要返回主鍵資訊:

需要修改mapper檔案,返回主鍵資訊。

方式一:


方式二:

  <insert id="insert" parameterType="com.taotao.pojo.TbContentCategory" useGeneratedKeys="true"keyProperty="id">

    insert into tb_content_category (id, parent_id, name,

      status, sort_order, is_parent,

      created, updated)

    values (#{id,jdbcType=BIGINT}, #{parentId,jdbcType=BIGINT}, #{name,jdbcType=VARCHAR},

      #{status,jdbcType=INTEGER}, #{sortOrder,jdbcType=INTEGER}, #{isParent,jdbcType=BIT},

      #{created,jdbcType=TIMESTAMP}, #{updated,jdbcType=TIMESTAMP})

  </insert>

@Override

     public TaotaoResult insertContentCategory(longparentId, 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);

     }

2.1.2.4 Controller層

接收兩個引數parentid、name。呼叫Service新增記錄。返回TaotaoResult。應該返回json資料。

@RequestMapping("/create")

     @ResponseBody

     public TaotaoResult createContentCategory(LongparentId, String name) {

          TaotaoResult result =contentCategoryService.insertContentCategory(parentId,name);

          returnresult;

     }

2.1.3  內容分類刪除

需求分析:

請求的url:

/content/category/delete/

引數:

1、parentId

2、Id

返回值:TaotaoResult

業務邏輯:

接收parentid、id兩個引數。刪除id對應的記錄。需要判斷parentid對應的記錄下是否有子節點。如果沒有子節點。需要把parentid對應的記錄的isparent改成false。

注意:刪除直接是物理刪除。

2.1.4  重新命名節點

1、


2、當編輯完成後會觸發onAfterEdit事件。


請求的url:/content/category/update

引數:id、name

返回值:返回TaotaoResult。Json格式

業務邏輯:根據id更新記錄的name列即可。

2.2    內容管理

內容管理表:


2.2.1  內容列表

需求分析

請求url:/content/query/list


引數:page、rows、categoryId


返回值:EUDataGridResult

Total、rows:內容pojo列表。

業務邏輯:

根據內容分類id查詢內容列表。需要實現分頁。返回EUDataGridResult

2.2.2  內容新增

需求分析:


圖片上傳初始化:


內容表單提交:


請求的url:/content/save

請求的方法:post

請求內容:表單中的內容。

返回的結果:TaotaoResult。

2.2.3  Dao層

向tb_content表中插入資料。可以使用逆向工程生成的程式碼。

2.2.4  Service層

接收表tb_content對應的pojo物件。把pojo物件插入到tb_content表中。

返回TaotaoResult。

@Service

public class ContentServiceImpl implements ContentService {

     @Autowired

     private TbContentMapper contentMapper;

     @Override

     public TaotaoResult insertContent(TbContentcontent) {

          //補全pojo內容

          content.setCreated(new Date());

          content.setUpdated(new Date());

          contentMapper.insert(content);

          return TaotaoResult.ok();

     }

}

2.2.5  Controller層

接收表單中的內容,使用pojo接收。要求pojo的屬性要和表單中的name一致。呼叫Service插入內容資訊。返回TaotaoResult。Json格式的資料。

@Controller

@RequestMapping("/content")

public class ContentController {

     @Autowired

     private ContentServicecontentService;

     @RequestMapping("/save")

     @ResponseBody

     public TaotaoResult insertContent(TbContent content) {

          TaotaoResult result =contentService.insertContent(content);

          returnresult;

     }

}

3  展示商城首頁大廣告位

3.1    首頁大廣告方案

前端系統獲取後端系統提供的介面,如何獲取?

3.1.1  方案1

jsonp跨域請求

 

需要當首頁載入完畢後,大廣告位就應該顯示。沒有觸發事件。不是太合適。

優點:不需要二次請求,頁面直接載入內容資料。減少門戶系統的壓力。

缺點:需要延遲載入。不利於seo優化。

3.1.2  第二種方案:


優點:有利於seo優化。可以在taotao-portal中對資料進行加工。

缺點:系統直接需要呼叫服務查詢內容資訊。多了一次http請求。

系統直接服務的呼叫,需要使用httpclient來實現。Taotao-portal和taotao-rest是在同一個區域網內部。速度非常快,呼叫時間可以忽略不計。

展示首頁內容功能,使用方案二實現。

3.2    展示流程


3.3    內容服務釋出

3.3.1  需求分析

根據內容的分類id查詢內容列表,從tb_content表中查詢。服務是一個restFul形式的服務。使用http協議傳遞json格式的資料。

3.3.2  Dao層

從tb_content表中查詢,根據內容分類id查詢。是單表查詢。可以使用逆向工程生成的程式碼。

3.3.3  Service層

接收內容分類id,根據分類id查詢分類列表。返回一個內容pojo列表。

引數:分類id

返回值:pojo列表

@Service

public class ContentServiceImpl implements ContentService {

     @Autowired

     private TbContentMappercontentMapper;

     @Override

     public List<TbContent> getContentList(longcontentCid) {

          //根據內容分類id查詢內容列表

          TbContentExample example =new TbContentExample();

          Criteria criteria = example.createCriteria();

          criteria.andCategoryIdEqualTo(contentCid);

          //執行查詢

          List<TbContent> list =contentMapper.selectByExample(example);

          returnlist;

     }

}

3.3.4  Controller層

釋出服務。接收查詢引數。Restful風格內容分類id應該從url中取。

/rest/content/list/{contentCategoryId}

從url中取內容分類id,呼叫Service查詢內容列表。返回內容列表。返回一個json格式的資料。可以使用TaotaoResult包裝此列表。

@Controller

@RequestMapping("/content")

public class ContentController {

     @Autowired

     private ContentServicecontentService;

     @RequestMapping("/list/{contentCategoryId}")

     @ResponseBody

     public TaotaoResult getContentList(@PathVariable LongcontentCategoryId) {

          try {

               List<TbContent> list =contentService.getContentList(contentCategoryId);

               return TaotaoResult.ok(list);

          } catch (Exceptione) {

               e.printStackTrace();

               return TaotaoResult.build(500, ExceptionUtil.getStackTrace(e));

          }

     }

}

3.4    Httpclient的使用

3.4.1  什麼是httpclient

HttpClient 是 Apache Jakarta Common 下的子專案,用來提供高效的、最新的、功能豐富的支援 HTTP 協議的客戶端程式設計工具包,並且它支援 HTTP 協議最新的版本和建議。

HTTP 協議可能是現在 Internet 上使用得最多、最重要的協議了,越來越多的 Java 應用程式需要直接通過 HTTP 協議來訪問網路資源。雖然在 JDK 的 java net包中已經提供了訪問 HTTP 協議的基本功能,但是對於大部分應用程式來說,JDK 庫本身提供的功能還不夠豐富和靈活。HttpClient 是 Apache Jakarta Common 下的子專案,用來提供高效的、最新的、功能豐富的支援 HTTP 協議的客戶端程式設計工具包,並且它支援 HTTP 協議最新的版本和建議。
下載地址:

以下列出的是 HttpClient 提供的主要的功能,要知道更多詳細的功能可以參見 HttpClient 的主頁。

(1)實現了所有 HTTP 的方法(GET,POST,PUT,HEAD 等)

(2)支援自動轉向

(3)支援 HTTPS 協議

(4)支援代理伺服器等


3.4.2  新增依賴

 

需要把httpclient的jar包新增到工程中。只需要在工程中新增httpclient的依賴。

3.4.3  使用方法

3.4.3.1 使用httpclient執行get請求

@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);

          //取響應的結果

          intstatusCode = 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();

     }

3.4.3.2 執行get請求帶引數

@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);

          //取響應的結果

          intstatusCode = 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();

     }

3.4.3.3 使用httpclient執行post請求

@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();

      }

3.4.3.4 帶引數post請求

     @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();

     }

3.4.4  Httpclient封裝成工具類

其他專案也可能會用到httpclient,所以把工具類放到taotao-common中。

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;

         }

}

4  大廣告位展示

4.1    需求分析



需要建立一個json字串傳遞給jsp:使用EL表示式${ad1} 接收

Json字串如何傳遞給jsp:使用modelAndView物件把json字串傳遞給jsp。

如何獲得json字串:獲得一個廣告位對應的內容列表,需要呼叫taotao-rest的服務。把列表轉換成json資料格式要求的pojo物件列表。

需要使用httpclient呼叫taotao-rest的服務。

4.2    Dao層

沒有

4.3    Service層

根據內容分類id查詢分類的內容列表,需要使用httpclient呼叫taotao-rest的服務。得到一個json字串。需要把字串轉換成java物件taotaoResult物件。從taotaoResult物件中取data屬性,得到內容列表。把內容列表轉換成jsp頁面要求的json格式。返回一個json字串。

引數:沒有引數

返回值:json字串。

@Service

public class ContentServiceImpl implements ContentService {

     @Value("${REST_BASE_URL}")

     private StringREST_BASE_URL;

     @Value("${REST_INDEX_AD_URL}")

     private StringREST_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<>();

               //建立一個jsp頁碼要求的pojo列表

               for (TbContenttbContent : 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 (Exceptione) {

               e.printStackTrace();

          }

          returnnull;

     }

}

4.4    Controller

展示首頁返回一個邏輯檢視,需要把首頁大廣告位的json資料傳遞給jsp。

@RequestMapping("/index")

     public String showIndex(Modelmodel) {

          String adJson = contentService.getContentList();

          model.addAttribute("ad1", adJson);

          return"index";

     }


效果