Springcloud微服务项目——人力资源管理(HRM)Day08 页面静态化

释放双眼,带上耳机,听听看~!

文章目录

  • 静态化优化方案设计

  • 为什么要使用页面静态化

    • 静态化好处
    • 分析
  • 静态页面生成时机
    * 单体项目方案分析
    * 集群项目架构分析

    • 实现准备
  • 数据库
    * 生成代码
    * 技术准备
    * Fastdfs
    * Velocity

  • 准备模板

    
    
    1
    2
    1  * 准备前端页面
    2
  • 页面静态化的整体流程

  • 后端代码

    • 前端准备

静态化优化方案设计

为什么要使用页面静态化

课程主页的访问人数非常多, 以不发请求静态页面代替要发请求静态页面或者动态页面.没有对后台数据获取.
课程详情页:只要课程信息不改,详情页就不会改变.
官网主页:一定的时间段是不可变
招聘主页:一定的时间段是不可变
职位详情:只要职位信息不改,详情页就不会改变.

有的页面访问人数很多,但是在一定时间段内不会改变(数据没变化).页面静态化.

静态化好处

降低数据库或缓存压力
提高响应速度,增强用户体验.


分析

页面静态化是这一种方案,而模板技术是实现这种方案的技术

静态页面=模板(结构)+数据(内容)

静态页面生成时机

①当部署并启动,需要在后台管理里面触发一个按钮,初始化静态页面. 初始化
②当数据(类型,广告等)发生改变后(后台做了增删改),要覆盖原来静态页面. 替换
方案:页面静态化,通过模板技术来实现.
模板技术:freemaker,velocity,thymeleaf等

单体项目方案分析

Springcloud微服务项目——人力资源管理(HRM)Day08 页面静态化

集群项目架构分析

Springcloud微服务项目——人力资源管理(HRM)Day08 页面静态化
Springcloud微服务项目——人力资源管理(HRM)Day08 页面静态化

实现准备

新建模块
hrm-page-parent
需要的配置
首先在网关中添加
Springcloud微服务项目——人力资源管理(HRM)Day08 页面静态化
然后是Swagger
Springcloud微服务项目——人力资源管理(HRM)Day08 页面静态化

数据库

Springcloud微服务项目——人力资源管理(HRM)Day08 页面静态化
为了数据库查询的一个效率 我们采用了反三范式的设计
Springcloud微服务项目——人力资源管理(HRM)Day08 页面静态化
数据库说明:
t_site:前端站点 主站 课程 职位 要做页面静态化的前端网站
t_page 页面, 在站点下面有多个页面要做静态化。 定义了模板
t_page_config 每做一次页面静态化,都要添加一个对象。一个页面一次持久化所需要数据保存。

生成代码

此处省略

技术准备

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

Fastdfs

使用feign实现文件的上传和下载 放在公共的服务里面
Springcloud微服务项目——人力资源管理(HRM)Day08 页面静态化

hrm-common-common需要导入的依赖


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
1<!--客户端feign支持-->
2<dependency>
3    <groupId>org.springframework.cloud</groupId>
4    <artifactId>spring-cloud-starter-openfeign</artifactId>
5</dependency>
6<dependency>
7    <groupId>io.github.openfeign.form</groupId>
8    <artifactId>feign-form</artifactId>
9    <version>2.1.0</version>
10</dependency>
11<dependency>
12    <groupId>io.github.openfeign.form</groupId>
13    <artifactId>feign-form-spring</artifactId>
14    <version>2.1.0</version>
15</dependency>
16
17

