网站性能优化,使用velocity实现页面静态化,实现实时更新静态页面

使用velocity实现页面静态化可以提高网站的性能,但是生成的静态页面怎么做到实时更新呢?

1、最笨的方式,手动刷新.
例如:网站首页,当管理员更新一个功能之后,手动点击后台的一个按钮直接更新对应的html文件
2、定时刷新。
每隔一段指定的时间去更新所有已经存在的html文件,当然前提是你要先验证哪些已经生成了html文件.至于怎么验证?你可以在每生成一个文件的时候往内存的某个list或者某个文件,或者某个表写入当前生成的文件名
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;
    }
很多细节还待优化,先这样记录下来吧,花了我半天时间弄这个!


你可能感兴趣的:(velocity)