页面静态化,就是将原本用户访问的url后的最终结果转换为静态页面 (可以是html) ,那么用户在以后的访问直接访问静态页面即可,这样就可以避免中间访问网络或是数据库的过程,从而降低了服务器压力。
github地址
<dependencies>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-testartifactId>
<scope>testscope>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-thymeleafartifactId>
dependency>
<dependency>
<groupId>org.apache.httpcomponentsgroupId>
<artifactId>httpclientartifactId>
<version>4.5.6version>
dependency>
dependencies>
application.yml
spring:
thymeleaf:
prefix: classpath:/templates/
suffix: .html
encoding: UTF-8
check-template-location: true
servlet:
content-type: text/html
mode: HTML
cache: false
创建一个User对象
package com.dfyang.staticizepage.pojo;
/**
* 用户
*/
public class User {
private String username;
private String password;
public User() {
}
public User(String username, String password) {
this.username = username;
this.password = password;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
创建一个动态页面(这里用到了themeleaf,其他的也无所谓)
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>用户title>
head>
<body>
<table>
<tr>
<td>用户名:td>
<td th:text="${user.username}">td>
tr>
<tr>
<td>密码:td>
<td th:text="${user.password}">td>
tr>
table>
body>
html>
创建controller层
package com.dfyang.staticizepage.controller;
import com.dfyang.staticizepage.pojo.User;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
@Controller
public class UserController {
@GetMapping("/user")
public String user(Model model) {
// 模拟从数据库中查询用户
User user = new User("user", "upass");
model.addAttribute("user", user);
return "/user";
}
}
启动项目,访问 http://localhost:8080/user
下面显示的就是要生成的静态页面,非常的简单,真实生成的可能有非常多的图片和文字,如果并发量大的化,会占用较大的网络服务器带宽,所以需要页面静态化处理。(注意:页面的多少与静态化步骤没有任何关系)
创建StaticizePageUtil工具类,生成静态页面的具体逻辑
package com.dfyang.staticizepage.utils;
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.springframework.util.ResourceUtils;
import java.io.*;
/**
* 静态化页面工具类
*/
public class StaticizePageUtil {
/** 生成静态文件的根路径 */
private static String basePath;
static {
try {
basePath = ResourceUtils.getFile("classpath:templates").getAbsolutePath() + "\\static\\";
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
/**
* 生成静态页面
* @param url 生成静态页面的url
* @param filePath 生成静态页面的路径
*/
public static void staticize(String url, String filePath) {
CloseableHttpClient httpClient = HttpClients.createDefault();
HttpGet httpGet = new HttpGet(url);
CloseableHttpResponse response = null;
HttpEntity entity = null;
Writer writer = null;
try {
// 1) 通过HttpClient访问url
response = httpClient.execute(httpGet);
entity = response.getEntity();
if (entity != null) {
String entityStr = EntityUtils.toString(entity); // 将请求获取到的页面信息转换为字符串
File file = new File(basePath + filePath);
System.err.printf(basePath + filePath); // 这里将路径输出一下
File baseDirs = new File(basePath);
if (!baseDirs.exists())
baseDirs.mkdirs(); // 如果生成文件夹不存在则创建
if (!file.exists())
file.createNewFile(); // 如果目标文件夹不存在则创建
writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file), "UTF-8"));
// 2) 将访问url获取的内容输出到指定文件
writer.write(entityStr);
writer.flush();
}
} catch (IOException e) {
e.printStackTrace();
} finally {
// 3) 关闭资源
try {
if (entity != null)
EntityUtils.consume(entity);
if (writer != null)
writer.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
注意:如果是webapp/WEB-INF/目录的,可以通过
request.getSession().getServletContext().getRealPath("/WEB-INF/jsp/user/");进行获取。
request可以通过@Autowired private HttpServletRequest request直接注入,传递也行,这里很好改就不演示了。
可以在controller层添加下面方法,访问 http://localhost:8080/generate
@GetMapping("/generate")
@ResponseBody
public String generate() {
StaticizePageUtil.staticize("http://localhost:8080/user", "user.html");
return "生成静态页面成功";
}
到这里已经生成好了静态文件,那么如何让用户访问静态页面
只需要改写controller,让用户直接访问静态页面,而真正访问数据源的让HttpClient进行访问
@GetMapping("/user")
public String user(Model model) {
return "/static/user";
}
@GetMapping("/staticizeUser")
public String staticizeUser(Model model) {
// 模拟从数据库中查询用户
User user = new User("user", "upass");
model.addAttribute("user", user);
return "/user";
}
如果页面有时会变化,我们可能需要定时去刷新我们的静态页面
在启动类上加上@EnableScheduling注解
package com.dfyang.staticizepage;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableScheduling;
@SpringBootApplication
@EnableScheduling
public class StaticizePageApplication {
public static void main(String[] args) {
SpringApplication.run(StaticizePageApplication.class, args);
}
}
修改application.yml,添加如下
custom:
user:
url: http://localhost:8080/user
file: user.html
创建定时任务,这样在我们启动项目就会定时为我们刷新静态页面
package com.dfyang.staticizepage.task;
import com.dfyang.staticizepage.utils.StaticizePageUtil;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
/**
* 静态化用户界面
*/
@Component
public class StaticizeUserHtmlTask {
@Value("${custom.user.url}")
private String url;
@Value("${custom.user.file}")
private String file;
@Scheduled(fixedRate = 300000)
public void generateStaticJSP() {
System.out.printf("生成静态页面");
StaticizePageUtil.staticize(url, file);
}
}