文章目錄 一.頁面靜態化流程 二.數據模型 1.輪播圖DataUrl接口 1)需求分析 2)接口定義 3)Dao 4)Service 5)Controller 6)測試 2.遠程請求接口 1)添加依賴 2)配置RestTemplate 3)測試RestTemplate 三.模板管理 1.模板管理業務流程 2.模板制作 3.GridFS研究 4.模板存儲 四.靜態化測試 1.填寫頁面DataUrl 1)修改頁面管理前端的page_edit.vue 2)修改頁面管理服務端PageService 2.靜態化程序
一.頁面靜態化流程
頁面靜態化需要準備數據模型和模板,先知道數據模型的結構才可以編寫模板,因為在模板中要引用數據模型中的數據,本節將系統講解CMS頁面數據模型獲取、模板管理及靜態化的過程。
下邊討論一個問題:如何獲取頁面的數據模型?
CMS管理了各種頁面,CMS對頁面進行靜態化時需要數據模型,但是CMS并不知道每個頁面的數據模型的具體內 容,它只管執行靜態化程序便可對頁面進行靜態化,所以CMS靜態化程序需要通過一種通用的方法來獲取數據模 型。
在編輯頁面信息時指定一個DataUrl,此DataUrl便是獲取數據模型的Url,它基于Http方式,CMS對頁面進行靜態 化時會從頁面信息中讀取DataUrl,通過Http遠程調用的方法請求DataUrl獲取數據模型。
管理員怎么知道DataUrl的內容呢?舉例說明: 此頁面是輪播圖頁面,它的DataUrl由開發輪播圖管理的程序員提供。 此頁面是精品課程推薦頁面,它的DataUrl由精品課程推薦的程序員提供。 此頁面是課程詳情頁面,它的DataUrl由課程管理的程序員提供。
頁面靜態化流程如下圖: 1、靜態化程序首先讀取頁面獲取DataUrl。 2、靜態化程序遠程請求DataUrl得到數據模型。 3、獲取頁面模板。 4、執行頁面靜態化。
二.數據模型
1.輪播圖DataUrl接口
1)需求分析
CMS中有輪播圖管理、精品課程推薦的功能,以輪播圖管理為例說明:輪播圖管理是通過可視化的操作界面由管理員指定輪播圖圖片地址,最后將輪播圖圖片地址保存在cms_config集合中,下邊是輪播圖數據模型: 針對首頁的輪播圖信息、精品推薦等信息的獲取統一提供一個Url供靜態化程序調用,這樣我們就知道了輪播圖頁面、精品課程推薦頁面的DataUrl,管理員在頁面配置中將此Url配置在頁面信息中。
本小節開發一個查詢輪播圖、精品推薦信息的接口,此接口供靜態化程序調用獲取數據模型。
2)接口定義
輪播圖信息、精品推薦等信息存儲在MongoDB的cms_config集合中 cms_config有固定的數據結構,如下:
文件位置:xcEduService01\xc-framework-model\src\main\java\com\xuecheng\framework\domain\cms\CmsConfig.java
package com
. xuecheng
. framework
. domain
. cms
; import lombok
. Data
;
import lombok
. ToString
;
import org
. springframework
. data
. annotation
. Id
;
import org
. springframework
. data
. mongodb
. core
. mapping
. Document
; import java
. util
. List
; @Data
@ToString
@Document ( collection
= "cms_config" )
public class CmsConfig { @Id private String id
; private String name
; private List
< CmsConfigModel> model
; }
數據模型項目內容如下:
文件位置:xcEduService01\xc-framework-model\src\main\java\com\xuecheng\framework\domain\cms\CmsConfigModel.java
package com
. xuecheng
. framework
. domain
. cms
; import lombok
. Data
;
import lombok
. ToString
; import java
. util
. Map
; @Data
@ToString
public class CmsConfigModel { private String key
; private String name
; private String url
; private Map mapValue
; private String value
;
}
上邊的模型結構可以對照cms_config中的數據進行分析。其中,在mapValue 中可以存儲一些復雜的數據模型內容。 根據配置信息Id查詢配置信息,定義接口如下:
文件位置xcEduService01\xc-service-api\src\main\java\com\xuecheng\api\cms\CmsConfigControllerApi.java
package com
. xuecheng
. api
. cms
; import com
. xuecheng
. framework
. domain
. cms
. CmsConfig
;
import io
. swagger
. annotations
. Api
;
import io
. swagger
. annotations
. ApiOperation
; @Api ( value
= "cms配置管理接口" , description
= "cms配置管理接口,提供數據模型的管理、查詢接口" )
public interface CmsConfigControllerApi { @ApiOperation ( "根據id查詢CMS配置信息" ) public CmsConfig
getmodel ( String id
) ;
}
3)Dao
定義CmsConfig的dao接口:
文件位置:xcEduService01\xc-service-manage-cms\src\main\java\com\xuecheng\manage_cms\dao\CmsConfigRepository.java
package com
. xuecheng
. manage_cms
. dao
; import com
. xuecheng
. framework
. domain
. cms
. CmsConfig
;
import org
. springframework
. data
. mongodb
. repository
. MongoRepository
; public interface CmsConfigRepository extends MongoRepository < CmsConfig, String> {
}
4)Service
定義Service實現根據id查詢CmsConfig信息:
文件位置:xcEduService01\xc-service-manage-cms\src\main\java\com\xuecheng\manage_cms\service\PageService.java
public CmsConfig
getConfigById ( String id
) { Optional
< CmsConfig> optional
= cmsConfigRepository
. findById ( id
) ; if ( optional
. isPresent ( ) ) { CmsConfig cmsConfig
= optional
. get ( ) ; return cmsConfig
; } return null
; }
5)Controller
文件位置:xcEduService01\xc-service-manage-cms\src\main\java\com\xuecheng\manage_cms\controller\CmsConfigController.java
package com
. xuecheng
. manage_cms
. controller
; import com
. xuecheng
. api
. cms
. CmsConfigControllerApi
;
import com
. xuecheng
. framework
. domain
. cms
. CmsConfig
;
import com
. xuecheng
. manage_cms
. service
. PageService
;
import org
. springframework
. beans
. factory
. annotation
. Autowired
;
import org
. springframework
. web
. bind
. annotation
. GetMapping
;
import org
. springframework
. web
. bind
. annotation
. PathVariable
;
import org
. springframework
. web
. bind
. annotation
. RequestMapping
;
import org
. springframework
. web
. bind
. annotation
. RestController
; @RestController
@RequestMapping ( "/cms/config" )
public class CmsConfigController implements CmsConfigControllerApi { @Autowired PageService pageService
; @Override @GetMapping ( "/getmodel/{id}" ) public CmsConfig
getmodel ( @PathVariable ( "id" ) String id
) { return pageService
. getConfigById ( id
) ; }
}
6)測試
使用postman測試接口: get請求:http://localhost:31001/cms/config/getmodel/5a791725dd573c3574ee333f (輪播圖信息)
2.遠程請求接口
SpringMVC提供 RestTemplate請求http接口,RestTemplate的底層可以使用第三方的http客戶端工具實現http 的 請求,常用的http客戶端工具有Apache HttpClient、OkHttpClient等,本項目使用OkHttpClient完成http請求, 原因也是因為它的性能比較出眾。
1)添加依賴
文件位置:xcEduService01\xc-service-manage-cms\pom.xml
< dependency> < groupId> com
. squareup
. okhttp3
< / groupId
> < artifactId> okhttp
< / artifactId
>
< / dependency
2)配置RestTemplate
在SpringBoot啟動類中配置 RestTemplate 文件位置:xcEduService01\xc-service-manage-cms\src\main\java\com\xuecheng\manage_cms\ManageCmsApplication.java
. . .
public class ManageCmsApplication {
public static void main ( String
[ ] args
) {
SpringApplication
. run ( ManageCmsApplication
. class , args
) ;
}
@Bean
public RestTemplate
restTemplate ( ) {
return new RestTemplate ( new OkHttp3ClientHttpRequestFactory ( ) ) ;
}
}
3)測試RestTemplate
根據url獲取數據,并轉為map格式
文件位置:xcEduService01\xc-service-manage-cms\src\test\java\com\xuecheng\manage_cms\RestTemplateTest.java
@Test
public void testRestTemplate ( ) {
ResponseEntity
< Map> forEntity
=
restTemplate
. getForEntity ( "http://localhost:31001/cms/config/get/5a791725dd573c3574ee333f" , Map
. class ) ;
System
. out
. println ( forEntity
) ;
}
三.模板管理
1.模板管理業務流程
CMS提供模板管理功能,業務流程如下:
1)要增加新模板首先需要制作模板,模板的內容就是Freemarker ftl模板內容。 2)通過模板管理模塊功能新增模板、修改模板、刪除模板。 3)模板信息存儲在MongoDB數據庫,其中模板信息存儲在cms_template集合中,模板文件存儲在GridFS文件系 統中。
cms_template集合: 下邊是一個模板的例子,其中templateFileId是模板文件的ID,此ID對應GridFS文件系統中文件ID。
2.模板制作
1)編寫模板文件
1、輪播圖頁面原型 在門戶的靜態工程目錄有輪播圖的靜態頁面,路徑是:/include/index_banner.html
< ! DOCTYPE html
>
< html lang
= "en" >
< head> < meta charset
= "UTF-8" > < title> Title
< / title
> < link rel
= "stylesheet" href
= "/plugins/normalize-css/normalize.css" / > < link rel
= "stylesheet" href
= "/plugins/bootstrap/dist/css/bootstrap.css" / > < link rel
= "stylesheet" href
= "/css/page-learing-index.css" / > < link rel
= "stylesheet" href
= "/css/page-header.css" / >
< / head
>
< body>
< div
class = "banner-roll" > < div
class = "banner-item" > < div
class = "item" style
= "background-image: url(../img/widget-bannerB.jpg);" > < / div
> < div
class = "item" style
= "background-image: url(../img/widget-bannerA.jpg);" > < / div
> < div
class = "item" style
= "background-image: url(../img/widget-banner3.png);" > < / div
> < div
class = "item" style
= "background-image: url(../img/widget-bannerB.jpg);" > < / div
> < div
class = "item" style
= "background-image: url(../img/widget-bannerA.jpg);" > < / div
> < div
class = "item" style
= "background-image: url(../img/widget-banner3.png);" > < / div
> < / div
> < div
class = "indicators" > < / div
>
< / div
>
< script type
= "text/javascript" src
= "/plugins/jquery/dist/jquery.js" > < / script
>
< script type
= "text/javascript" src
= "/plugins/bootstrap/dist/js/bootstrap.js" > < / script
>
< script type
= "text/javascript" > var tg
= $
( '.banner-item .item' ) ; var num
= 0 ; for ( i
= 0 ; i
< tg
. length
; i
++ ) { $
( '.indicators' ) . append ( '<span></span>' ) ; $
( '.indicators' ) . find ( 'span' ) . eq ( num
) . addClass ( 'active' ) ; } function
roll ( ) { tg
. eq ( num
) . animate ( { 'opacity' : '1' , 'z-index' : num
} , 1000 ) . siblings ( ) . animate ( { 'opacity' : '0' , 'z-index' : 0 } , 1000 ) ; $
( '.indicators' ) . find ( 'span' ) . eq ( num
) . addClass ( 'active' ) . siblings ( ) . removeClass ( 'active' ) ; if ( num
>= tg
. length
- 1 ) { num
= 0 ; } else { num
++ ; } } $
( '.indicators' ) . find ( 'span' ) . click ( function ( ) { num
= $
( this ) . index ( ) ; roll ( ) ; } ) ; var timer
= setInterval ( roll
, 3000 ) ; $
( '.banner-item' ) . mouseover ( function ( ) { clearInterval ( timer
) } ) ; $
( '.banner-item' ) . mouseout ( function ( ) { timer
= setInterval ( roll
, 3000 ) } ) ;
< / script
>
< / body
>
< / html
>
2、數據模型為: 通過http 獲取到數據模型如下: 下圖數據模型的圖片路徑改成可以瀏覽的正確路徑。
{ "_id" : ObjectId ( "5a791725dd573c3574ee333f" ) , "_class" : "com.xuecheng.framework.domain.cms.CmsConfig" , "name" : "輪播圖" , "model" : [ { "key" : "banner1" , "name" : "輪播圖1地址" , "value" : "http://192.168.101.64/group1/M00/00/01/wKhlQFp5wnCAG-kAAATMXxpSaMg864.png" } , { "key" : "banner2" , "name" : "輪播圖2地址" , "value" : "http://192.168.101.64/group1/M00/00/01/wKhlQVp5wqyALcrGAAGUeHA3nvU867.jpg" } , { "key" : "banner3" , "name" : "輪播圖3地址" , "value" : "http://192.168.101.64/group1/M00/00/01/wKhlQFp5wtWAWNY2AAIkOHlpWcs395.jpg" } ]
}
3、編寫模板 在freemarker測試工程中新建模板index_banner.ftl(復制index_banner.html并修改)。 文件位置:xcEduService01\test-freemarker\src\main\resources\templates\index_banner.ftl
< ! DOCTYPE html
>
< html lang
= "en" >
< head> < meta charset
= "UTF-8" > < title> Title
< / title
> < link rel
= "stylesheet" href
= "http://www.xuecheng.com/plugins/normalize-css/normalize.css" / > < link rel
= "stylesheet" href
= "http://www.xuecheng.com/plugins/bootstrap/dist/css/bootstrap.css" / > < link rel
= "stylesheet" href
= "http://www.xuecheng.com/css/page-learing-index.css" / > < link rel
= "stylesheet" href
= "http://www.xuecheng.com/css/page-header.css" / >
< / head
>
< body>
< div
class = "banner-roll" > < div
class = "banner-item" > < #
-- < div
class = "item" style
= "background-image: url(http://www.xuecheng.com/img/widget-bannerB.jpg);" > < / div
> < div
class = "item" style
= "background-image: url(http://www.xuecheng.com/img/widget-bannerA.jpg);" > < / div
> < div
class = "item" style
= "background-image: url(http://www.xuecheng.com/img/widget-banner3.png);" > < / div
> < div
class = "item" style
= "background-image: url(http://www.xuecheng.com/img/widget-bannerB.jpg);" > < / div
> < div
class = "item" style
= "background-image: url(http://www.xuecheng.com/img/widget-bannerA.jpg);" > < / div
> < div
class = "item" style
= "background-image: url(http://www.xuecheng.com/img/widget-banner3.png);" > < / div
> -- > < #
if model
? ? > < #list model as item
> < div
class = "item" style
= "background-image: url(${item.value});" > < / div
> < / #list
> < / #
if > < / div
> < div
class = "indicators" > < / div
>
< / div
>
< script type
= "text/javascript" src
= "http://www.xuecheng.com/plugins/jquery/dist/jquery.js" > < / script
>
< script type
= "text/javascript" src
= "http://www.xuecheng.com/plugins/bootstrap/dist/js/bootstrap.js" > < / script
>
< script type
= "text/javascript" > var tg
= $
( '.banner-item .item' ) ; var num
= 0 ; for ( i
= 0 ; i
< tg
. length
; i
++ ) { $
( '.indicators' ) . append ( '<span></span>' ) ; $
( '.indicators' ) . find ( 'span' ) . eq ( num
) . addClass ( 'active' ) ; } function
roll ( ) { tg
. eq ( num
) . animate ( { 'opacity' : '1' , 'z-index' : num
} , 1000 ) . siblings ( ) . animate ( { 'opacity' : '0' , 'z-index' : 0 } , 1000 ) ; $
( '.indicators' ) . find ( 'span' ) . eq ( num
) . addClass ( 'active' ) . siblings ( ) . removeClass ( 'active' ) ; if ( num
>= tg
. length
- 1 ) { num
= 0 ; } else { num
++ ; } } $
( '.indicators' ) . find ( 'span' ) . click ( function ( ) { num
= $
( this ) . index ( ) ; roll ( ) ; } ) ; var timer
= setInterval ( roll
, 3000 ) ; $
( '.banner-item' ) . mouseover ( function ( ) { clearInterval ( timer
) } ) ; $
( '.banner-item' ) . mouseout ( function ( ) { timer
= setInterval ( roll
, 3000 ) } ) ;
< / script
>
< / body
>
< / html
>
2)模板測試
在freemarker測試工程編寫一個方法測試輪播圖模板,代碼如下: 文件位置:xcEduService01\test-freemarker\src\main\java\com\xuecheng\test\freemarker\controller\FreemarkerController.java
@Autowired
RestTemplate restTemplate
; @RequestMapping ( "/banner" )
public String
index_banner ( Map
< String, Object> map
) {
String dataUrl
= "http://localhost:31001/cms/config/getmodel/5a791725dd573c3574ee333f" ;
ResponseEntity
< Map> forEntity
= restTemplate
. getForEntity ( dataUrl
, Map
. class ) ;
Map body
= forEntity
. getBody ( ) ;
map
. putAll ( body
) ;
return "index_banner" ;
}
請求:http://localhost:8088/freemarker/banner
3.GridFS研究
1)
2)
4.模板存儲
1)
2)
四.靜態化測試
上邊章節完成了數據模型和模板管理的測試,下邊測試整個頁面靜態化的流程,流程如下: 1)填寫頁面DataUrl 在編輯cms頁面信息界面page_edit.vue中添加DataUrl,并將此字段保存到cms_page集合中。 2)靜態化程序獲取頁面的DataUrl 3)靜態化程序遠程請求DataUrl獲取數據模型。 4)靜態化程序獲取頁面的模板信息 5)執行頁面靜態化
1.填寫頁面DataUrl
修改頁面管理模板代碼,實現編輯頁面DataUrl。 注意:此地址由程序員提供給系統管理員,由系統管理員錄入到系統中。 下邊實現頁面修改界面錄入DataUrl:
1)修改頁面管理前端的page_edit.vue
首先來看一下cms_page的模型代碼: 文件位置:\xcEduService01\xc-framework-model\src\main\java\com\xuecheng\framework\domain\cms\CmsPage.java
package com
. xuecheng
. framework
. domain
. cms
; import lombok
. Data
;
import lombok
. ToString
;
import org
. springframework
. data
. annotation
. Id
;
import org
. springframework
. data
. mongodb
. core
. mapping
. Document
; import java
. util
. Date
;
import java
. util
. List
; @Data
@ToString
@Document ( collection
= "cms_page" )
public class CmsPage { private String siteId
; @Id private String pageId
; private String pageName
; private String pageAliase
; private String pageWebPath
; private String pageParameter
; private String pagePhysicalPath
; private String pageType
; private String pageTemplate
; private String pageHtml
; private String pageStatus
; private Date pageCreateTime
; private String templateId
; private List
< CmsPageParam> pageParams
; private String templateFileId
; private String htmlFileId
; private String dataUrl
; }
接下來,在首頁表單中添加dataUrl輸入框: 文件位置:xc-ui-pc-sysmanage\src\module\cms\page\page_edit.vue
< el‐form‐item label
= "數據Url" prop
= "dataUrl" >
< el‐input v‐model
= "pageForm.dataUrl" auto‐complete
= "off" > < / el‐input
>
< / el‐form‐item
>
2)修改頁面管理服務端PageService
在更新cmsPage數據代碼中添加:
one
. setDataUrl ( cmsPage
. getDataUrl ( )
添加后如下: 文件位置:xcEduService01\xc-service-manage-cms\src\main\java\com\xuecheng\manage_cms\service\PageService.java
public CmsPageResult
update ( String id
, CmsPage cmsPage
) { CmsPage one
= this . getById ( id
) ; if ( one
!= null
) { one
. setTemplateId ( cmsPage
. getTemplateId ( ) ) ; one
. setSiteId ( cmsPage
. getSiteId ( ) ) ; one
. setPageAliase ( cmsPage
. getPageAliase ( ) ) ; one
. setPageName ( cmsPage
. getPageName ( ) ) ; one
. setPageWebPath ( cmsPage
. getPageWebPath ( ) ) ; one
. setPagePhysicalPath ( cmsPage
. getPagePhysicalPath ( ) ) ; one
. setDataUrl ( cmsPage
. getDataUrl ( ) ) ; cmsPageRepository
. save ( one
) ; return new CmsPageResult ( CommonCode
. SUCCESS
, one
) ; } return new CmsPageResult ( CommonCode
. FAIL
, null
) ; }
2.靜態化程序
在PageService中定義頁面靜態化方法,如下: 文件位置:xcEduService01\xc-service-manage-cms\src\main\java\com\xuecheng\manage_cms\service\PageService.java
public String
getPageHtml ( String pageId
) { Map model
= getModelByPageId ( pageId
) ; if ( model
== null
) { ExceptionCast
. cast ( CmsCode
. CMS_GENERATEHTML_DATAISNULL
) ; } String template
= getTemplateByPageId ( pageId
) ; if ( StringUtils
. isEmpty ( template
) ) { ExceptionCast
. cast ( CmsCode
. CMS_GENERATEHTML_TEMPLATEISNULL
) ; } String html
= generateHtml ( template
, model
) ; return html
; } private String
generateHtml ( String templateContent
, Map model
) { Configuration configuration
= new Configuration ( Configuration
. getVersion ( ) ) ; StringTemplateLoader stringTemplateLoader
= new StringTemplateLoader ( ) ; stringTemplateLoader
. putTemplate ( "template" , templateContent
) ; configuration
. setTemplateLoader ( stringTemplateLoader
) ; try { Template template
= configuration
. getTemplate ( "template" ) ; String content
= FreeMarkerTemplateUtils
. processTemplateIntoString ( template
, model
) ; return content
; } catch ( Exception e
) { e
. printStackTrace ( ) ; } return null
; } private String
getTemplateByPageId ( String pageId
) { CmsPage cmsPage
= this . getById ( pageId
) ; if ( cmsPage
== null
) { ExceptionCast
. cast ( CmsCode
. CMS_PAGE_NOTEXISTS
) ; } String templateId
= cmsPage
. getTemplateId ( ) ; if ( StringUtils
. isEmpty ( templateId
) ) { ExceptionCast
. cast ( CmsCode
. CMS_GENERATEHTML_TEMPLATEISNULL
) ; } Optional
< CmsTemplate> optional
= cmsTemplateRepository
. findById ( templateId
) ; if ( optional
. isPresent ( ) ) { CmsTemplate cmsTemplate
= optional
. get ( ) ; String templateFileId
= cmsTemplate
. getTemplateFileId ( ) ; GridFSFile gridFSFile
= gridFsTemplate
. findOne ( Query
. query ( Criteria
. where ( "_id" ) . is ( templateFileId
) ) ) ; GridFSDownloadStream gridFSDownloadStream
= gridFSBucket
. openDownloadStream ( gridFSFile
. getObjectId ( ) ) ; GridFsResource gridFsResource
= new GridFsResource ( gridFSFile
, gridFSDownloadStream
) ; try { String content
= IOUtils
. toString ( gridFsResource
. getInputStream ( ) , "utf-8" ) ; return content
; } catch ( IOException e
) { e
. printStackTrace ( ) ; } } return null
; } private Map
getModelByPageId ( String pageId
) { CmsPage cmsPage
= this . getById ( pageId
) ; if ( cmsPage
== null
) { ExceptionCast
. cast ( CmsCode
. CMS_PAGE_NOTEXISTS
) ; } String dataUrl
= cmsPage
. getDataUrl ( ) ; if ( StringUtils
. isEmpty ( dataUrl
) ) { ExceptionCast
. cast ( CmsCode
. CMS_GENERATEHTML_DATAURLISNULL
) ; } ResponseEntity
< Map> forEntity
= restTemplate
. getForEntity ( dataUrl
, Map
. class ) ; Map body
= forEntity
. getBody ( ) ; return body
; }
單元測試getPageHtml方法,過程略。
創作挑戰賽 新人創作獎勵來咯,堅持創作打卡瓜分現金大獎
總結
以上是生活随笔 為你收集整理的学成在线--9.页面静态化 的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔 網站內容還不錯,歡迎將生活随笔 推薦給好友。