hrm-common-client 模块
注意 这里使用的配置是我们自己的配置
configuration = FeignMultipartSupportConfig.class
FastDfsClient.java


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
1@FeignClient(value = "HRM-COMMON", configuration = FeignMultipartSupportConfig.class,
2        fallbackFactory = FastDfsClientFallbackFactory.class )
3@RequestMapping("/fastDfs")
4public interface FastDfsClient {
5    //上传
6    @PostMapping(produces = {MediaType.APPLICATION_JSON_UTF8_VALUE}
7            , consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
8    AjaxResult upload(@RequestPart(required = true,value = "file")MultipartFile file);
9
10
11    //下载 以Response来接收数据
12    @GetMapping
13     Response download(@RequestParam(required = true,value = "path") String path);
14}
15
16

FastDfsClientFallbackFactory.java


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
1@Component
2public class FastDfsClientFallbackFactory implements FallbackFactory<FastDfsClient> {
3    @Override
4    public FastDfsClient create(Throwable throwable) {
5        return new FastDfsClient() {
6            @Override
7            public AjaxResult upload(MultipartFile file) {
8                return new AjaxResult().setSuccess(false).setMessage("上传失败");
9            }
10
11            @Override
12            public Response download(String path) {
13                return null;
14            }
15        };
16    }
17}
18
19

FeignMultipartSupportConfig.java


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
1@Configuration
2public class FeignMultipartSupportConfig {
3
4    //form编码格式
5    @Bean
6    @Primary
7    @Scope("prototype")
8    public Encoder multipartFormEncoder() {
9        return new SpringFormEncoder();
10    }
11
12    @Bean
13    public feign.Logger.Level multipartLoggerLevel() {
14        return feign.Logger.Level.FULL;
15    }
16}
17
18

hrm-common-service-2090模块 上传下载的实现
需要导入的依赖


1
2
3
4
5
6
7
8
1<!-- https://mvnrepository.com/artifact/commons-io/commons-io -->
2<dependency>
3    <groupId>commons-io</groupId>
4    <artifactId>commons-io</artifactId>
5    <version>2.4</version>
6</dependency>
7
8

实现
FastDfsController.java


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
1@RestController
2@RequestMapping("/fastDfs")
3public class FastDfsController {
4    //crud 上传 下载(查看) 删除 修改(先删除后添加)
5    /**
6     * 参数:上传文件
7     * 返回值:成功与否,还要返回地址
8     */
9    @PostMapping(produces = {MediaType.APPLICATION_JSON_UTF8_VALUE}
10            , consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
11    public AjaxResult upload(@RequestPart(required = true,value = "file")MultipartFile file){
12        try {
13            System.out.println(file.getOriginalFilename() + ":" + file.getSize());
14            String originalFilename = file.getOriginalFilename();
15            // xxx.jpg
16            String extName = originalFilename.substring(originalFilename.lastIndexOf(".")+1);
17            System.out.println(extName);
18            String filePath =  FastDfsApiOpr.upload(file.getBytes(), extName);
19            return AjaxResult.me().setResultObj(filePath); //把上传后的路径返回回去
20        } catch (IOException e) {
21            e.printStackTrace();
22            return AjaxResult.me().setSuccess(false).setMessage("上传失败!"+e.getMessage());
23        }
24    }
25
26    //下载
27    @GetMapping
28    void download(@RequestParam(required = true,value = "path") String path, HttpServletResponse response){
29        ByteArrayInputStream bis = null;
30        ServletOutputStream outputStream = null;
31        try{
32            String pathTmp = path.substring(1); // goup1/xxxxx/yyyy
33            String groupName =  pathTmp.substring(0, pathTmp.indexOf("/")); //goup1
34            String remotePath = pathTmp.substring(pathTmp.indexOf("/")+1);// xxxxx/yyyy
35            System.out.println(groupName);
36            System.out.println(remotePath);
37            byte[] data = FastDfsApiOpr.download(groupName, remotePath);
38
39
40            //以流方式直接做响应 不需要返回Response
41            bis = new ByteArrayInputStream(data);
42            outputStream = response.getOutputStream();
43            IOUtils.copy(bis,outputStream);
44        }catch (Exception e
45        ){
46            e.printStackTrace();
47        }
48        finally {
49            if (outputStream != null) {
50                try {
51                    outputStream.close();
52                } catch (IOException e) {
53                    e.printStackTrace();
54                }
55            }
56            if (bis != null) {
57                try {
58                    bis.close();
59                } catch (IOException e) {
60                    e.printStackTrace();
61                }
62            }
63        }
64    }
65    /**
66     * 参数:完整路径 /goup1/xxxxx/yyyy
67     * 返回值:成功与否,还要返回地址
68     *
69     */
70    @DeleteMapping
71    public AjaxResult del(@RequestParam(required = true,value = "path") String path){
72        String pathTmp = path.substring(1); // goup1/xxxxx/yyyy
73        String groupName =  pathTmp.substring(0, pathTmp.indexOf("/")); //goup1
74        String remotePath = pathTmp.substring(pathTmp.indexOf("/")+1);// /xxxxx/yyyy
75        System.out.println(groupName);
76        System.out.println(remotePath);
77        FastDfsApiOpr.delete(groupName, remotePath);
78        return  AjaxResult.me();
79    }
80}
81
82

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


Velocity

Velocity是一个基于java的模板引擎(template engine),它允许任何人仅仅简单的使用模板语言(template language)来引用由java代码定义的对象。作为一个比较完善的模板引擎,Velocity的功能是比较强大的,但强大的同时也增加了应用复杂性。

准备模板

Springcloud微服务项目——人力资源管理(HRM)Day08 页面静态化

准备前端页面

Pager.vue
Springcloud微服务项目——人力资源管理(HRM)Day08 页面静态化

基本上的准备都已完成 接下来我们正式开始

页面静态化的整体流程

后端代码

搭建一个
hrm-page-parent模块

也是三个子模块
Springcloud微服务项目——人力资源管理(HRM)Day08 页面静态化

hrm-page-common模块放domain 和Query

导入依赖 其余两个模块也是依赖这个模块


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
1<dependencies>
2
3    <!--不能直接依赖starter,有自动配置,而消费者是不需要额。-->
4
5    <dependency>
6        <groupId>org.springframework.boot</groupId>
7        <artifactId>spring-boot-starter-web</artifactId>
8    </dependency>
9
10    <dependency>
11        <groupId>org.springframework.boot</groupId>
12        <artifactId>spring-boot-starter-test</artifactId>
13        <scope>test</scope>
14    </dependency>
15
16    <dependency>
17        <groupId>org.leryoo</groupId>
18        <artifactId>hrm-basic-util</artifactId>
19        <version>1.0-SNAPSHOT</version>
20    </dependency>
21
22    <!--不能全部引入mybatis-plus,这是要做数据库操作,这里是不需要的,只需引入核心包解决错误而已-->
23    <dependency>
24        <groupId>com.baomidou</groupId>
25        <artifactId>mybatis-plus</artifactId>
26        <version>2.2.0</version>
27    </dependency>
28</dependencies>
29
30

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


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
1spring:
2  profiles:
3    active: dev
4  cloud:
5    config:
6      name: application-page #github上面名称
7      profile: ${spring.profiles.active} #环境 java -jar -D xxx jar
8      label: master #分支
9      discovery:
10        enabled: true #从eureka上面找配置服务
11        service-id: hrm-config-server #指定服务名
12      #uri: http://127.0.0.1:1299 #配置服务器 单机配置
13eureka: #eureka不能放到远程配置中
14  client:
15    service-url:
16      defaultZone: http://localhost:1010/eureka  #告诉服务提供者要把服务注册到哪儿 #单机环境
17  instance:
18    prefer-ip-address: true #显示客户端真实ip
19feign:
20  hystrix:
21    enabled: true #开启熔断支持
22  client:
23    config:
24      remote-service:           #服务名,填写default为所有服务
25        connectTimeout: 3000
26        readTimeout: 3000
27hystrix:
28  command:
29    default:
30      execution:
31        isolation:
32          thread:
33            timeoutInMilliseconds: 3000
34
35

在码云的配置仓库中添加
application-page-dev.yml


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
1server:
2  port: 2030
3spring:
4  application:
5    name: hrm-page
6  datasource:
7    driver-class-name: com.mysql.jdbc.Driver
8    url: jdbc:mysql://localhost:3306/hrm-page
9    username: root
10    password: root
11mybatis-plus:
12  mapper-locations: classpath:org/leryoo/mapper/*Mapper.xml
13  type-aliases-package: org.leryoo.domain,org.leryoo.query
14
15

注意 记得要先提交到码云

然后是导入两个工具类
一个是文件解压的工具类
ZipUtil.java


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
1import java.io.*;
2import java.util.Enumeration;
3import java.util.zip.ZipEntry;
4import java.util.zip.ZipException;
5import java.util.zip.ZipFile;
6import java.util.zip.ZipOutputStream;
7
8public final class ZipUtil  
9{  
10  
11    /**
12     * 缓冲大小
13     */  
14    private static int BUFFERSIZE = 2 << 10;  
15      
16    /**
17     * 压缩
18     * @param paths
19     * @param fileName
20     */  
21    public static void zip(String[] paths, String fileName)  
22    {  
23          
24        ZipOutputStream zos = null;
25        try  
26        {  
27            zos = new ZipOutputStream(new FileOutputStream(fileName));
28            for(String filePath : paths)  
29            {  
30                //递归压缩文件  
31                File file = new File(filePath);  
32                String relativePath = file.getName();  
33                if(file.isDirectory())  
34                {  
35                    relativePath += File.separator;
36                }  
37                zipFile(file, relativePath, zos);  
38            }  
39        }  
40        catch (IOException e)
41        {  
42            e.printStackTrace();  
43        }  
44        finally  
45        {  
46            try  
47            {  
48                if(zos != null)  
49                {  
50                    zos.close();  
51                }  
52            }  
53            catch (IOException e)  
54            {  
55                e.printStackTrace();  
56            }  
57        }  
58    }  
59      
60    public static void zipFile(File file, String relativePath, ZipOutputStream zos)  
61    {  
62        InputStream is = null;
63        try  
64        {  
65            if(!file.isDirectory())  
66            {  
67                ZipEntry zp = new ZipEntry(relativePath);
68                zos.putNextEntry(zp);  
69                is = new FileInputStream(file);
70                byte[] buffer = new byte[BUFFERSIZE];  
71                int length = 0;  
72                while ((length = is.read(buffer)) >= 0)  
73                {  
74                    zos.write(buffer, 0, length);  
75                }  
76                zos.flush();  
77                zos.closeEntry();  
78            }  
79            else  
80            {  
81                for(File f: file.listFiles())  
82                {  
83                    zipFile(f, relativePath + f.getName() + File.separator, zos);  
84                }  
85            }  
86        }  
87        catch (IOException e)  
88        {  
89            e.printStackTrace();  
90        }  
91        finally  
92        {  
93            try  
94            {  
95                if(is != null)  
96                {  
97                    is.close();  
98                }  
99            }  
100            catch (IOException e)  
101            {  
102                e.printStackTrace();  
103            }  
104        }  
105    }  
106      
107    /**
108     * 解压缩
109     * @param fileName
110     * @param path
111     */  
112    public static void unzip(String fileName, String path)  
113    {  
114        FileOutputStream fos = null;  
115        InputStream is = null;  
116        try  
117        {  
118            ZipFile zf = new ZipFile(new File(fileName));
119            Enumeration en = zf.entries();
120            while (en.hasMoreElements())  
121            {  
122                ZipEntry zn = (ZipEntry) en.nextElement();  
123                if (!zn.isDirectory())  
124                {  
125                    is = zf.getInputStream(zn);  
126                    File f = new File(path + zn.getName());  
127                    File file = f.getParentFile();  
128                    file.mkdirs();  
129                    fos = new FileOutputStream(path + zn.getName());  
130                    int len = 0;  
131                    byte bufer[] = new byte[BUFFERSIZE];  
132                    while (-1 != (len = is.read(bufer)))  
133                    {  
134                        fos.write(bufer, 0, len);  
135                    }  
136                    fos.close();  
137                }  
138            }  
139        }  
140        catch (ZipException e)
141        {  
142            e.printStackTrace();  
143        }  
144        catch (IOException e)  
145        {  
146            e.printStackTrace();  
147        }  
148        finally  
149        {  
150            try  
151            {  
152                if(null != is)  
153                {  
154                    is.close();  
155                }  
156                if(null != fos)  
157                {  
158                    fos.close();  
159                }  
160            }  
161            catch (IOException e)  
162            {  
163                e.printStackTrace();  
164            }  
165        }  
166    }  
167      
168    /**
169     * @param args
170     */  
171//    public static void main(String[] args)
172//    {
173//        //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");
174//        //unzip("D://tmep.zip", "D:/temp/");
175//
176//        Map<String, Object> modelMap = new HashMap<>(); //封装两个参数作为一个对象传入进去
177//        String templatePagePath = "D://temp/home.vm.html"; //本地静态页面地址
178//        String staticRoot = "D://temp/";
179//        modelMap.put("staticRoot", staticRoot);
180//        modelMap.put("courseTypes", null);
181//        VelocityUtils.staticByTemplate(modelMap,"D://temp/home.vm",templatePagePath); //进行页面静态化
182//    }
183}  
184
185

一个是生成静态页面的工具类


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
1package org.leryoo.utils;
2
3import org.apache.velocity.Template;
4import org.apache.velocity.VelocityContext;
5import org.apache.velocity.app.Velocity;
6import org.apache.velocity.app.VelocityEngine;
7
8import java.io.*;
9import java.util.Properties;
10
11public class VelocityUtils {
12  private static Properties p = new Properties();
13  static {
14      p.setProperty(Velocity.FILE_RESOURCE_LOADER_PATH, "");
15      p.setProperty(Velocity.ENCODING_DEFAULT, "UTF-8");
16      p.setProperty(Velocity.INPUT_ENCODING, "UTF-8");
17      p.setProperty(Velocity.OUTPUT_ENCODING, "UTF-8");
18  }
19 
20  /**
21   * 返回通过模板,将model中的数据替换后的内容
22   * @param model
23   * @param templateFilePathAndName
24   * @return
25   */
26  public static String getContentByTemplate(Object model, String templateFilePathAndName){
27      try {
28          Velocity.init(p);
29          Template template = Velocity.getTemplate(templateFilePathAndName);
30          VelocityContext context = new VelocityContext();
31          context.put("model", model);
32          StringWriter writer = new StringWriter();
33          template.merge(context, writer);
34          String retContent = writer.toString();
35          writer.close();
36          return retContent;
37      } catch (Exception e) {
38          e.printStackTrace();
39      }
40      return "";
41  }
42
43  /**
44   * 根据模板,静态化model到指定的文件 模板文件中通过访问model来访问设置的内容
45   *
46   * @param model
47   *            数据对象
48   * @param templateFilePathAndName
49   *            模板文件的物理路径
50   * @param targetFilePathAndName
51   *            目标输出文件的物理路径
52   */
53  public static void staticByTemplate(Object model, String templateFilePathAndName, String targetFilePathAndName) {
54      try {
55          Velocity.init(p);
56          Template template = Velocity.getTemplate(templateFilePathAndName);
57         
58          VelocityContext context = new VelocityContext();
59          context.put("model", model);
60          FileOutputStream fos = new FileOutputStream(targetFilePathAndName);
61          BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(fos, "UTF-8"));// 设置写入的文件编码,解决中文问题
62          template.merge(context, writer);
63          writer.close();
64      } catch (Exception e) {
65          e.printStackTrace();
66      }
67  }
68
69  /**
70   * 静态化内容content到指定的文件
71   *
72   * @param content
73   * @param targetFilePathAndName
74   */
75  public static void staticBySimple(Object content, String targetFilePathAndName) {
76      VelocityEngine ve = new VelocityEngine();
77      ve.init(p);
78      String template = "${content}";
79      VelocityContext context = new VelocityContext();
80      context.put("content", content);
81      StringWriter writer = new StringWriter();
82      ve.evaluate(context, writer, "", template);
83      try {
84          FileWriter fileWriter = new FileWriter(new File(targetFilePathAndName));
85          fileWriter.write(writer.toString());
86          fileWriter.close();
87      } catch (IOException e) {
88          e.printStackTrace();
89      }
90  }
91}
92
93

