學成在線筆記一:項目概述與CMS接口開發

項目介紹

項目概述

學成在線借鑑了MOOC(大型開放式網絡課程,即MOOC(massive open online courses))的設計思想,是一個提供IT職業課程在線學習的平臺,它爲即將和已經加入IT領域的技術人才提供在線學習服務,用戶通過在線學習、在線練習、在線考試等學習內容,最終掌握所學的IT技能,並能在工作中熟練應用。

功能模塊

當前市場的在線教育模式多種多樣,包括:B2C、C2C、B2B2C等業務模式,學成在線採用B2B2C業務模式,即向企業或個人提供在線教育平臺提供教學服務,老師和學生通過平臺完成整個教學和學習的過程,市場上類似的平臺有:網易雲課堂、騰訊課堂等,學成在線的特點是IT職業課程在線教學。

大模塊介紹:

功能模塊名稱 功能說明
門戶 在首頁、活動頁、專題頁等頁面提供課程學習入口。
學習中心 學生登錄學習中心在線學習課程。
社交系統 社交系統爲老師和學生交流搭建溝通的平臺,包括:問答系統、評論系統、論壇等,
學生和老師通過問答系統提問問題、回答問題,通過評論系統對老師授課進行評論。
教學管理中心 教師登錄教學管理中心進行課程管理、資源管理、考試管理等教學活動。
系統管理中心 系統管理員登錄系統管理中心進行分類管理、運維管理等功能。

技術架構

學成在線採用當前流行的前後端分離架構開發,由用戶層、UI層、微服務層、數據層等部分組成,爲PC、App、H5等客戶端用戶提供服務。下圖是系統的技術架構圖:

各模塊說明:

