使用velocity实现页面静态化可以提高网站的性能,但是生成的静态页面怎么做到实时更新呢?
1、最笨的方式,手动刷新.
例如:网站首页,当管理员更新一个功能之后,手动点击后台的一个按钮直接更新对应的html文件
2、定时刷新。
每隔一段指定的时间去更新所有已经存在的html文件,当然前提是你要先验证哪些已经生成了html文件.至于怎么验证?你可以在每生成一个文件的时候往内存的某个list或者某个文件,或者某个表写入当前生成的文件名
3、智能刷新
被观察者:
观察者,观察用户做了什么操作,然后更新或者删除、生成html页面
生成静态页面:
生成静态页面通用方法:
静态页面生成成功后访问静态资源:
3、智能刷新
管理员在后台的每个操作 增删改查,都进行监听,并在操作完成后去验证一下对应的文件是否存在,存在就更新,不存在就不操作
使用第三智能刷新明显科学一点,使用第三种方法我们就需要使用到 设计模式中的——观察者模式
初始化velocity的配置:
package com.wwxl.filter;
import java.io.IOException;
import java.util.Properties;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import org.apache.velocity.app.Velocity;
import com.wwxl.servletcontext.FConfig;
/**
* Servlet Filter implementation class SetCodeFilter
*/
public class SetCodeFilter implements Filter {
/**
* Default constructor.
*/
public SetCodeFilter() {
// TODO Auto-generated constructor stub
}
/**
* @see Filter#destroy()
*/
public void destroy() {
// TODO Auto-generated method stub
}
/**
* @see Filter#doFilter(ServletRequest, ServletResponse, FilterChain)
*/
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
// TODO Auto-generated method stub
// place your code here
// pass the request along the filter chain
chain.doFilter(request, response);
}
/**
* @see Filter#init(FilterConfig)
*/
@SuppressWarnings("static-access")
public void init(FilterConfig fConfig) throws ServletException {
//初始化velocity配置
Properties properties=new Properties();
//指定velocity日志存放位置
properties.put("runtime.log",fConfig.getServletContext().getRealPath("/WEB-INF/log/velocity_example.log"));
//指定模板存放的位置
properties.put("file.resource.loader.path",fConfig.getServletContext().getRealPath("/WEB-INF/velocity/"));
properties.put("input.encoding","UTF-8");
properties.put("default.contentType","text/html;charset\\=UTF-8");
properties.put("output.encoding","UTF-8 ");
Velocity.init(properties);
//初始化时获取servletcontext,在java 代码里面会用到这个servletcontext来获取服务器的相对路径
FConfig fc=new FConfig();
fc.setServletcontext(fConfig.getServletContext());
}
}
package com.wwxl.servletcontext;
import javax.servlet.ServletContext;
/**
* 获取servletcontext,生命周期是 从servletContext创建到服务器关闭
* @author Administrator
*
*/
public class FConfig {
public static ServletContext servletcontext;
public static ServletContext getServletcontext() {
return servletcontext;
}
public static void setServletcontext(ServletContext servletcontext) {
FConfig.servletcontext = servletcontext;
}
}
被观察者:
package com.wwxl.service.impl;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Observable;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.wwxl.dao.UserDao;
import com.wwxl.entity.User;
import com.wwxl.observer.UserServiceimplObserver;
import com.wwxl.service.UserService;
//被观察对象 继承observable
@Service
@Transactional
public class UserServiceimpl extends Observable implements UserService{
@Autowired
@Qualifier("userDao")
private UserDao userDao;
/**
* 添加用户
*/
public boolean sva(User user) {
boolean falg=this.userDao.sva(user);
if(falg)
{
Map<String,Object> maps=new HashMap<String, Object>();
maps.put("falg","save");
maps.put("user",user);
//标记此 Observable 对象为已改变的对象;现在 hasChanged 方法将返回 true。
this.setChanged();
//如果 hasChanged 方法指示对象已改变,则通知其所有观察者,并调用 clearChanged 方法来指示此对象不再改变,maps是更改的内容
this.notifyObservers(maps);
}
return falg;
}
/**
* 查询用户
*/
public List<User> findAll() {
return this.userDao.findAll();
}
/**
* 根据id查询用户
*/
public User findUserById(String id) {
return this.userDao.getById(id);
}
//注册观察者,一个 observable 对象可以有一个或多个观察者。观察者可以是实现了 Observer 接口的任意对象
public UserServiceimpl(){
//注册观察者
this.addObserver(new UserServiceimplObserver());
}
}
观察者,观察用户做了什么操作,然后更新或者删除、生成html页面
package com.wwxl.observer;
import java.util.Map;
import java.util.Observable;
import java.util.Observer;
import com.wwxl.entity.User;
import com.wwxl.servletcontext.FConfig;
import com.wwxl.util.JHtmlVelocityGenerator;
//观察者,观察用户发生改变就生成静态页面
public class UserServiceimplObserver extends FConfig implements Observer{
//观察用户是否修改了数据
@SuppressWarnings("unchecked")
public void update(Observable o, Object arg) {
Map<String,Object> maps=(Map<String, Object>)arg;
String falg=(String) maps.get("falg");
System.out.println("对用户做了什么操作:"+falg);
User user=(User) maps.get("user");
boolean falgs=JHtmlVelocityGenerator.JHtmlVelocityGenerators(getServletcontext(), user, "mytemplates.html","res/template");
if(falgs)
{
System.out.println("生成静态页面成功");
}
else
{
System.out.println("生成静态页面失败");
}
}
}
生成静态页面:
package com.wwxl.util;
import java.io.File;
import javax.servlet.ServletContext;
import org.apache.velocity.VelocityContext;
import com.wwxl.constant.ClassConstant;
import com.wwxl.entity.User;
public class JHtmlVelocityGenerator extends HtmlVelocityGenerator {
/**
* 生成静态页面
* @param servletcontext servlert上下文
* @param entity 修改的对象
* @param templateName 模板名称
* @param savePath 存放路径
*/
public static boolean JHtmlVelocityGenerators(ServletContext servletcontext,User user,String templateName,String savePath) {
boolean falg=false;
// 获得相对路径
String realPath =servletcontext.getRealPath(savePath);
File savefiles = new File(realPath);
if (!savefiles.exists())
savefiles.mkdirs();
String htmlName=ClassConstant.HTML_PREFIX+user.getId();
VelocityContext context = new VelocityContext();
context.put("user",user);
falg=HtmlVelocityGenerator.HtmlCreate(savefiles, templateName, htmlName, context);
return falg;
}
}
生成静态页面通用方法:
package com.wwxl.util;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStreamWriter;
import org.apache.velocity.Template;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.Velocity;
/**
* velocity静态页面生成通用类
* @author 邓文伟
*
*/
public class HtmlVelocityGenerator{
/**
* 静态页面生成器
* @param savefiles 生成的html页面保存的路径
* @param templateName 模板名称
* @param htmlName 生成的html名称
* @param context velocity上下文
* @return
*/
public static boolean HtmlCreate(File savefiles,String templateName,String htmlName,VelocityContext context) {
try {
Template template = Velocity.getTemplate(templateName);
File savefile = new File(savefiles,htmlName+".html");
FileOutputStream outstream = new FileOutputStream(savefile);
OutputStreamWriter writer = new OutputStreamWriter(outstream,"UTF-8");
BufferedWriter bufferWriter = new BufferedWriter(writer);
template.merge(context, bufferWriter);
bufferWriter.flush();
outstream.close();
bufferWriter.close();
return true;
}catch (Exception e) {
e.printStackTrace();
return false;
}
}
public static void main(String[] args) {
//HtmlVelocityGenerator.HtmlCreate("c:/");
}
}
静态页面生成成功后访问静态资源:
/**
* 查询静态资源
* @param request
* @param response
* @param id
* @return
*/
@RequestMapping({ "/userIds.htm" })
public ModelAndView userByIds(HttpServletRequest request,
HttpServletResponse response, String id) {
ModelAndView mv = new JModelAndView(null, request, response);
// 获得要生成的静态html文件的名字
String htmlName =HTML_PREFIX + id + ".html";
mv.setViewName(CONTEXT_RES_TEMPLATE+htmlName);
return mv;
}
很多细节还待优化,先这样记录下来吧,花了我半天时间弄这个!