静态化

Posted Ryan

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了静态化相关的知识,希望对你有一定的参考价值。

静态化是在项目中比较常见的一种技术,实现起来也非常简单。无非就是先将访问的资源保存为html文件,访问时优先访问html。不过在静态化之前还需要做一些准备工作。

1.将访问路径编写成rest风格的,如下:

@RequestMapping("/index/{moduleId}/{reportId}")

 

2.将ajax请求尽可能的转化成同步加载的,这样静态化的时候才会尽可能多的静态化数据,当然是用ajax也可以,只不过是用ajax的数据就不会被静态化了。

 

3.提前将所有界面都生成html文件,这里是用了spring的定时任务根据自己的实际情况更新数据。我们的数据仓库每天晚上更新一次,所以我们这里的静态化的线上定时时间也是每天晚上在数据仓库更新了之后运行,静态化了之后减轻了数据库和服务器的压力,访问速度当然也快了好几倍

1 <dependency>
2   <groupId>commons-httpclient</groupId>
3   <artifactId>commons-httpclient</artifactId>
4   <version>3.1</version>
5 </dependency>
httpclient依赖

 

  1 package com.demo.task;
  2 
  3 import java.io.File;
  4 import java.io.FileOutputStream;
  5 import java.io.IOException;
  6 import java.util.HashMap;
  7 import java.util.List;
  8 import java.util.Map;
  9 
 10 import org.apache.commons.httpclient.HttpClient;
 11 import org.apache.commons.httpclient.methods.GetMethod;
 12 import org.apache.log4j.Logger;
 13 import org.springframework.beans.factory.annotation.Autowired;
 14 import org.springframework.context.support.GenericXmlApplicationContext;
 15 import org.springframework.scheduling.annotation.Scheduled;
 16 import org.springframework.stereotype.Component;
 17 import org.springframework.test.context.ContextConfiguration;
 18 
 19 import com.demo.controller.paramvo.DataReportParam;
 20 import com.demo.entity.DataModule;
 21 import com.demo.entity.DataReport;
 22 import com.demo.service.IDataModuleService;
 23 import com.demo.service.IDataReportService;
 24 
 25 /**
 26  * 静态化
 27  */
 28 @Component
 29 @ContextConfiguration(locations = "/applicationContext.xml")
 30 public class StaticHtml {
 31 
 32 
 33     private Logger logger = Logger.getLogger(StaticHtml.class);
 34     /** 静态化URL */
 35     public String static_url = "/dpf/main/index/${moduleId}/${reportId}"; 
 36     /** 静态化界面名称 */
 37     public static String static_name = "main_index_${moduleId}_${reportId}.html"; 
 38     /** 判断是否是windows系统 */
 39     public final static boolean IS_LOCAL = System.getProperty("os.name").startsWith("win")||System.getProperty("os.name").startsWith("Win");
 40     /** 网址(可以考虑IP,指定WEB来处理) */
 41     private final String LOGON_SITE = IS_LOCAL?"172.16.5.16":"192.168.99.96";;
 42     /** 端口 */
 43     private final int LOGON_PORT = IS_LOCAL?8080:8080;;
 44     private HttpClient client = new HttpClient();
 45     /** 运行锁 */
 46     public boolean EXEC_LOCK = false;
 47     public static String static_root = "/templates/temp/";
 48     /** 静态页面存放根目录 */
 49     private final static String INDEX_HOME_ROOT = IS_LOCAL?"/home/admin/view"+static_root
 50             :"/home/admin/view"+static_root;
 51     
 52     /** 同步文件shell脚本 */
 53     private String scp_command = "scp -r /home/admin/view/templates/temp/ 192.168.99.97:/home/admin/view/templates/";
 54     /** 静态化列表 URL - 是否静态化  1-是 0-否 */
 55     public HashMap<String,Integer> static_html = new HashMap<String,Integer>();
 56     private GenericXmlApplicationContext context = new GenericXmlApplicationContext(); 
 57     /** 模块 */
 58     @Autowired private IDataModuleService dataModuleService;
 59     /** 报表  */
 60     @Autowired private IDataReportService dataReportService;
 61     /**  
 62      * @功能描述: 初始化client 
 63      * @创建作者: **
 64      * @创建日期: 2016年10月17日 下午2:16:14
 65      */ 
 66     public void createClient(){
 67         client.getHostConfiguration().setHost(LOGON_SITE, LOGON_PORT);
 68     }
 69     
 70     /**  
 71      * @功能描述: 添加URL
 72      * @param moduleId 模块id
 73      * @param reportId 报表id
 74      */ 
 75     private void addUrl(String moduleId, String reportId){
 76         static_html.put(static_url.replace("${moduleId}", moduleId)
 77                 .replace("${reportId}", reportId),0);
 78     }
 79     
 80     /**  
 81      * @功能描述: 初始化URL
 82      */ 
 83     private void initUrl(){
 84         List<DataModule> modules = dataModuleService.queryAll();
 85         for(int i=0; i< modules.size(); i++) {
 86             Long moduleId = modules.get(i).getId();
 87             DataReportParam vo = new DataReportParam();
 88             vo.setModuleId(moduleId);
 89             List<DataReport> reports = dataReportService.queryList(vo);
 90             for(int j=0; j< reports.size(); j++) {
 91                 Long reportId = reports.get(j).getId();
 92                 addUrl(moduleId.toString(), reportId.toString());
 93             }
 94         }
 95     }
 96     
 97     /**  
 98      * @throws IOException 
 99      * @功能描述: 首页静态化任务 30MIN执行一次(根据访问量来设置更新时间)
100      * @创建作者: **
101      * @创建日期: 2016年10月17日 下午2:15:53
102      */ 
103     @Scheduled(cron="* 0/30 * * * ?") 
104     public synchronized void exec() throws IOException {
105         EXEC_LOCK=true;
106         long s = System.currentTimeMillis();
107         logger.info("-----------首页缓存开始-----------");
108         createClient();
109         //初始化需要静态化界面的url
110         static_html = new HashMap<String,Integer>();
111         initUrl();
112         File folder = new File(INDEX_HOME_ROOT);
113         if(!folder.exists()) 
114             folder.mkdirs();
115         int i=0;
116         int a=static_html.size();
117           logger.info("共计缓存界面"+a+"个");
118           System.out.println("共计缓存界面"+a+"个");
119         for (Map.Entry<String, Integer> entry : static_html.entrySet()) {
120             i++;
121             String url = entry.getKey();
122             Integer is_static = entry.getValue();
123             Integer p = (int) (Double.valueOf(i)/a*100);
124               logger.info(url+" 成功("+p+"%)");
125               System.out.println(url+" 成功("+p+"%)");
126               if(is_static!=1){
127                 GetMethod get = new GetMethod(url);
128                 //模拟表单元素
129                 File file = null;
130                 FileOutputStream is = null;
131                   try {
132                       String moduleId = url.split("/")[4];
133                       String reportId = url.split("/")[5];
134                       String fileName = static_name.replace("${moduleId}", moduleId).replace("${reportId}", reportId);
135                     file = new File(INDEX_HOME_ROOT+fileName);
136                     is = new FileOutputStream(file);
137                       int status = client.executeMethod(get);
138                       if(status>=200&&status<400){
139                           String html = get.getResponseBodyAsString();
140                           is.write(html.getBytes());
141                           logger.info(url+" 成功("+p+"%)");
142                       }else{
143                           logger.info(url+" 失败("+p+"%)");
144                       }
145                   } catch (Exception e) {
146                       logger.error("首页缓存失败",e);
147                 } finally{
148                     if(is != null){
149                         is.flush();
150                           is.close();
151                     }
152                 }
153                 entry.setValue(1);
154             }
155         }
156 
157         logger.info("-----------缓存结束-----------");
158         long e = System.currentTimeMillis();
159         logger.info("-----------耗时:"+(e-s)/1000+"秒-----------");
160         EXEC_LOCK=false;
161     }
162     
163     /**  
164      * @功能描述: 判断缓存界面是否存在
165      * @创建作者: **
166      * @创建日期: 2016年10月17日 下午3:05:26
167      * @param cityCode
168      * @return
169      */ 
170     public static boolean existsStatic(Long moduleId, Long reportId){
171         String fileName = static_name.replace("${moduleId}", moduleId.toString()).replace("${reportId}", reportId.toString());
172         File file = new File(INDEX_HOME_ROOT+fileName);
173         if(file.exists() && file.length()>0){
174             return true;
175         }
176         return false;
177     }
178     
179     /**  
180      * @功能描述: 调用静态化界面
181      * @创建作者: **
182      * @创建日期: 2016年9月29日 下午4:47:06
183      * @param args
184      */ 
185     public void main(String[] args) {
186         try {
187             context = new GenericXmlApplicationContext();  
188             context.setValidating(false);  
189             context.load("classpath*:applicationContext*.xml");  
190             context.refresh();  
191             dataModuleService = context.getBean(IDataModuleService.class); 
192             dataReportService = context.getBean(IDataReportService.class); 
193             exec();
194             if(!IS_LOCAL){
195                 //同步文件夹
196                 Runtime.getRuntime().exec(scp_command);
197             }
198         } catch (Exception e) {
199             logger.error("静态化失败", e);
200         }
201     }
202 
203 }
静态化工具类

 

4.访问控制,如果存在静态化界面则访问静态化页面

 1 @RequestMapping("/index/{moduleId}/{reportId}")
 2     public ModelAndView index(@PathVariable Long moduleId, @PathVariable Long reportId) {
 3         ModelAndView result = new ModelAndView("main/index");
 4         
 5         //判断是否静态化
 6         if (StaticHtml.existsStatic(moduleId, reportId)) {
 7             String static_name = StaticHtml.static_name.replace("${appId}", moduleId.toString())
 8             .replace("${appType}", reportId.toString()).replace(".html", "");
 9             result.setViewName(StaticHtml.static_root+static_name);
10             return result;
11         }
12                 //do something
13                 return result;
14 }
静态化访问控制

 

仅供参考,不足之处还请见谅,欢迎指正!转载请标明出处。如有疑问,欢迎评论或者联系我邮箱1034570286@qq.com

以上是关于静态化的主要内容,如果未能解决你的问题,请参考以下文章

如何在 python 中并行化以下代码片段?

支持动态或静态片段的不同屏幕尺寸?

片段事务中的实例化错误

片段内部静态类和gradle问题

为啥保守光栅化无法为某些三角形调用片段着色器?

片段 null 必须是公共静态类才能从实例状态正确重新创建