序號 名稱 功能描述
1 用戶層 用戶層描述了本系統所支持的用戶類型包括:pc用戶、app用戶、h5用戶。pc用戶通過
瀏覽器訪問系統、app用戶通過android、ios手機訪問系統,H5用戶通過h5頁面訪問系
統。
2 CDN CDN全稱Content Delivery Network,即內容分發網絡,本系統所有靜態資源全部通過
CDN加速來提高訪問速度。系統靜態資源包括:html頁面、js文件、css文件、image圖
片、pdf和ppt及doc教學文檔、video視頻等。
3 負載均衡 系統的CDN層、UI層、服務層及數據層均設置了負載均衡服務,上圖僅在UI層前邊標註
了負載均衡。每一層的負載均衡會根據系統的需求來確定負載均衡器的類型,系統支持
4層負載均衡+7層負載均衡結合的方式,4層負載均衡是指在網絡傳輸層進行流程轉發,
根據IP和端口進行轉發,7層負載均衡完成HTTP協議負載均衡及反向代理的功能,根據
url進行請求轉發。
4 UI層 UI層描述了系統向pc用戶、app用戶、h5用戶提供的產品界面。根據系統功能模塊特點
確定了UI層包括如下產品界面類型:1)面向pc用戶的門戶系統、學習中心繫統、教學
管理系統、系統管理中心。2)面向h5用戶的門戶系統、學習中心繫統。3)面向app
用戶的門戶系統、學習中心繫統未在上圖標註,在app項目中有詳細說明。
5 微服務層 微服務層將系統服務分類三類:前端服務、後端服務及系統服務。前端服務:主要爲學
習用戶提供學習服務。後端服務:主要爲管理用戶提供教學管理服務。系統服務:公
共服務,爲系統的所有微服務提供公共服務功能。服務網關:提供服務路由、負載均
衡、認證授權等服務。
6 數據層 數據層描述了系統的數據存儲的內容類型,持久化的業務數據使用MySQL和MongoDB
保存,其中MongoDB中主要保存系統日誌信息。消息隊列:存儲系統服務間通信的消
息,本身提供消息存取服務,與微服務層的系統服務連接。索引庫:存儲課程信息的索
引信息,本身提供索引維護及搜索的服務,與微服務層的系統服務連接。緩存:作爲系
統的緩存服務,存儲課程信息、分類信息、用戶信息等,與微服務層的所有服務連接。
文件存儲:提供系統靜態資源文件的分佈式存儲服務,文件存儲服務器作爲CDN服務器
的數據來源,CDN上的靜態資源將最終在文件存儲服務器上保存多份。流媒體服務:
作爲流媒體服務器,存儲所有的流媒體文件。
7 外部系統接口 1)微信、QQ、微博登錄接口,本系統和微信、QQ、微博系統對接,用戶輸入微信、
QQ、微博的賬號和密碼即可登錄本系統。2)微信、QQ、微博分享接口,本系統和微
信、QQ、微博系統對接,可直接將本系統的課程資源信息分享到微信、QQ、微博。
3)支付寶、微信、網銀支付接口,本系統提供支付寶、微信、網銀三種支付接口。
4)短信接口,本系統與第三方平臺對接短信發送接口。5)郵件接口,本系統需要連
接第三方的smpt郵件服務器對外發送電子郵件。6)微信公衆號,本系統與微信公衆號
平臺接口,用戶通過微信公衆號訪問H5頁面。7)點播、直播,前期視頻點播與直播採
用第三方服務方式,本系統與第三方點、直播服務對接,對外提供視頻點播與直播服
務。8)OSS存儲,前期靜態資源文件的存儲採用第三方服務方式,本系統與第三方提
供的OSS存儲服務對接,將系統的靜態資源文件存儲到第三方提供的OSS存儲服務器
上。9)CDN,本系統與第三方CDN服務對接,使用CDN加速服務來提高本系統的訪問
速度。
8 DevOps DevOps(英文Development和Operations的組合)是一組過程、方法與系統的統稱,
用於促進開發(應用程序/軟件工程)、技術運營和質量保障(QA)部門之間的溝通、
協作與整合。本項目供了許多開發、運營、維護支撐的系統,包括:Eureka服務治理
中心:提供服務治理服務,包括:服務註冊、服務獲取等。Spring Cloud Config服務
配置管理中心:提供服務配置管理服務,包括:配置文件更新、配置文件下發等。
Hystrix Dashboard服務熔斷監控:監控熔斷的請求響應時間、成功率等。Zipkin服務
追蹤監控:監控服務調用鏈路健康情況。Jenkins持續集成服務:提供系統持續集成服
務。Git/GitLab代碼管理服務:提供git代碼管理服務。ELK日誌分析服務:提供elk日誌分
析服務,包括系統運行日誌分析、告警服務。Docker容器化部署服務:將本系統所有
服務採用容器化部署方式。Maven項目管理工具:提供管理項目所有的Java包依賴、項
目工程打包服務。

技術棧

重點了解微服務技術棧

學成在線服務端基於Spring Boot構建,採用Spring Cloud微服務框架。

  • 持久層:MySQL、MongoDB、Redis、ElasticSearch

  • 數據訪問層:使用Spring Data JPA 、Mybatis、Spring Data Mongodb等

  • 業務層:Spring IOC、Aop事務控制、Spring Task任務調度、Feign、Ribbon、Spring AMQP、Spring Data Redis等。

  • 控制層:Spring MVC、FastJSON、RestTemplate、Spring Security Oauth2+JWT等

  • 微服務治理:Eureka、Zuul、Hystrix、Spring Cloud Config等

CMS需求分析

什麼是CMS

CMS (Content Management System)即內容管理系統,不同的項目對CMS的定位不同,比如:一個在線教育網站,有些公司認爲CMS系統是對所有的課程資源進行管理,而在早期網站剛開始盛行時很多公司的業務是網站製作,當時對CMS的定位是創建網站,即對網站的頁面、圖片等靜態資源進行管理。

CMS有哪些類型

