Springcloud微服務項目——人力資源管理(HRM)Day08 頁面靜態化

靜態化優化方案設計

爲什麼要使用頁面靜態化

課程主頁的訪問人數非常多, 以不發請求靜態頁面代替要發請求靜態頁面或者動態頁面.沒有對後臺數據獲取.
課程詳情頁:只要課程信息不改,詳情頁就不會改變.
官網主頁:一定的時間段是不可變
招聘主頁:一定的時間段是不可變
職位詳情:只要職位信息不改,詳情頁就不會改變.

有的頁面訪問人數很多,但是在一定時間段內不會改變(數據沒變化).頁面靜態化.

靜態化好處

降低數據庫或緩存壓力
提高響應速度,增強用戶體驗.


分析

頁面靜態化是這一種方案,而模板技術是實現這種方案的技術
靜態頁面=模板(結構)+數據(內容)

靜態頁面生成時機

①當部署並啓動,需要在後臺管理裏面觸發一個按鈕,初始化靜態頁面. 初始化
②當數據(類型,廣告等)發生改變後(後臺做了增刪改),要覆蓋原來靜態頁面. 替換
方案:頁面靜態化,通過模板技術來實現.
模板技術:freemaker,velocity,thymeleaf等

單體項目方案分析

在這裏插入圖片描述

集羣項目架構分析

在這裏插入圖片描述
在這裏插入圖片描述

實現準備

新建模塊 hrm-page-parent
需要的配置
首先在網關中添加
在這裏插入圖片描述
然後是Swagger
在這裏插入圖片描述

數據庫

在這裏插入圖片描述
爲了數據庫查詢的一個效率 我們採用了反三範式的設計
在這裏插入圖片描述
數據庫說明:
t_site:前端站點 主站 課程 職位 要做頁面靜態化的前端網站
t_page 頁面, 在站點下面有多個頁面要做靜態化。 定義了模板
t_page_config 每做一次頁面靜態化,都要添加一個對象。一個頁面一次持久化所需要數據保存。

生成代碼

此處省略

技術準備

模板技術 velocity
RabbitMq
Nosql — redis
Dfs技術-fastdfs

Fastdfs

使用feign實現文件的上傳和下載 放在公共的服務裏面
在這裏插入圖片描述
hrm-common-common需要導入的依賴

<!--客戶端feign支持-->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<dependency>
    <groupId>io.github.openfeign.form</groupId>
    <artifactId>feign-form</artifactId>
    <version>2.1.0</version>
</dependency>
<dependency>
    <groupId>io.github.openfeign.form</groupId>
    <artifactId>feign-form-spring</artifactId>
    <version>2.1.0</version>
</dependency>

hrm-common-client 模塊
注意 這裏使用的配置是我們自己的配置
configuration = FeignMultipartSupportConfig.class
FastDfsClient.java

@FeignClient(value = "HRM-COMMON", configuration = FeignMultipartSupportConfig.class,
        fallbackFactory = FastDfsClientFallbackFactory.class )
@RequestMapping("/fastDfs")
public interface FastDfsClient {
    //上傳
    @PostMapping(produces = {MediaType.APPLICATION_JSON_UTF8_VALUE}
            , consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
    AjaxResult upload(@RequestPart(required = true,value = "file")MultipartFile file);


    //下載 以Response來接收數據
    @GetMapping
     Response download(@RequestParam(required = true,value = "path") String path);
}

FastDfsClientFallbackFactory.java

@Component
public class FastDfsClientFallbackFactory implements FallbackFactory<FastDfsClient> {
    @Override
    public FastDfsClient create(Throwable throwable) {
        return new FastDfsClient() {
            @Override
            public AjaxResult upload(MultipartFile file) {
                return new AjaxResult().setSuccess(false).setMessage("上傳失敗");
            }

            @Override
            public Response download(String path) {
                return null;
            }
        };
    }
}

FeignMultipartSupportConfig.java

@Configuration
public class FeignMultipartSupportConfig {

    //form編碼格式
    @Bean
    @Primary
    @Scope("prototype")
    public Encoder multipartFormEncoder() {
        return new SpringFormEncoder();
    }

