对于经常逛网页的人来说最受不了的事情就是访问的网页加载太慢,除去网络的原因网站的系统性能对加载的快慢非常重要,
网上有个统计:
每慢500ms Google访问量降低20%
每慢400ms Yahoo 访问量降低5-9%
每慢100ms Amazon销售额降低1%
对于商务网站来说用户的多少就表示着网站的命运 所以对网站的系统性能的优化格外重要;
假如当网站在一段时间内有10w个用户访问网站的一个商品时, 网站就会和数据库交互10w次 数据库也只是一个应用而已 它存在数据库瓶颈问题 数据库每次只能同时保持大概2000个连接数 所以对于这些访问者来说只有20%的人能很快访问到网页,50%的人在较慢的一段时间内还是能访问到网页的,但剩下的30%的访问者就会收到连接超时的异常
对于这种由于访问数据库的次数太多的解决方案有:
A.页面情态化成html
页面情态化就是将原来的本应该每次都要访问数据库再生成情态html文件返回,而现在就是只生成一次html下次再访问服务器只要访问该html文件就行不用再访问数据库了,对于这个技术对系统的性能提升很大,但是这个技术只能用于不怎么变化的模块:例如像商品的详细介绍页面:
像这种的页面的信息一周甚至一个月都不会变化,将类似这种模块情态化最合适;
实现这个技术的方法是使用模版技术:Velocity 或 freemarket
这两种技术都出现了10多年了freemarket比velocity出现的晚几年 声称比velocity功能强大 现在的struts2也使用了freemarket 但是velocity扩展性更好 我这使用的是velocity
基本语法:
1、"#"用来标识Velocity的脚本语句,包括#set、#if 、#else、#end、#foreach、#end、#iinclude、#parse、#macro等;
如:
#if($info.imgs)
<img src="$info.imgs" border=0>
#else
<img src="noPhoto.jpg">
#end
2、"$"用来标识一个对象(或理解为变量);如
如:$i、$msg、$TagUtil.options(...)等。
3、"{}"用来明确标识Velocity变量;
比如在页面中,页面中有一个$someonename,此时,Velocity将把someonename作为变量名,若我们程序是想在someone这个变量的后面紧接着显示name字符,则上面的标签应该改成${someone}name。
4、"!"用来强制把不存在的变量显示为空白。
如当页面中包含$msg,如果msg对象有值,将显示msg的值,如果不存在msg对象同,则在页面中将显示$msg字符。这是我们不希望的,为了把不存在的变量或变量值为null的对象显示为空白,则只需要在变量名前加一个“!”号即可。
如:$!msg
使用方法:
1.在http://velocity.apache.com下载velocity-*.rar 解压
可以将velocity-*-dep.jar放带WEB-INF的lib目录下即可 也可以使用velocity-*.jar但是这时要将co'm'mons-connections-*.jar和commons-lang-*.jar和oro-*.jar也加入lib目录下
2.配置velocity的一些属性:
我使用的是在filter中加入相应的配置如:
1 try{ 2 Properties prop = new Properties(); 3 prop.put("runtime.log", config.getServletContext().getRealPath("/WEB-INF/log/velocity.log")); 4 prop.put("file.resource.loader.path", config.getServletContext().getRealPath("/WEB-INF/vm")); 5 prop.put("input.encoding", "GB18030"); 6 prop.put("output.encoding", "GB18030"); 7 Velocity.init(prop); 8 }catch( Exception e ){ 9 e.printStackTrace(); 10 }
file.resource.loader.path 配置的是模版所在的位置 input.encoding ,output.encoding 配置的是相应的输入输出的编码要跟你模版中的编码一样
3.编写模版生成的代码:我使用的是在商品添加或修改时就生成该商品的html情态文件
1 <form action="/shopping/cart" method="post" name="cart"> 2 <INPUT TYPE="hidden" NAME="productid" value="${product.id}" /> 3 <div id="browse_left"> 4 5 <div class="right_left"> 6 <div class="right_right"> 7 <div class="right_title"><b>${product.name}</b></div> 8 <div class="right_desc"> 9 <ul> 10 <li class="li2">商品编号:${product.id}<font color="#CC0000">(电话订购专用)</font></li> 11 #if($!{product.brand}) <li>品牌:$product.brand.name</li> #end </ul> 12 </div> 13 <div class="right_desc"> 14 #if($product.productStyles.size()==1) 15 <INPUT TYPE="hidden" NAME="styleid" value="$product.productStyles.iterator().next().id" /> 16 <li>颜色:红色</li> 17 #else 18 <li>颜色:<SELECT name="styleid">#foreach($color in $product.productStyles) 19 <option value="$color.id">$color.name</option> 20 #end </SELECT></li> 21 #end 22 </div> 23 <ul> 24 <li>市场价:<s>${product.marketprice}</s> 元 <font color='#ff6f02'>本站价:<b>${product.sellprice} 元</b></font> 节省:<font color='#ff6f02'>${product.savedPrice}</font> 元 </li> 25 26 </ul> 27 </div> 28 </div> 29 <div id="browse_right"><div id="sy_biankuang"> 30 <div class="sy_xinpintuijian_font">本站尚未开张</div> 31 <div class="sy_dianhua" style="line-height:150%"><font color="#FF0000"> 32 全国:010-6466 3070</font><br/>MSN在线客服:*****@sohu.com<br/> 33 <font color="#3A8FAF">QQ在线客服:895957140</font></div> 34 </div></div> 35 </form>
<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>7200</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/list/*</url-pattern></filter-mapping>
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close"><property name="driverClass" value="${driverClass}"/><property name="jdbcUrl" value="${jdbcUrl}"/><property name="user" value="${user}"/><property name="password" value="${password}"/><!-- 初始化时获取的连接数,取值应在minPoolSize与maxPoolSize之间。Default: 3 --><property name="initialPoolSize" value="1"/><!-- 连接池中保留的最小连接数。 --><property name="minPoolSize" value="1"/> <!-- 连接池中保留的最大连接数。Default: 15 --><property name="maxPoolSize" value="300"/><!-- 最大空闲时间,60秒内未使用则连接被丢弃。若为0则永不丢弃。Default: 0 --><property name="maxIdleTime" value="60"/> <!-- 当连接池中的连接耗尽的时候c3p0一次同时获取的连接数。Default: 3 --><property name="acquireIncrement" value="5"/> <!-- 每60秒检查所有连接池中的空闲连接。Default: 0 --><property name="idleConnectionTestPeriod" value="60"/></bean>
配置过程:
1). 先保证 Tomcat 可以运行,即能够正常启动
2). ( 5.x 版本)服务器根目录下边 $TOMCAT_HOME( 或者 $CATALINA_HOME)/server/lib/ 目录下边有一个文件:
servlets-ssi.renametojar ,将这个文件名更名为一个 jar 后缀,当然最方便的方法是直接改掉文件后缀,按照 Tomcat 扫描jar 路径类的原理来讲,直接更名为 jar 应该也是可以的,不过我没尝试过,一般网上最常用的方法是改成: servlets-ssi.jar。( 6.x 版本)服务器不需要去寻找 jar 文件了,直接进入下一步操作都可以。
3). 找到文件: $TOMCAT_HOME( 或者 $CATALINA_HOME)/conf/web.xml ,这里面不需要我们自己写入 SSI Servlet 和SSI Filter 的配置,首先我们要选择使用哪种方式来配置:
Servlet 配置:
在这个文件里面,找到以下注释代码段,将注释代码段去掉:
Servlet 配置——
<!--<servlet><servlet-name>ssi</servlet-name><servlet-class>org.apache.catalina.ssi.SSIServlet</servlet-class><init-param><param-name>buffered</param-name><param-value>1</param-value></init-param><init-param><param-name>debug</param-name><param-value>0</param-value></init-param><init-param><param-name>expires</param-name><param-value>666</param-value></init-param><init-param><param-name>isVirtualWebappRelative</param-name><param-value>0</param-value></init-param><load-on-startup>4</load-on-startup></servlet>-->
ServletMapping 配置——
<!--<servlet-mapping><servlet-name>ssi</servlet-name><url-pattern>*.shtml</url-pattern></servlet-mapping>-->
Filter 配置:
Filter 的相关配置——
<!--<filter><filter-name>ssi</filter-name><filter-class>org.apache.catalina.ssi.SSIFilter</filter-class><init-param><param-name>contentType</param-name><param-value>text/x-server-parsed-html(;.*)?</param-value></init-param><init-param><param-name>debug</param-name><param-value>0</param-value></init-param><init-param><param-name>expires</param-name><param-value>666</param-value></init-param><init-param><param-name>isVirtualWebappRelative</param-name><param-value>0</param-value></init-param></filter>-->
FilterMapping 相关配置——
<!--<filter-mapping><filter-name>ssi</filter-name><url-pattern>*.shtml</url-pattern></filter-mapping>-->
只是 Filter 配置里面还需要取消另外一个注释,下边的 MIME TYPE 的服务器支持相关注释
<!--<mime-mapping><extension>shtml</extension><mime-type>text/x-server-parsed-html</mime-type></mime-mapping>-->
上边的注释取消过后,配置就基本好了,在 Tomcat 5.x 的版本中配置的时候,到这个地步就结束了,但是在 Tomcat 6.x 版本中可能还会出现下边的异常:
java.lang.SecurityException: Filter of class org.apache.catalina.ssi. SSIFilter (SSIServlet) is privileged and cannot be loaded by this web application
4). 所以正对这点 6.x 还有一个步骤,在 $TOMCAT_HOME( 或者 $CATALINA_HOME)/conf/context.xml 文件中在<Context> 结点添加一个属性 privileged="true" ,然后再启动就不会抛出上边的异常了。
5). 若要解决乱码问题,根据上边文档需要修改 SSI 中的启动参数:添加如下代码:
<init-param><param-name> inputEncoding </param-name><param-value> utf-8 </param-value></init-param><init-param><param-name> outputEncoding </param-name><param-value> utf-8 </param-value></init-param>