网站性能提升

一、使用Velocity模板生成静态网页
1.什么是velocity
Velocity是一个基于java的模板引擎(template engine)。它允许任何人仅仅简单的使用模板语言(template language)来引用由java代码定义的对象。
2.基本的jar包
Velocity-1.6.jar包+commons-collections-3.2.1.jar包+commons-lang-2.4.jar包+oro-2.0.8.jar包。(当然我们也可以只导入velocity-1.6-dep.jar包代替前面四个jar包,但是如果是与其它框架集成需注意jar包引起的冲突问题)除此之外还应导入日志包:Lib/log4j-1.2.12.jar包。
3.使用velocity的步骤
步骤一、在src目录下建立velocity.properties文件,内容如下:
##指定日志文件存放位置
runtime.log=D:/velocity/logfile.log
##指定模板文件加载位置
file.resource.loader.path=D:/workspace/veloctiy/vm
##指定输入编码格式
input.encoding=UTF-8
##指定velocity的servlet向浏览器输出内容的编码
default.contentType=text/html/:charset/=UTF-8
##指定输出编码格式
output.encoding=UTF-8
步骤二、在D:/workspace/veloctiy/vm目录下建立模板文件base.vm.
步骤三、建立测试类Base.java,主要代码如下:
Velocity.init("src/velocity.properties");
VelocityContext context = new VelocityContext();
context.put("who", "张三");
context.put("what", "你好");
Template template = Velocity.getTemplate("base.vm");
StringWriter sw = new StringWriter();
template.merge(context, sw);
sw.flush();
System.out.println(sw.toString());
步骤四、依据上面的测试代码,编写base.vm的代码如下:
${who} 说 ${what}
步骤五、完成测试,在控制台输出内容。需要注意的事项,velocity.properties文件中相关项的配置,特别是注意文件的编码及相关的文件路径的书写方式。
步骤六、其它测试
在测试类的context对象中增加如下代码:
// 对象类型
User u = new User("admin");
context.put("user", u);
// list对象迭代
List<String> names = new ArrayList<String>();
names.add("张三");
names.add("李四");
names.add("王五");
context.put("list", names);
// 迭代map对象
Map<String, String> map = new HashMap<String, String>();
map.put("first", "one");
map.put("secod", "two");
map.put("third", "three");
context.put("map", map);
// if|else测试
context.put("condition", true);
// 对象null解决方案:$!person-->加!
context.put("person", null);
随后在base.vm对应增加的代码如下:
用户名:${user.username}
--------------------------迭代分隔线-------------------
#foreach($element in $list)
$index. $element
#end
--------------------------迭代map对象--------------------
#foreach($key in $map.keySet())
$key = $map.get($key)
#end
--------------------------if/else测试--------------------
#if($condition)
条件为真
#else
条件为假
#end
----------------------对象为null解决方案--------------
$!person
对于以上的代码需要说明的是,velocity变量名可以通过directive.foreach.counter.name 属性修改,如:directive.foreach.counter.name=index,以后便可以通过$index来进行索引值访问。迭代的索引默认从1开始,我们可以通过directive.foreach.counter.initial.value=0来进行修改,修改后默认索引便从0开始。
4.在web项目中使用velocity
步骤一,关于velocity使用前的properties配置文件的设置,通常情况下我们可以在过滤器的init方法中执行类似如下的代码:
Properties prop = new Properties();
prop.put("runtime.log", config.getServletContext().getRealPath(
      "/WEB-INF/log/velocity.log"));
prop.put("file.resource.loader.path", config.getServletContext().getRealPath("/WEB-INF/vm"));
prop.put("input.encoding", "UTF-8");
prop.put("output.encoding", "UTF-8");
这样设置有两个好处,一是可以根据项目中设置的日志文件所在的相对路径来设置runtime.log参数。二是可以保证velocity模板只被初始化一次。
步骤二、比如在一些在线购物网站上,后台对产品更新后,我们可以根据一定的规律动态地生成静态页面,然后再根据静态页面的生成规律来完成静态页面访问链接的设置。类似如下代码:
File saveDir =
new File(request.getSession().getServletContext().getRealPath(
     "/html/product/" + entity.getType().getId()));