然后写一个静态化的全家桶
Controller层


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
1@Autowired
2private IPageConfigService pageConfigService;
3
4@PostMapping("/pageStatic")
5AjaxResult staticPage(
6        @RequestParam(value = "pageName",required = true) String pageName,
7        @RequestParam(value = "dataKey",required = true)String dataKey){
8    try {
9        pageConfigService.staticPage(pageName,dataKey);
10        return AjaxResult.me();
11    } catch (Exception e) {
12        e.printStackTrace();
13        return AjaxResult.me().setMessage("静态化失败!"+e.getMessage());
14    }
15}
16
17

Service层 也是整个页面静态化的核心


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
1package org.leryoo.service.impl;
2
3import com.alibaba.fastjson.JSONObject;
4import com.baomidou.mybatisplus.mapper.EntityWrapper;
5import com.baomidou.mybatisplus.service.impl.ServiceImpl;
6import feign.Response;
7import org.apache.commons.fileupload.FileItem;
8import org.apache.commons.fileupload.FileItemFactory;
9import org.apache.commons.fileupload.disk.DiskFileItemFactory;
10import org.apache.commons.io.IOUtils;
11import org.leryoo.client.FastDfsClient;
12import org.leryoo.client.RedisClient;
13import org.leryoo.domain.PageConfig;
14import org.leryoo.domain.Pager;
15import org.leryoo.mapper.PageConfigMapper;
16import org.leryoo.mapper.PagerMapper;
17import org.leryoo.service.IPageConfigService;
18import org.leryoo.util.AjaxResult;
19import org.leryoo.utils.VelocityUtils;
20import org.leryoo.utils.ZipUtil;
21import org.springframework.beans.factory.annotation.Autowired;
22import org.springframework.stereotype.Service;
23import org.springframework.web.multipart.commons.CommonsMultipartFile;
24
25import java.io.*;
26import java.util.List;
27import java.util.Map;
28
29/**
30 * <p>
31 *  服务实现类
32 * </p>
33 *
34 * @author yhptest
35 * @since 2020-02-24
36 */
37@Service
38public class PageConfigServiceImpl extends ServiceImpl<PageConfigMapper, PageConfig> implements IPageConfigService {
39
40
41    @Autowired
42    private PagerMapper pagerMapper;
43
44    @Autowired
45    private FastDfsClient fastDfsClient;
46
47    @Autowired
48    private RedisClient redisClient;
49
50    @Autowired
51    private PageConfigMapper pageConfigMapper;
52    //正在做页面静态化
53    @Override      //courseTypes- xxx jobTypes=yyy
54    public void staticPage(String pageName, String dataKey){
55        InputStream inputStream = null;
56        FileOutputStream os = null;
57        try{
58            //一 通过pageName获取Page并从中获取模板 url(zip)+name(home.vm)
59            //1.1 查询page对象
60            List<Pager> pagers = pagerMapper.selectList(new EntityWrapper<Pager>().eq("name", pageName));
61            if (pagers == null || pagers.size()<1) return;
62            Pager pager = pagers.get(0);
63            //1.2 获取模板zip包,它是fastdfs的地址
64            String templateUrl = pager.getTemplateUrl();
65            //1.3 使用fastdfsclient下载它
66            Response response = fastDfsClient.download(templateUrl);
67            inputStream = response.body().asInputStream();
68            String tmpdir=System.getProperty("java.io.tmpdir"); //跨操作系统
69            String unzipFile = tmpdir+"/temp.zip";
70            os = new FileOutputStream(unzipFile);
71            IOUtils.copy(inputStream, os);
72            System.out.println("下载路径:" + unzipFile);
73            //1.4 解压缩
74            String unzipDir = tmpdir+"/temp/";
75            ZipUtil.unzip(unzipFile,unzipDir);
76            System.out.println("解压路径:" + unzipDir);
77            //1.5 解压路径拼接模板名称得到完整的模板地址
78            String tempatePath = unzipDir+"/"+pager.getTemplateName(); //c://temp/home.vm
79            System.out.println("模板路径:" + tempatePath);
80            //二  通过dataKey获取数据
81            //{"courseTypes":[]}
82            String jsonStr = redisClient.get(dataKey);
83            Map model = JSONObject.parseObject(jsonStr,Map.class); //获取传递的map数据
84            //{"courseTypes":[],"staticRoot":"xxx"}
85            model.put("staticRoot",unzipDir); // 往map里面追加参数
86            //三  做页面静态化到本地
87            String staticPath = tempatePath+".html";//c://temp/home.vm.html
88            System.out.println("静态化页面地址:"+staticPath);
89            VelocityUtils.staticByTemplate(model,tempatePath,staticPath);
90
91            //四 把静态化好的页面上传到fast   dfs
92            AjaxResult ajaxResult = fastDfsClient
93                    .upload(new CommonsMultipartFile(createFileItem(new File(staticPath))));
94
95            //五 存放pageConfig
96            PageConfig pageConfig = new PageConfig();
97            pageConfig.setTemplateUrl(templateUrl);
98            pageConfig.setTemplateName(pager.getTemplateName());
99            pageConfig.setDataKey(dataKey);
100            pageConfig.setPhysicalPath(pager.getPhysicalPath());
101            pageConfig.setDfsType(0L); //0表示fastDfs
102            pageConfig.setPageUrl((String) ajaxResult.getResultObj()); //上传完的地址
103            pageConfig.setPageId(pager.getId());
104            pageConfigMapper.insert(pageConfig);
105            //@TODO 六 发送Message到mq中
106        }catch (Exception e){
107            e.printStackTrace();
108        }finally {
109
110            if (os != null) {
111                try {
112                    os.close();
113                } catch (IOException e) {
114                    e.printStackTrace();
115                }
116            }
117            if (inputStream != null) {
118                try {
119                    inputStream.close();
120                } catch (IOException e) {
121                    e.printStackTrace();
122                }
123            }
124        }
125
126    }
127
128    /*
129创建FileItem
130*/
131    private FileItem createFileItem(File file) {
132        FileItemFactory factory = new DiskFileItemFactory(16, null);
133        String textFieldName = "textField";
134        FileItem item = factory.createItem("file", "text/plain", true, file.getName());
135        int bytesRead = 0;
136        byte[] buffer = new byte[8192];
137        try {
138            FileInputStream fis = new FileInputStream(file);
139            OutputStream os = item.getOutputStream();
140            while ((bytesRead = fis.read(buffer, 0, 8192)) != -1) {
141                os.write(buffer, 0, bytesRead);
142            }
143            os.close();
144            fis.close();
145        } catch (IOException e) {
146            e.printStackTrace();
147        }
148        return item;
149    }
150
151}
152
153
154