CMS基本上分爲:針對後臺數據內容的管理、針對前端頁面的管理、針對樣式風格的管理等。比如:一個給企業做網站的公司,其CMS系統主要是網站頁面管理及樣式風格的管理。

本項目CMS的定位是什麼

本項目作爲一個大型的在線教育平臺,對CMS系統的定位是對各各網站(子站點)頁面的管理,主要管理由於運營需要而經常變動的頁面,從而實現根據運營需要快速進行頁面開發、上線的需求。

導入基礎工程與Nginx配置(省略)

CMS頁面管理需求

這些頁面的管理流程是什麼?

  1. 創建站點

    一個網站有很多子站點,比如:學成在線有主門戶、學習中心、問答系統等子站點。具體的哪個頁面是歸屬於具體的站點,所以要管理頁面,先要管理頁面所屬的站點。

  2. 創建模板

    頁面如何創建呢?比如電商網站的商品詳情頁面,每個頁面的內容佈局、板式是相同的,不同的只是內容,這個頁面的佈局、板式就是頁面模板,模板+數據就組成一個完整的頁面,最終要創建一個頁面文件需要先定義此頁面的模板,最終拿到頁面的數據再結合模板就拼裝成一個完整的頁面。

  3. 創建頁面

    創建頁面是指填寫頁面的基本信息,如:頁面的名稱、頁面的url地址等。

  4. 頁面預覽

    頁面預覽是頁面發佈前的一項工作,頁面預覽使用靜態化技術根據頁面模板和數據生成頁面內容,並通過瀏覽器預覽頁面。頁面發佈前進行頁面預覽的目是爲了保證頁面發佈後的正確性。

  5. 頁面發佈

    使用計算機技術將頁面發送到頁面所在站點的服務器,頁面發佈成功就可以通過瀏覽器來訪問了。

本項目要實現什麼樣的功能?

  1. 頁面管理

    管理員在後臺添加、修改、刪除頁面信息。

  2. 頁面預覽

    管理員通過頁面預覽功能預覽頁面發佈後的效果。

  3. 頁面發佈

    管理員通過頁面發佈功能將頁面發佈到遠程門戶服務器。頁面發佈成功,用戶即可在瀏覽器瀏覽到最新發布的頁面,整個頁面添加、發佈的過程由於軟件自動執行,無需人工登錄服務器操作。

CMS接口開發

工程導入(省略)

注意:

​ 我這裏導入遇到一個坑,xc-framework-common的依賴中spring-cloud-starter-feign導入不成功,在Spring Boot 2.x後,該依賴更名了,需要將該依賴修改爲:spring-cloud-starter-openfeign(不需要輸入版本號)。

MongoDB安裝以及集合導入(省略)

請求與響應對象

接收請求參數對象

定義請求模型QueryPageRequest,此模型作爲查詢條件類型

package com.xuecheng.framework.domain.cms.request;

import com.xuecheng.framework.model.request.RequestData;
import lombok.Data;

@Data
public class QueryPageRequest extends RequestData {
    
    //站點id
    private String siteId;
    //頁面ID
    private String pageId;
    //頁面名稱
    private String pageName;
    //別名
    private String pageAliase;
    //模版id
    private String templateId;

}

響應結果對象

package com.xuecheng.framework.model.response;

import lombok.Data;
import lombok.ToString;

@Data
@ToString
public class QueryResponseResult extends ResponseResult {

    QueryResult queryResult;

    public QueryResponseResult(ResultCode resultCode,QueryResult queryResult){
        super(resultCode);
       this.queryResult = queryResult;
    }

}

API接口定義

xc-service-api中定義接口,進行接口的統一管理

package com.xuecheng.api.cms;

import com.xuecheng.framework.domain.cms.request.QueryPageRequest;
import com.xuecheng.framework.model.response.QueryResponseResult;

public interface CmsPageControllerApi {

    QueryResponseResult findList(int page, int size, QueryPageRequest queryPageRequest);

}

API接口實現