// 生成的文件存放在网站根目录的html/product/类别id/

if (!saveDir.exists()) {
    saveDir.mkdirs();
}
VelocityContext context = new VelocityContext();
context.put("product", product);
Template template = Velocity.getTemplate("product/productview.vm");
FileOutputStream outStream = new FileOutputStream(new File(saveDir, product.getId()+".html"));
OutputStreamWriter writer = new OutputStreamWriter(outStream,"UTF-8");
BufferedWriter sw = new BufferedWriter(writer);
template.merge(context, sw);
sw.flush();
sw.close();
outStream.close();

二、使用缓存:OSCache
步骤一、导入OSCache的基本jar包:oscache.jar、/lib/commons-logging.jar
步骤二、编写oscache.properties配置文件,它的内容可参/etc/oscache.properties文件。这个配置文件在开发阶段应放在src目录下,运行时建议移到/WEB-INF/classes目录下。
步骤三、在jsp中引入标签库,代码如下:
<%@ taglib uri="http://www.opensymphony.com/oscache" prefix="cache"%>
步骤四、在jsp页面中使用缓存标签,内容如下:
<cache:cache>
    <%=new Date() %>
</cache:cache>
说明:缓存默认的存放时间为3600秒,且缓存默认存放在application范围。这即是说在3600秒内访问这此jsp页面,显示的时间一直是第一次访问显示的时间。缓存的key将以请求URI+查询字串组成,这即是说如果请求时附加的参数发生改变,则这里显示的时间也会随之改变。比如使用osCacheTest.jsp第一次访问此页面,随后仍使用此uri访问时,显示的时间不会改变,但是如果附加osCacheTest.jsp?name=XXX这样的参数再访问此页面时,显示的时间则会改变。如果不想访问时时间的显示不因附加参数的变化而变化,则可以如下使用缓存标签:
<cache:cache key="timeABC">   <%=new Date() %>    </cache:cache>
这样设置后,无论怎样附加请求参数,访问jsp页面显示的时间总不会改变。
如果想设置缓存过期时间,可以设置time=10,即是说10秒后缓存失效。这样10秒后访问此页面,显示的时间会改变。如果想缓存只在session范围内有效,可以设置作如下设置:
<cache:cache key="timeABC" scope="session">
附加说明:除此之处,cache标签还有一个属性,它的作用是清掉缓存,比如有如下代码
<cache:cache key="timeABC" time="10" refresh="${param.isclear}" >
    <%=new Date() %>
</cache:cache>
如果我们向此uri传递附加参数?isclear=true时,无论这个缓存是否过期,它总会清掉缓存中的内容。如果一个项目中有许多页面都使用了缓存,而我们想清掉这些缓存时,不可能像使用这种附加uri参数的方式来逐个清除。一个比较合理的方式是使用flush标签,代码如下:
   <cache:flush key="timeABC" scope="session"></cache:flush>
清掉session范围内key值为timeABC的缓存,如果没有key值,表示清掉session范围内所有缓存。另我们可以使用这种方式对缓存编组,具体的代码如下:
<cache:addgroup group="abc">
   <cache:cache>时间一:<%=new Date() %></cache:cache>
    <cache:cache>时间二:<%=new Date() %></cache:cache>