    @Bean
    public feign.Logger.Level multipartLoggerLevel() {
        return feign.Logger.Level.FULL;
    }
}

hrm-common-service-2090模塊 上傳下載的實現
需要導入的依賴

<!-- https://mvnrepository.com/artifact/commons-io/commons-io -->
<dependency>
    <groupId>commons-io</groupId>
    <artifactId>commons-io</artifactId>
    <version>2.4</version>
</dependency>

實現
FastDfsController.java

@RestController
@RequestMapping("/fastDfs")
public class FastDfsController {
    //crud 上傳 下載(查看) 刪除 修改(先刪除後添加)
    /**
     * 參數:上傳文件
     * 返回值:成功與否,還要返回地址
     */
    @PostMapping(produces = {MediaType.APPLICATION_JSON_UTF8_VALUE}
            , consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
    public AjaxResult upload(@RequestPart(required = true,value = "file")MultipartFile file){
        try {
            System.out.println(file.getOriginalFilename() + ":" + file.getSize());
            String originalFilename = file.getOriginalFilename();
            // xxx.jpg
            String extName = originalFilename.substring(originalFilename.lastIndexOf(".")+1);
            System.out.println(extName);
            String filePath =  FastDfsApiOpr.upload(file.getBytes(), extName);
            return AjaxResult.me().setResultObj(filePath); //把上傳後的路徑返回回去
        } catch (IOException e) {
            e.printStackTrace();
            return AjaxResult.me().setSuccess(false).setMessage("上傳失敗!"+e.getMessage());
        }
    }

    //下載
    @GetMapping
    void download(@RequestParam(required = true,value = "path") String path, HttpServletResponse response){
        ByteArrayInputStream bis = null;
        ServletOutputStream outputStream = null;
        try{
            String pathTmp = path.substring(1); // goup1/xxxxx/yyyy
            String groupName =  pathTmp.substring(0, pathTmp.indexOf("/")); //goup1
            String remotePath = pathTmp.substring(pathTmp.indexOf("/")+1);// xxxxx/yyyy
            System.out.println(groupName);
            System.out.println(remotePath);
            byte[] data = FastDfsApiOpr.download(groupName, remotePath);


            //以流方式直接做響應 不需要返回Response
            bis = new ByteArrayInputStream(data);
            outputStream = response.getOutputStream();
            IOUtils.copy(bis,outputStream);
        }catch (Exception e
        ){
            e.printStackTrace();
        }
        finally {
            if (outputStream != null) {
                try {
                    outputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (bis != null) {
                try {
                    bis.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
    /**
     * 參數:完整路徑 /goup1/xxxxx/yyyy
     * 返回值:成功與否,還要返回地址
     *
     */
    @DeleteMapping
    public AjaxResult del(@RequestParam(required = true,value = "path") String path){
        String pathTmp = path.substring(1); // goup1/xxxxx/yyyy
        String groupName =  pathTmp.substring(0, pathTmp.indexOf("/")); //goup1
        String remotePath = pathTmp.substring(pathTmp.indexOf("/")+1);// /xxxxx/yyyy
        System.out.println(groupName);
        System.out.println(remotePath);
        FastDfsApiOpr.delete(groupName, remotePath);
        return  AjaxResult.me();
    }
}

FastDfsApiOpr.java在上一篇文章中有寫到


Velocity

Velocity是一個基於java的模板引擎(template engine),它允許任何人僅僅簡單的使用模板語言(template language)來引用由java代碼定義的對象。作爲一個比較完善的模板引擎,Velocity的功能是比較強大的,但強大的同時也增加了應用複雜性。

準備模板

在這裏插入圖片描述

準備前端頁面

Pager.vue
在這裏插入圖片描述

基本上的準備都已完成 接下來我們正式開始

頁面靜態化的整體流程

後端代碼

搭建一個hrm-page-parent模塊

也是三個子模塊
在這裏插入圖片描述

hrm-page-common模塊放domain 和Query

導入依賴 其餘兩個模塊也是依賴這個模塊

<dependencies>

    <!--不能直接依賴starter,有自動配置,而消費者是不需要額。-->

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>

    <dependency>
        <groupId>org.leryoo</groupId>
        <artifactId>hrm-basic-util</artifactId>
        <version>1.0-SNAPSHOT</version>
    </dependency>

    <!--不能全部引入mybatis-plus,這是要做數據庫操作,這裏是不需要的,只需引入核心包解決錯誤而已-->
    <dependency>
        <groupId>com.baomidou</groupId>
        <artifactId>mybatis-plus</artifactId>
        <version>2.2.0</version>
    </dependency>
</dependencies>

hrm-page-service-2030
首先是配置文件
bootstrap.yml

spring:
  profiles:
    active: dev
  cloud:
    config:
      name: application-page #github上面名稱
      profile: ${spring.profiles.active} #環境 java -jar -D xxx jar
      label: master #分支
      discovery:
        enabled: true #從eureka上面找配置服務
        service-id: hrm-config-server #指定服務名
      #uri: http://127.0.0.1:1299 #配置服務器 單機配置
eureka: #eureka不能放到遠程配置中
  client:
    service-url:
      defaultZone: http://localhost:1010/eureka  #告訴服務提供者要把服務註冊到哪兒 #單機環境
  instance:
    prefer-ip-address: true #顯示客戶端真實ip
feign:
  hystrix:
    enabled: true #開啓熔斷支持
  client:
    config:
      remote-service:           #服務名,填寫default爲所有服務
        connectTimeout: 3000
        readTimeout: 3000
hystrix:
  command:
    default:
      execution:
        isolation:
          thread:
            timeoutInMilliseconds: 3000

在碼雲的配置倉庫中添加
application-page-dev.yml

server:
  port: 2030
spring:
  application:
    name: hrm-page
  datasource:
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://localhost:3306/hrm-page
    username: root
    password: root
mybatis-plus:
  mapper-locations: classpath:org/leryoo/mapper/*Mapper.xml
  type-aliases-package: org.leryoo.domain,org.leryoo.query

注意 記得要先提交到碼雲

然後是導入兩個工具類
一個是文件解壓的工具類
ZipUtil.java

import java.io.*;
import java.util.Enumeration;
import java.util.zip.ZipEntry;
import java.util.zip.ZipException;
import java.util.zip.ZipFile;
import java.util.zip.ZipOutputStream;

public final class ZipUtil  
{  
  
    /** 
     * 緩衝大小 
     */  
    private static int BUFFERSIZE = 2 << 10;  
      
    /** 
     * 壓縮 
     * @param paths 
     * @param fileName 
     */  
    public static void zip(String[] paths, String fileName)  
    {  
          
        ZipOutputStream zos = null;
        try  
        {  
            zos = new ZipOutputStream(new FileOutputStream(fileName));
            for(String filePath : paths)  
            {  
                //遞歸壓縮文件  
                File file = new File(filePath);  
                String relativePath = file.getName();  
                if(file.isDirectory())  
                {  
                    relativePath += File.separator;
                }  
                zipFile(file, relativePath, zos);  
            }  
        }  
        catch (IOException e)
        {  
            e.printStackTrace();  
        }  
        finally  
        {  
            try  
            {  
                if(zos != null)  
                {  
                    zos.close();  
                }  
            }  
            catch (IOException e)  
            {  
                e.printStackTrace();  
            }  
        }  
    }  
      
    public static void zipFile(File file, String relativePath, ZipOutputStream zos)  
    {  
        InputStream is = null;
        try  
        {  
            if(!file.isDirectory())  
            {  
                ZipEntry zp = new ZipEntry(relativePath);
                zos.putNextEntry(zp);  
                is = new FileInputStream(file);
                byte[] buffer = new byte[BUFFERSIZE];  
                int length = 0;  
                while ((length = is.read(buffer)) >= 0)  
                {  
                    zos.write(buffer, 0, length);  
                }  
                zos.flush();  
                zos.closeEntry();  
            }  
            else  
            {  
                for(File f: file.listFiles())  
                {  
                    zipFile(f, relativePath + f.getName() + File.separator, zos);  
                }  
            }  
        }  
        catch (IOException e)  
        {  
            e.printStackTrace();  
        }  
        finally  
        {  
            try  
            {  
                if(is != null)  
                {  
                    is.close();  
                }  
            }  
            catch (IOException e)  
            {  
                e.printStackTrace();  
            }  
        }  
    }  
      
    /** 
     * 解壓縮 
     * @param fileName 
     * @param path 
     */  
    public static void unzip(String fileName, String path)  
    {  
        FileOutputStream fos = null;  
        InputStream is = null;  
        try  
        {  
            ZipFile zf = new ZipFile(new File(fileName));
            Enumeration en = zf.entries();
            while (en.hasMoreElements())  
            {  
                ZipEntry zn = (ZipEntry) en.nextElement();  
                if (!zn.isDirectory())  
                {  
                    is = zf.getInputStream(zn);  
                    File f = new File(path + zn.getName());  
                    File file = f.getParentFile();  
                    file.mkdirs();  
                    fos = new FileOutputStream(path + zn.getName());  
                    int len = 0;  
                    byte bufer[] = new byte[BUFFERSIZE];  
                    while (-1 != (len = is.read(bufer)))  
                    {  
                        fos.write(bufer, 0, len);  
                    }  
                    fos.close();  
                }  
            }  
        }  
        catch (ZipException e)
        {  
            e.printStackTrace();  
        }  
        catch (IOException e)  
        {  
            e.printStackTrace();  
        }  
        finally  
        {  
            try  
            {  
                if(null != is)  
                {  
                    is.close();  
                }  
                if(null != fos)  
                {  
                    fos.close();  
                }  
            }  
            catch (IOException e)  
            {  
                e.printStackTrace();  
            }  
        }  
    }  
      
    /** 
     * @param args 
     */  
//    public static void main(String[] args)
//    {
//        //zip(new String[] {"D:/tmp/20150418/logs/file/2015-08-28/debug-log.log","D:/tmp/20150418/logs/file/2015-08-28/error-log.log"}, "D:/tmp/20150418/logs/file/2015-08-28/test.zip");
//        //unzip("D://tmep.zip", "D:/temp/");
//
//        Map<String, Object> modelMap = new HashMap<>(); //封裝兩個參數作爲一個對象傳入進去
//        String templatePagePath = "D://temp/home.vm.html"; //本地靜態頁面地址
//        String staticRoot = "D://temp/";
//        modelMap.put("staticRoot", staticRoot);
//        modelMap.put("courseTypes", null);
//        VelocityUtils.staticByTemplate(modelMap,"D://temp/home.vm",templatePagePath); //進行頁面靜態化
//    }
}  

一個是生成靜態頁面的工具類

package org.leryoo.utils;

import org.apache.velocity.Template;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.Velocity;
import org.apache.velocity.app.VelocityEngine;

import java.io.*;
import java.util.Properties;

public class VelocityUtils {
	private static Properties p = new Properties();
	static {
		p.setProperty(Velocity.FILE_RESOURCE_LOADER_PATH, "");
		p.setProperty(Velocity.ENCODING_DEFAULT, "UTF-8");
		p.setProperty(Velocity.INPUT_ENCODING, "UTF-8");
		p.setProperty(Velocity.OUTPUT_ENCODING, "UTF-8");
	}
	
	/**
	 * 返回通過模板,將model中的數據替換後的內容
	 * @param model
	 * @param templateFilePathAndName
	 * @return
	 */
	public static String getContentByTemplate(Object model, String templateFilePathAndName){
		try {
			Velocity.init(p);
			Template template = Velocity.getTemplate(templateFilePathAndName);
			VelocityContext context = new VelocityContext();
			context.put("model", model);
			StringWriter writer = new StringWriter();
			template.merge(context, writer);
			String retContent = writer.toString();
			writer.close();
			return retContent;
		} catch (Exception e) {
			e.printStackTrace();
		}
		return "";
	}

	/**
	 * 根據模板,靜態化model到指定的文件 模板文件中通過訪問model來訪問設置的內容
	 * 
	 * @param model
	 *            數據對象
	 * @param templateFilePathAndName
	 *            模板文件的物理路徑
	 * @param targetFilePathAndName
	 *            目標輸出文件的物理路徑
	 */
	public static void staticByTemplate(Object model, String templateFilePathAndName, String targetFilePathAndName) {
		try {
			Velocity.init(p);
			Template template = Velocity.getTemplate(templateFilePathAndName);
			
			VelocityContext context = new VelocityContext();
			context.put("model", model);
			FileOutputStream fos = new FileOutputStream(targetFilePathAndName);
			BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(fos, "UTF-8"));// 設置寫入的文件編碼,解決中文問題
			template.merge(context, writer);
			writer.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/**
	 * 靜態化內容content到指定的文件
	 * 
	 * @param content
	 * @param targetFilePathAndName
	 */
	public static void staticBySimple(Object content, String targetFilePathAndName) {
		VelocityEngine ve = new VelocityEngine();
		ve.init(p);
		String template = "${content}";
		VelocityContext context = new VelocityContext();
		context.put("content", content);
		StringWriter writer = new StringWriter();
		ve.evaluate(context, writer, "", template);
		try {
			FileWriter fileWriter = new FileWriter(new File(targetFilePathAndName));
			fileWriter.write(writer.toString());
			fileWriter.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}

然後寫一個靜態化的全家桶
Controller層

@Autowired
private IPageConfigService pageConfigService;

@PostMapping("/pageStatic")
AjaxResult staticPage(
        @RequestParam(value = "pageName",required = true) String pageName,
        @RequestParam(value = "dataKey",required = true)String dataKey){
    try {
        pageConfigService.staticPage(pageName,dataKey);
        return AjaxResult.me();
    } catch (Exception e) {
        e.printStackTrace();
        return AjaxResult.me().setMessage("靜態化失敗!"+e.getMessage());
    }
}

Service層 也是整個頁面靜態化的核心

package org.leryoo.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import feign.Response;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileItemFactory;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.io.IOUtils;
import org.leryoo.client.FastDfsClient;
import org.leryoo.client.RedisClient;
import org.leryoo.domain.PageConfig;
import org.leryoo.domain.Pager;
import org.leryoo.mapper.PageConfigMapper;
import org.leryoo.mapper.PagerMapper;
import org.leryoo.service.IPageConfigService;
import org.leryoo.util.AjaxResult;
import org.leryoo.utils.VelocityUtils;
import org.leryoo.utils.ZipUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.commons.CommonsMultipartFile;

import java.io.*;
import java.util.List;
import java.util.Map;

/**
 * <p>
 *  服務實現類
 * </p>
 *
 * @author yhptest
 * @since 2020-02-24
 */
@Service
public class PageConfigServiceImpl extends ServiceImpl<PageConfigMapper, PageConfig> implements IPageConfigService {


    @Autowired
    private PagerMapper pagerMapper;

    @Autowired
    private FastDfsClient fastDfsClient;

    @Autowired
    private RedisClient redisClient;

    @Autowired
    private PageConfigMapper pageConfigMapper;
    //正在做頁面靜態化
    @Override      //courseTypes- xxx jobTypes=yyy
    public void staticPage(String pageName, String dataKey){
        InputStream inputStream = null;
        FileOutputStream os = null;
        try{
            //一 通過pageName獲取Page並從中獲取模板 url(zip)+name(home.vm)
            //1.1 查詢page對象
            List<Pager> pagers = pagerMapper.selectList(new EntityWrapper<Pager>().eq("name", pageName));
            if (pagers == null || pagers.size()<1) return;
            Pager pager = pagers.get(0);
            //1.2 獲取模板zip包,它是fastdfs的地址
            String templateUrl = pager.getTemplateUrl();
            //1.3 使用fastdfsclient下載它
            Response response = fastDfsClient.download(templateUrl);
            inputStream = response.body().asInputStream();
            String tmpdir=System.getProperty("java.io.tmpdir"); //跨操作系統
            String unzipFile = tmpdir+"/temp.zip";
            os = new FileOutputStream(unzipFile);
            IOUtils.copy(inputStream, os);
            System.out.println("下載路徑:" + unzipFile);
            //1.4 解壓縮
            String unzipDir = tmpdir+"/temp/";
            ZipUtil.unzip(unzipFile,unzipDir);
            System.out.println("解壓路徑:" + unzipDir);
            //1.5 解壓路徑拼接模板名稱得到完整的模板地址
            String tempatePath = unzipDir+"/"+pager.getTemplateName(); //c://temp/home.vm
            System.out.println("模板路徑:" + tempatePath);
            //二  通過dataKey獲取數據
            //{"courseTypes":[]}
            String jsonStr = redisClient.get(dataKey);
            Map model = JSONObject.parseObject(jsonStr,Map.class); //獲取傳遞的map數據
            //{"courseTypes":[],"staticRoot":"xxx"}
            model.put("staticRoot",unzipDir); // 往map裏面追加參數
            //三  做頁面靜態化到本地
            String staticPath = tempatePath+".html";//c://temp/home.vm.html
            System.out.println("靜態化頁面地址:"+staticPath);
            VelocityUtils.staticByTemplate(model,tempatePath,staticPath);

            //四 把靜態化好的頁面上傳到fast	dfs
            AjaxResult ajaxResult = fastDfsClient
                    .upload(new CommonsMultipartFile(createFileItem(new File(staticPath))));

            //五 存放pageConfig
            PageConfig pageConfig = new PageConfig();
            pageConfig.setTemplateUrl(templateUrl);
            pageConfig.setTemplateName(pager.getTemplateName());
            pageConfig.setDataKey(dataKey);
            pageConfig.setPhysicalPath(pager.getPhysicalPath());
            pageConfig.setDfsType(0L); //0表示fastDfs
            pageConfig.setPageUrl((String) ajaxResult.getResultObj()); //上傳完的地址
            pageConfig.setPageId(pager.getId());
            pageConfigMapper.insert(pageConfig);
            //@TODO 六 發送Message到mq中
        }catch (Exception e){
            e.printStackTrace();
        }finally {

            if (os != null) {
                try {
                    os.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (inputStream != null) {
                try {
                    inputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

    }

    /*
創建FileItem
*/
    private FileItem createFileItem(File file) {
        FileItemFactory factory = new DiskFileItemFactory(16, null);
        String textFieldName = "textField";
        FileItem item = factory.createItem("file", "text/plain", true, file.getName());
        int bytesRead = 0;
        byte[] buffer = new byte[8192];
        try {
            FileInputStream fis = new FileInputStream(file);
            OutputStream os = item.getOutputStream();
            while ((bytesRead = fis.read(buffer, 0, 8192)) != -1) {
                os.write(buffer, 0, bytesRead);
            }
            os.close();
            fis.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return item;
    }

}


hrm-page-client
page客戶端 通過feign完成服務之間的調用 將這個服務暴露出去
導入依賴

<dependency>
    <groupId>org.leryoo</groupId>
    <artifactId>hrm-page-common</artifactId>
    <version>1.0-SNAPSHOT</version>
</dependency>

<!--客戶端feign支持-->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>

PageConfigClient.java

@FeignClient(value = "HRM-PAGE",fallbackFactory = PageConfigClientFallbackFactory.class  )//服務提供
@RequestMapping("/pageConfig")
public interface PageConfigClient {
    /**
     * 有了pageName就可以獲取模塊
     * 有了datakey就可以獲取數據
     * @param pageName
     * @param dataKey
     * @return
     */
    @PostMapping("/pageStatic")
    AjaxResult staticPage(
            @RequestParam(value = "pageName",required = true) String pageName,
            @RequestParam(value = "dataKey",required = true)String dataKey);
}

PageConfigClientFallbackFactory.java

@Component
public class PageConfigClientFallbackFactory implements FallbackFactory<PageConfigClient> {
    @Override
    public PageConfigClient create(Throwable throwable) {
        return new PageConfigClient() {
            @Override
            public AjaxResult staticPage(String pageName, String dataKey) {
                return AjaxResult.me().setSuccess(false).setMessage("靜態化失敗!");
            }
        };
    }
}

前端準備

我們可以通過頁面點擊按鈕 或者測試方法生成靜態頁面 這裏我們選擇用頁面點擊按鈕的方式

首先 我們先創建一個頁面 只加一個按鈕
在這裏插入圖片描述
前端代碼
在這裏插入圖片描述

課程中心的代碼

/**
 * 頁面靜態化方法
 */
@PostMapping("/staticIndexPageInit")
public AjaxResult staticIndexPageInit()
{
    try{
        courseTypeService.staticIndexPageInit();
        //調用頁面靜態化的邏輯
        return AjaxResult.me();
    }catch (Exception e){
        e.printStackTrace();
        return AjaxResult.me().setSuccess(false).setMessage(e.getMessage());
    }
}

Service層 通過feign去調用page模塊的方法 完成靜態頁面的生成

@Override
public void staticIndexPageInit() {

    //1頁面名稱寫死,約定大於配置
    String pageName = "CourseSiteIndex";

    //2 需要一個保存到redis數據庫的key
    String dataKey="CourseSiteIndex_data";
    //本來就是從redis獲取,還要在放一次,其他頁面靜態化的場景不一定有緩衝
    List<CourseType> courseTypes = this.treeData(0L);
    //課程處理
    Map<String,Object> courseTypeSdata = new HashMap<>();
    courseTypeSdata.put("courseTypes",courseTypes);
    //職位
    redisClient.add(dataKey, JSONArray.toJSONString(courseTypeSdata)); //{courseTypes:[]}

    //3 調用方法模板+數據=靜態頁面
    pageConfigClient.staticPage(pageName,dataKey);
}

然後點擊按鈕 就會在臨時文件夾裏生成
在這裏插入圖片描述
這也就ok了

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