創建xc-service-manage-cms工程。

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>xc-service-api</artifactId>
        <groupId>com.xuecheng</groupId>
        <version>1.0-SNAPSHOT</version>
        <relativePath>../xc-service-api/pom.xml</relativePath>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>xc-service-manage-cms</artifactId>

    <dependencies>
        <dependency>
            <groupId>com.xuecheng</groupId>
            <artifactId>xc-service-api</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
        <dependency>
            <groupId>com.xuecheng</groupId>
            <artifactId>xc-framework-model</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
        <dependency>
            <groupId>com.xuecheng</groupId>
            <artifactId>xc-framework-utils</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
        <dependency>
            <groupId>com.xuecheng</groupId>
            <artifactId>xc-framework-common</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-freemarker</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-mongodb</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-amqp</artifactId>
        </dependency>
        <dependency>
            <groupId>com.squareup.okhttp3</groupId>
            <artifactId>okhttp</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-mongodb</artifactId>
        </dependency>
    </dependencies>

</project>

application.yml

server:
    port: 31001
spring:
  application:
      name: xc‐service‐manage‐cms
  data:
    mongodb:
      uri: mongodb://192.168.136.110:27017/
      database: xc_cms

啓動類

package com.xuecheng.manage_cms;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.domain.EntityScan;
import org.springframework.context.annotation.ComponentScan;

@SpringBootApplication
@EntityScan("com.xuecheng.framework.domain.cms")
@ComponentScan(basePackages={"com.xuecheng.api"})
@ComponentScan(basePackages={"com.xuecheng.manage_cms"})
public class ManageCmsApplication {

    public static void main(String[] args) {
        SpringApplication.run(ManageCmsApplication.class, args);
    }

}

Dao

package com.xuecheng.manage_cms.dao;

import com.xuecheng.framework.domain.cms.CmsPage;
import org.springframework.data.mongodb.repository.MongoRepository;

public interface CmsPageRepository extends MongoRepository<CmsPage, String> {
}

Service

package com.xuecheng.manage_cms.service;

import com.xuecheng.framework.domain.cms.CmsPage;
import com.xuecheng.framework.domain.cms.request.QueryPageRequest;
import com.xuecheng.framework.model.response.CommonCode;
import com.xuecheng.framework.model.response.QueryResponseResult;
import com.xuecheng.framework.model.response.QueryResult;
import com.xuecheng.manage_cms.dao.CmsPageRepository;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.stereotype.Service;

@Slf4j
@Service
public class CmsPageService {

    @Autowired
    private CmsPageRepository cmsPageRepository;

    public QueryResponseResult findList(int page, int size, QueryPageRequest queryPageRequest) {
        if (page <= 0) {
            page = 1;
        }
        // 頁碼從0開始
        page = page - 1;
        // 查詢
        Page<CmsPage> pageResult = cmsPageRepository.findAll(PageRequest.of(page, size));
        QueryResult<CmsPage> cmsPageQueryResult = new QueryResult<>();
        cmsPageQueryResult.setList(pageResult.getContent());
        cmsPageQueryResult.setTotal(pageResult.getTotalElements());
        
        return new QueryResponseResult(CommonCode.SUCCESS, cmsPageQueryResult);
    }
}

Controller

package com.xuecheng.manage_cms.controller;

import com.xuecheng.api.cms.CmsPageControllerApi;
import com.xuecheng.framework.domain.cms.request.QueryPageRequest;
import com.xuecheng.framework.model.response.QueryResponseResult;
import com.xuecheng.manage_cms.service.CmsPageService;
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/page")
public class CmsPageController implements CmsPageControllerApi {

    @Autowired
    private CmsPageService cmsPageService;

    @Override
    @GetMapping("list/{page}/{size}")
    public QueryResponseResult findList(@PathVariable("page") int page,
                                        @PathVariable("size") int size,
                                        QueryPageRequest queryPageRequest) {
        return cmsPageService.findList(page, size, queryPageRequest);
    }
}

測試