</cache:addgroup>
它还有一个属性group,表示清掉某分组下的缓存,比如这里在flush标签中增加group="abc",将清掉组名为“abc”所包含的所有缓存。
缓存小结:使用缓存时,应根据业务需求来灵活选择缓存数据的存放范围域及时间域。
以上都是针对<cache:cache>标签下的局部缓存,以下介绍OSCache的全局缓存。
使用OSCache的全局缓存非常方便,首先应在项目中配置一个oscache.properties文件,它的具体模板可以参看OSCache解压后etc目录下的oscache.properties文件。然后在web.xml中配置一个过滤器,代码如下:
<filter>
   <filter-name>CacheFilter</filter-name>
   <filter-class>
    com.opensymphony.oscache.web.filter.CacheFilter
   </filter-class>
   <!-- 缓存过期时间,单位:秒 -->
   <init-param>
    <param-name>time</param-name>
    <param-value>60</param-value>
   </init-param>
   <init-param>
    <param-name>scope</param-name>
    <param-value>application</param-value>
   </init-param>
</filter>
<filter-mapping>
   <filter-name>CacheFilter</filter-name>
   <url-pattern>/product/*</url-pattern>
</filter-mapping>
这样配置后,以/product/开头路径下的所有请求都会进行页面缓存,关于缓存的具体设置应在oscache.properties文件中进行设置。
Cache.memory=true:指定是否使用内存缓存,默认为true,即使用内存缓存
Cache.capacity:指定缓存的数量,默认的数量是无限的。也可以为其设置缓存数量,如1000
如果我们只使用硬盘作为缓存,可以这样设置
Cache.memory=false:禁用内存缓存
Cache.path=d://cache:指定缓存保存的路径
Cache.persistence.class=com.opensymphony.oscache.plugins.diskpersistence.DiskPersistenceListener :指定用于设置的持久化类
注意:缓存的key将以请求的URI+查询字串组成,访问xxx.jsp?name=abc和访问xxx.jsp?name=xyz将得到两份缓存,缓存是在初次访问页面时进行的,后面的所有请求将直接返回缓存中内容。缓存中存放的内容为网页的html代码。
全局缓存原理简易分析:
当用户请求到达时,首先被filter拦截到,然后在Map树中查找缓存(key=请求uri,value=缓存内容),如果存在这些缓存则把缓存内容返回给用用户,如果Map树中不存在此缓存则包装原resoponse对象,执行doFilter(request,被包装的response对象),最后再从包装的response对象中获取内容,并添加到Map树中供下次访问使用。如下的代码简易地模拟了缓存的原理。
---------------------------------------------------------------------
// 这一步本应是根据配置的缓存过滤器的作用域范围来得到cache Map对象,这里我们简化为直接从application范围中得到cache Map对象
Map<String, String> cache = (Map<String, String>) request.getSession().getServletContext().getAttribute("cacheMap");

String key = request.getRequestURI(); // 得到请求的uri
String content = cache.get(key); // 得到全部
if (content != null && content.length() > 0) {
// 1->直接把缓存中的内容写到用户请求的流中
// 2->返回
return;
} else {
// 1->包装原response对象
// 2->传递给下一个filter对象执行
chain.doFilter(request, responseWarp<被包装的response对象>);
   
// 3->在map树中添加此缓存内容
cache.put(key,responseWarp.getContent());
// 4->此时直接把resopnseWarp.getContet()得到的内容写到用户请求的流中
}
---------------------------------------------------------------------
有了以上的原理分析,我们必须考虑filter的执行顺序问题,由于OSCache会直接把缓存中的内容写回到输出流中,并直接返回,这样可以导致后续filter无法执行,通常我们应把一些权限filter写在这里的缓存filter之前,这样才能有效保证权限拦截的顺利执行。而osiv这样的filter应写在缓存filter之后,因为缓存filter一般会直接返回请求的数据,没有必要去执行osiv这样的filter。

OSCache与hibernate的二级缓存性能比较
Hibernate的二级缓存主要保存的是实体数据,当hibernate配置使用二级缓存时,查询、更新、保存数据都会引发保存实体数据到二级缓存中,当调用业务方法查询数据时便可以直接从库中获取实体数据,避免了连库操作,提高了效率。
OSCache缓存会直接根据请求查找数据(html代码),直接把数据写回到用户请求的流中并返回。这样比访问静态页面的效率还高,访问静态页面的步骤:请求到达->读取静态页面到内存->写到流中返回给用户。使用OSCache缓存可以直接把数据写到流中并返回给用户,省略了读取静态页面到内存中这一步骤。

三、SSI技术
SSI:即Server Side Include,通常称为“服务器端包含”技术。使用了SSI技术的文件默认后缀名为.shthml,SSI技术通过在html文件中加入SSI指令让WEB服务器在输出标准HTML代码之前先解释SSI指令,并把解释完后的输出结果和HTML代码一起返回给客户端
在大部分的项目中,我们主要使用SSI的包含指令<!--#include file/virtural= -->
他们的作用类似于JSP中<jsp:include page="xxx.jsp"/>
1.为何要使用SSI
既然JSP中的<jsp:include/>指令已提供了类似的功能,那为何要使用SSI技术,主要有如下原因:(1)SSI技术是通用技术,它不受限于运行环境,在java、CGI、ASP、PHP、.net中都可以使用SSI技术(2)解释SSI的效率比解释JSP的效率快很多,因为JSP规范提供了太多的功能,这些功能都需要servlet引擎进行解释,所以效率上JSP要低很多。
目前大多数门户网站都使用了SSI技术。解释SSI文件最佳的服务器是Apache Http Server.大型门户网站基本上都是采用Apache http Server和解释SSI文件。需要注意的是如果使用Apache http Server来解释SSI指令,被包含的文件不能是jsp文件,因为此服务器不能解释jsp文件。
2.配置使用SSI
目前主流的web服务器提供了SSI实现,我们只需要打SSI功能就可以使用
下面展示在Tomcat5下使用SSI技术的主要步骤(使用tomcat解释SSI指令在效率上无实质性的提升)
步骤一、把…/server/lib/serlets-ssi.renametojar的名称改为servlet-ssi.jar(补充:tomcat6以上版本无需此步,因为org.apache.catalina.ssi.SSIServlet已包含在 catalina.jar包中)
步骤二、设置…/conf/context.xml文件,在<Context>节点添加privilege=“true”属性,该属性指定我们发布的web应用有权限使用容器的servlet。当你如果需要在…/conf/servlet.xml添加其它的应用时,最好也为<Context>加上privileged=“true”属性,如下:
<Context debut=“0” path=“” docBase=“E:/website”privileged=“ true”>
步骤三、在…/conf/web.xml开启SSI功能,Tomcat提供了两种开启SSI的方式:一种是servlet,另一种是filter。这里我们使用Servlet开启SSI功能。在…conf/web.xml文件中找到<servlet-name>ssi</servlet-name>,去掉对它的注释,然后在shtml文件的编码格式中指定inputEnocoding和outputEncoding属性值,即说在此servlet的配置下增加如下代码:
<init-param>
       <param-name>inputEncoding</param-name>
       <param-value>UTF-8</param-value>
</init-param>
<init-param>
       <param-name>ouputEncoding</param-name>
       <param-value>UTF-8</param-value>
</init-param>
注意同时别忘记了把它相关的<servlet-mapping>的注解去掉
步骤三、使用ssi指令的网页文件后缀名改为shtml。
3.SSI指令基本格式
<!--#指令名称=指令参数-->
<!--#include file="foot.html"-->
说明:<!-- -->表示html注释,当web服务不支持SSI时,会忽略这些信息。#include为SSI指令之一。注意<!—与#之间不能有空格,只有ssi指令与参数之间存在空格。SSI指令是大小写敏感的,因此参数必须小写才会起作用。


四、Compass实现优化查询
1.基本的jar文件
compass-2.2.0.jar、commons-logging.jar、/lucene/*.jar
2.自动化创建实体索引:实体注解标记及spring的gps扫描管理
3.编写查询代码

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值