hrm-page-client
page客户端 通过feign完成服务之间的调用 将这个服务暴露出去
导入依赖


1
2
3
4
5
6
7
8
9
10
11
12
13
1<dependency>
2    <groupId>org.leryoo</groupId>
3    <artifactId>hrm-page-common</artifactId>
4    <version>1.0-SNAPSHOT</version>
5</dependency>
6
7<!--客户端feign支持-->
8<dependency>
9    <groupId>org.springframework.cloud</groupId>
10    <artifactId>spring-cloud-starter-openfeign</artifactId>
11</dependency>
12
13

PageConfigClient.java


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
1@FeignClient(value = "HRM-PAGE",fallbackFactory = PageConfigClientFallbackFactory.class  )//服务提供
2@RequestMapping("/pageConfig")
3public interface PageConfigClient {
4    /**
5     * 有了pageName就可以获取模块
6     * 有了datakey就可以获取数据
7     * @param pageName
8     * @param dataKey
9     * @return
10     */
11    @PostMapping("/pageStatic")
12    AjaxResult staticPage(
13            @RequestParam(value = "pageName",required = true) String pageName,
14            @RequestParam(value = "dataKey",required = true)String dataKey);
15}
16
17

PageConfigClientFallbackFactory.java


1
2
3
4
5
6
7
8
9
10
11
12
13
14
1@Component
2public class PageConfigClientFallbackFactory implements FallbackFactory<PageConfigClient> {
3    @Override
4    public PageConfigClient create(Throwable throwable) {
5        return new PageConfigClient() {
6            @Override
7            public AjaxResult staticPage(String pageName, String dataKey) {
8                return AjaxResult.me().setSuccess(false).setMessage("静态化失败!");
9            }
10        };
11    }
12}
13
14