Swagger

OpenAPI規範(OpenAPI Specification 簡稱OAS)是Linux基金會的一個項目,試圖通過定義一種用來描述API格式或API定義的語言,來規範RESTful服務開發過程,目前版本是V3.0,並且已經發布並開源在github上。

https://github.com/OAI/OpenAPI-Specification

Swagger是全球最大的OpenAPI規範(OAS)API開發工具框架,支持從設計和文檔到測試和部署的整個API生命週期的開發。

https://swagger.io/

Spring Boot 可以集成Swagger,生成Swagger接口,Spring Boot是Java領域的神器,它是Spring項目下快速構建項目的框架。

常用註解

  • @Api:修飾整個類,描述Controller的作用@ApiOperation:描述一個類的一個方法,或者說一個接口。

  • @ApiParam:單個參數描述

  • @ApiModel:用對象來接收參數

  • @ApiModelProperty:用對象接收參數時,描述對象的一個字段

  • @ApiResponse:HTTP響應其中1個描述

  • @ApiResponses:HTTP響應整體描述

  • @ApiIgnore:使用該註解忽略這個API

  • @ApiError :發生錯誤返回的信息

  • @ApiImplicitParam:一個請求參數

  • @ApiImplicitParams:多個請求參數

@ApiImplicitParams參數介紹

屬性 取值 作用
paramType 查詢的參數類型
path 以地址的形式提交數據
query 直接跟參數完成自動映射賦值
body 以流的形式提交(POST請求)
header 參數攜帶在request headers(請求頭)
form 以form表單的形式提交(POST)
dataType 參數的數據類型(只是用於展示)
Long
String
name 接收參數名
value 該參數的描述
required true/false 參數是否必填
defaultValue 默認值

Swagger配置類

package com.xuecheng.api.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;

@Configuration
@EnableSwagger2
public class Swagger2Configuration {
    @Bean
    public Docket createRestApi() {
        return new Docket(DocumentationType.SWAGGER_2)
                .apiInfo(apiInfo())
                .select()
                .apis(RequestHandlerSelectors.basePackage("com.xuecheng"))
                .paths(PathSelectors.any())
                .build();
    }

    private ApiInfo apiInfo() {
        return new ApiInfoBuilder()
                .title("學成網api文檔")
                .description("學成網api文檔")
                .version("1.0")
                .build();
    }

}

Swagger接口定義

修改CmsPageControllerApi,使用Swagger相關注解

package com.xuecheng.api.cms;

import com.xuecheng.framework.domain.cms.request.QueryPageRequest;
import com.xuecheng.framework.model.response.QueryResponseResult;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;

@Api(value = "CMS頁面管理接口", description = "CMS頁面管理接口,提供頁面的增刪改查")
public interface CmsPageControllerApi {

    @ApiOperation("分頁查詢頁面列表")
    @ApiImplicitParams(
            @ApiImplicitParam(name = "page", value = "頁碼", required = true, paramType = "path", dataType = "int"),
            @ApiImplicitParam(name = "size", value = "每頁記錄數", required = true, paramType = "path", dataType = "int")
    )
    QueryResponseResult findList(int page, int size, QueryPageRequest queryPageRequest);

}

QueryPageRequest使用@ApiModelProperty對屬性進行解析

package com.xuecheng.framework.domain.cms.request;

import com.xuecheng.framework.model.request.RequestData;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;

@Data
public class QueryPageRequest extends RequestData {

    //站點id
    @ApiModelProperty("站點ID")
    private String siteId;
    //頁面ID
    @ApiModelProperty("頁面ID")
    private String pageId;
    //頁面名稱
    @ApiModelProperty("頁面名稱")
    private String pageName;
    //別名
    @ApiModelProperty("頁面別名")
    private String pageAliase;
    //模版id
    @ApiModelProperty("模板ID")
    private String templateId;

}

訪問測試

訪問地址:http://localhost:31001/swagger-ui.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章