前端准备

我们可以通过页面点击按钮 或者测试方法生成静态页面 这里我们选择用页面点击按钮的方式

首先 我们先创建一个页面 只加一个按钮
Springcloud微服务项目——人力资源管理(HRM)Day08 页面静态化
前端代码
Springcloud微服务项目——人力资源管理(HRM)Day08 页面静态化

课程中心的代码


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
1/**
2 * 页面静态化方法
3 */
4@PostMapping("/staticIndexPageInit")
5public AjaxResult staticIndexPageInit()
6{
7    try{
8        courseTypeService.staticIndexPageInit();
9        //调用页面静态化的逻辑
10        return AjaxResult.me();
11    }catch (Exception e){
12        e.printStackTrace();
13        return AjaxResult.me().setSuccess(false).setMessage(e.getMessage());
14    }
15}
16
17

Service层 通过feign去调用page模块的方法 完成静态页面的生成


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
1@Override
2public void staticIndexPageInit() {
3
4    //1页面名称写死,约定大于配置
5    String pageName = "CourseSiteIndex";
6
7    //2 需要一个保存到redis数据库的key
8    String dataKey="CourseSiteIndex_data";
9    //本来就是从redis获取,还要在放一次,其他页面静态化的场景不一定有缓冲
10    List<CourseType> courseTypes = this.treeData(0L);
11    //课程处理
12    Map<String,Object> courseTypeSdata = new HashMap<>();
13    courseTypeSdata.put("courseTypes",courseTypes);
14    //职位
15    redisClient.add(dataKey, JSONArray.toJSONString(courseTypeSdata)); //{courseTypes:[]}
16
17    //3 调用方法模板+数据=静态页面
18    pageConfigClient.staticPage(pageName,dataKey);
19}
20
21

然后点击按钮 就会在临时文件夹里生成
Springcloud微服务项目——人力资源管理(HRM)Day08 页面静态化
这也就ok了

给TA打赏
共{{data.count}}人
人已打赏
安全网络

CDN安全市场到2022年价值76.3亿美元

2018-2-1 18:02:50

安全技术

Hook改变的React Component写法思路(3) - useContext

2021-12-21 16:36:11

个人中心
购物车
优惠劵
今日签到
有新私信 私信列表
搜索