compass实现搜索、订单载入功能、velocity模版静态化、OSCache优化性能、SSI实现

一、compass实现搜索
1、配置

1.1、加入如下jar包。



1.2、将compass与spring集成,让compass使用spring的事务,配置文件如下:

bean.xml文件中加入如下内容

[html]  view plain copy print ?
  1.   <bean id="compass" class="org.compass.spring.LocalCompassBean">  
  2.     <!-- 指定映射类方式 -->  
  3.     <property name="classMappings">  
  4.         <list>  
  5.             <value>com.nbchina.bean.article.Article</value>  
  6.             <value>com.nbchina.bean.article.ArticleClass</value>  
  7.         </list>  
  8.     </property>  
  9.     <property name="compassSettings">  
  10.         <props>  
  11.             <prop key="compass.engine.connection">file://e:/index</prop>  
  12.             <prop key="compass.engine.highlighter.default.formatter.simple.pre"><![CDATA[<font color='red'>]]></prop>  
  13.             <prop key="compass.engine.highlighter.default.formatter.simple.post"><![CDATA[</font>]]></prop>  
  14.             <prop key="compass.transaction.factory">org.compass.spring.transaction.SpringSyncTransactionFactory</prop>  
  15.         </props>  
  16.     </property>  
  17.     <property name="transactionManager" ref="transactionManager" />  
  18. </bean>  
  19. <!-- CompassGps为CompassGpsDevice提供Compass对象,他们一起为程序提供索引的实时更新 -->  
  20. <bean id="compassGps" class="org.compass.gps.impl.SingleCompassGps" init-method="start" destroy-method="stop">  
  21.     <property name="compass" ref="compass" />  
  22.     <property name="gpsDevices">  
  23.         <list>  
  24.             <bean class="org.compass.spring.device.SpringSyncTransactionGpsDeviceWrapper">  
  25.                 <property name="gpsDevice">  
  26.                     <!-- 为gpsDevice属性注入针对JPA的GPS驱动 -->  
  27.                     <bean class="org.compass.gps.device.jpa.JpaGpsDevice">  
  28.                         <property name="name" value="jpaDevice" />  
  29.                         <property name="entityManagerFactory" ref="entityManagerFactory" />  
  30.                         <property name="injectEntityLifecycleListener" value="true"/>  
  31.                     </bean>  
  32.                 </property>  
  33.             </bean>  
  34.         </list>  
  35.     </property>  
  36. </bean>  


Article实体内容如下

[java]  view plain copy print ?
  1. @Entity  @Searchable //通过这个注解,指明该类跟lucene中的document映射  
  2. public class Article {  
  3.   
  4.   
  5.     @Id  
  6.     @GeneratedValue(strategy=GenerationType.AUTO)  
  7.     @SearchableId  
  8.     private Integer id;  
  9.       
  10.     @ManyToOne(cascade=CascadeType.REFRESH,optional=false)  
  11.     @JoinColumn(name="acid")   
  12.     @SearchableComponent  
  13.     private ArticleClass ac;  
  14.       
  15.     //@SearchableComponent代表还要跟其他类关联  
  16.     //boost=2数字越大级别越高,代表标题检索到的排序在前。默认为1.  
  17.     //index=Index.NO代表不参与索引  
  18.     //store=Store.YES代表储存  
  19.     //name="titleName" 有些字段和关联的其他表字段相同,那么可以重命名。  
  20.     @Column(length=80,nullable=false)  
  21.     @SearchableProperty(boost=2,store=Store.YES, name="titleName")  
  22.     private String title;  
  23.       
  24.     @Column(length=255)  
  25.     private String titleIntact;  
  26.       
  27.     @Column(length=10)  
  28.     private String titleFontColor;  
  29.       
  30.     @Column(length=255)  
  31.     private String linkURL;  
  32.       
  33.     @Column(length=255)  
  34.     private String keyword;  
  35.       
  36.     @Column(length=255)  
  37.     @SearchableProperty(index=Index.NO,store=Store.YES)  
  38.     private String intro;  
  39.       
  40.     @Column(nullable=false)  
  41.     private Integer hits = 1;  
  42.       
  43.     @Temporal(TemporalType.DATE) @Column(nullable=false)  
  44.     @SearchableProperty(index=Index.NO,store=Store.YES,format="yyyy-MM-dd")  
  45.     private Date updateTime = new Date();  
  46.       
  47.     @Column(nullable=false)  
  48.     private Boolean onTop = false;  
  49.       
  50.     @Column(nullable=false)  
  51.     private Boolean elite = false;  
  52.       
  53.     @Column(nullable=false)  
  54.     private Boolean hot = false;  
  55.       
  56.     @Column(nullable=false)  
  57.     private Integer status = 0;  
  58.       
  59.     @Column(nullable=false)  
  60.     private Integer deleted = 0;  
  61.       
  62.     @Column(length=80)  
  63.     private String editor = "admin";  
  64.       
  65.     @Column(length=80)  
  66.     private String author = "佚名";  
  67.       
  68.     @Column(length=80)  
  69.     private String copyFrom;  
  70.       
  71.     @Lob @Column(nullable=false)  
  72.     @SearchableProperty(store=Store.YES)  
  73.     private String content;  
  74.       
  75.     @Column(nullable=true)  
  76.     private Integer includeImage = 0;  
  77.       
  78.     @Lob  
  79.     private String uploadFiles;  
  80.       
  81.     @Column(length=255)  
  82.     private String includeImageURL;  
  83.       
  84.     @Column(length=255)  
  85.     private String voiceURL;  
  86.       
  87.   
  88.       
  89. }  


[java]  view plain copy print ?
  1. @Entity @Searchable(root=false)  
  2. public class ArticleClass implements Serializable{  
  3.   
  4.     //@Searchable(root=false)代表不是搜索的根类,是Article的配角,关联的类而已。  
  5.     @Id  
  6.     @GeneratedValue(strategy=GenerationType.AUTO)  
  7.     @SearchableProperty(index=Index.NO, store=Store.YES)  
  8.     private Integer id;  
  9.       
  10.     @Column(length=36,nullable=false)  
  11.     @SearchableProperty(index=Index.NO, store=Store.YES)  
  12.     private String name;  
  13.       
  14.     @Column(length=200)  
  15.     private String note;  
  16.       
  17.     @Column(nullable=false)  
  18.     private Boolean visible=true;  
  19.       
  20.     @Column(nullable=false)  
  21.     private Integer orderId=0;  
  22.       
  23.     @Column(length=255)  
  24.     private String imageURL;  
  25.       
  26.     @Column(length=10)  
  27.     private String level;  
  28.   
  29.   
  30.   
  31.     @OneToMany(cascade={CascadeType.REFRESH,CascadeType.REMOVE},mappedBy="parent")  
  32.     private Set<ArticleClass> childs = new HashSet<ArticleClass>();  
  33.       
  34.       
  35.     @ManyToOne(cascade=CascadeType.REFRESH)  
  36.     @JoinColumn(name="parentid")      
  37.     private ArticleClass parent;  
  38.       
  39.     @OneToMany(mappedBy="ac", cascade=CascadeType.REMOVE)  
  40.     @SearchableReference   //表示引用article  
  41.     private Set<Article> articles = new HashSet<Article>();  
  42.   
  43. }  


建立ArticleSearchServiceBean.java

[java]  view plain copy print ?
  1. @Service @Transactional  
  2. public class ArticleSearchServiceBean extends CompassDaoSupport implements ArticleSearchService {  
  3.       
  4.     @Resource  
  5.     public void setSessionFactory(Compass compass){  
  6.         super.setCompass(compass);  
  7.     }  
  8.       
  9.     public QueryResult<Article> search(String key, int startIndex, int maxResult) {  
  10.         return this.getCompassTemplate().execute(new ArticleResultCallback(key, startIndex, maxResult));  
  11.     }  
  12.   
  13. }  

建立ArticleResultCallback.java

[java]  view plain copy print ?
  1. public class ArticleResultCallback implements CompassCallback<QueryResult<Article>> {  
  2.     private String key;  
  3.     private int startIndex;  
  4.     private int maxResult;  
  5.   
  6.     public ProductResultCallback(String key, int startIndex, int maxResult) {  
  7.         this.key = key;  
  8.         this.startIndex = startIndex;  
  9.         this.maxResult = maxResult;  
  10.     }  
  11.   
  12.     public QueryResult<Article> doInCompass(CompassSession session) throws CompassException {  
  13.         List<Article> articles = new ArrayList<Article>();  
  14.         CompassHits hits = session.find(key);  
  15.         int lastIndex = startIndex + maxResult - 1;  
  16.         if(lastIndex>(hits.length()-1)) lastIndex = hits.length()-1;  
  17.         for(int i=startIndex; i<=lastIndex; i++){  
  18.             Article article = (Article) hits.data(i);  
  19.             if(hits.highlighter(i).fragment("title")!=null){//处理高亮显示  
  20.                 article.setTitle(hits.highlighter(i).fragment("title"));  
  21.             }  
  22.             articles.add(article);  
  23.         }  
  24.         QueryResult<Article> qr = new QueryResult<Article>();  
  25.         qr.setResultlist(articles);  
  26.         qr.setTotalrecord(hits.length());//设置查询到的总记录数  
  27.         return qr;  
  28.     }  
  29.   
  30. }  

ArticleSearchAction内加入如下内容

[java]  view plain copy print ?
  1. QueryResult<Article> qr = articleSearchService.search("关键字", pageView.getFirstResult(), pageView.getMaxresult());  
  2.   
  3. pageView.setQueryResult(qr);  



二、订单载入(锁定,防止多人同时操作)

order实体内加入

/* 锁定该订单的员工,如果该值不为null,即订单被锁定 */
private String employee;

OrderServiceBean内加入

[java]  view plain copy print ?
  1. public Order getLockOrder(String orderid, String employee){  
  2.     em.createQuery("update Order o set o.employee=?1 where o.orderid=?2 and o.employee is null")  
  3.         .setParameter(1, employee).setParameter(2, orderid).executeUpdate();  
  4.     em.flush();  
  5.     return this.find(orderid);  
  6. }  
  7. public void unLock(String orderid){  
  8.     em.createQuery("update Order o set o.employee=?1 where o.orderid=?2")  
  9.     .setParameter(1null).setParameter(2, orderid).executeUpdate();  
  10. }  

action内加入

[java]  view plain copy print ?
  1. if(!order.getEmployee().equals(username)){  
  2.             request.setAttribute("message""该订单已被"+ order.getEmployee() + "锁定");  
  3.             return mapping.findForward("message");    
  4.         }  


jsp内判断

[java]  view plain copy print ?
  1. <c:if test="${empty entry.employee || entry.employee==employee.username}"><a href="">载入订单</a></c:if>  
  2. <c:if test="${!empty entry.employee && entry.employee!=employee.username}">被${entry.employee}锁定</c:if>  



三、Velocity 模版静态化
1、Velocity配置

如下代码加入到系统初始化代码块中

[java]  view plain copy print ?
  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""UTF-8");  
  6.     prop.put("output.encoding""UTF-8");  
  7.     Velocity.init(prop);  
  8.     System.out.println("Velocity Initialized");  
  9. }catch( Exception e ){  
  10.     System.out.println("VSelocity error");  
  11.     e.printStackTrace();  
  12. }  

引入Velocity1.6 jar 包


2、实例

WebRoot-WEB-INF-VM目录下建立mailContent.vm
文件内容如下
[html]  view plain copy print ?
  1. <html>  
  2. <head>  
  3. <title>测试</title>  
  4. <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">  
  5. </head>  
  6. 尊敬的客户:${userName}  
  7. </body>  
  8. </html>  
使用代码如下
[java]  view plain copy print ?
  1. Template template = Velocity.getTemplate("mailContent.vm","UTF-8");  
  2. VelocityContext context = new VelocityContext();  
  3. context.put("userName""测试名");  
  4. StringWriter writer = new StringWriter();  
  5. template.merge(context, writer);  
  6. writer.flush();  
  7. String mailContent = writer.toString();  
  8. EmailSender.send(entry.getEmail(), "测试", mailContent, "text/html");   

三、Velocity脚本语法摘要

1.     变量

(1)变量的定义:
#set($name = "hello")      说明:velocity中变量是弱类型的。
当使用#set 指令时,括在双引号中的字面字符串将解析和重新解释,如下所示:
#set($directoryRoot = "www" )
#set($templateName = "index.vm" )
#set($template = "$directoryRoot/$templateName" )
$template
输出将会是:www/index.vm
注:在velocity中使用$2.5这样的货币标识是没有问题得的,因为velocity中的变量总是以一个大写或者小写的字母开始的。
(2)变量规范的写法
${name} ,也可以写成:$name。提倡用前面的写法。
例如:你希望通过一个变量$vice来动态的组织一个字符串。
 Jack is a $vicemaniac.
本来变量是$vice现在却变成了$vicemaniac,这样Veloctiy就不知道您到底要什么了。所以,应该使用规范的格式书写 : Jack is a ${vice}maniac
现在Velocity知道变量是$vice而不是$vicemaniac。
注意:当引用属性的时候不能加{}
(3)变量的赋值:  
$name="hello"
赋值的左边必须是一个变量或者是属性引用。右边可以是下面六种类型之一: 
变量引用,字面字符串,属性引用,方法引用,字面数字,数组列表。
下面的例子演示了上述的每种类型:
#set( $monkey = $bill ) ## variable reference
#set( $monkey.Friend = "monica" ) ## string 
#set( $monkey.Blame = $whitehouse.Leak ) ## property reference
#set( $monkey.Plan = $spindoctor.weave($web) ) ## method reference
#set( $monkey.Number = 123 ) ##number 
#set( $monkey.Say = ["Not", $my, "fault"] ) ## ArrayList
注意:①如果上述例子中的右值是null, 则左值不会被赋值,也就是说会保留以前的值。
②velocity模板中未被定义的变量将被认为是一个字符串。例如:
#set($foo = "gibbous") 
$moon = $foo
输出结果为:
$moon = gibbous
③velocity模板中不会将reference解释为对象的实例变量。例如:$foo.Name将被解释为Foo对象的getName()方法,而不是Foo对象的Name实例变量。例如:
$foo.getBar()  等同于$foo.Bar ;
$data.getUser("jon") 等同于$data.User("jon") ;
data.getRequest().getServerName() 等同于
$data.Request.ServerName等同于${data.Request.ServerName}
 
2.     循环
#foreach ($element in $list)
     This is $element.
     $velocityCount 
#end
例子:
#set( $list = ["pine", "oak", "maple"])
#foreach ($element in $list)
$velocityCount
This is $element.<br>
#end
输出的结果为:
1 This is pine. 
2 This is oak. 
3 This is maple.
每次循环$list中的一个值都会赋给$element变量。
$list可以是一个Vector、Hashtable或者Array。分配给$element的值是一个java对象,并且可以通过变量被引用。例如:如果$element t是一个java的Product类,并且这个产品的名字可以通过调用他的getName()方法得到。
#foreach ( $key in $list.keySet())
Key: $key -> Value: $list.get($key) <br>
#end
提示:velocity中大小写敏感。
Velocity还特别提供了得到循环次数的方法,$velocityCount变量的名字是Velocity默认的名字。
 
例子:
First example:
  #foreach ( $foo in [1..5] )
    $foo
  #end


  Second example:
  #foreach ( $bar in [2..-2] )
    $bar
  #end


  Third example:
  #set ( $arr = [0..1] )
  #foreach ( $i in $arr )
    $i
  #end
上面三个例子的输出结果为:
  First example:
  1 2 3 4 5


  Second example:
  2 1 0 -1 -2


  Third example:
  0 1
3.     条件语句
#if (condition) 
#elseif (condition) 
#else 
#end
4.     语句的嵌套
#foreach ($element in $list) 
## inner foreach 内循环 
#foreach ($element in $list) 
This is $element. $velocityCount <br>inner<br>
#end 
## inner foreach 内循环结束 
## outer foreach 
This is $element. 
$velocityCount <br>outer<br>
#end
语句中也可以嵌套其他的语句,如#if…#else…#end等。
5.      注释
(1)单行注释:
  ## This is a single line comment.
(2)多行注释:
  #*
   Thus begins a multi-line comment. Online visitors won’t
   see this text because the Velocity Templating Engine will
  ignore it.
  *#
(3)文档格式:
  #**
   This is a VTL comment block and
   may be used to store such information
  as the document author and versioning
   information:
   @version 1.1
   @author  xiao
     *#
6.     关系和逻辑操作符
Velocity 也具有逻辑AND, OR 和 NOT 操作符。

## example for AND
#if($foo && $bar)
   <strong> This AND that</strong>
#end
例子中#if() 指令仅在$foo 和$bar 斗为真的时候才为真。如果$foo 为假,则表达式也为假;并且 $bar 将不被求值。如果 $foo 为真,Velocity 模板引擎将继续检查$bar的值,如果 $bar 为真,则整个表达式为真。并且输出This AND that 。如果 $bar 为假,将没有输出因为整个表达式为假。
7.Velocity 中的宏
Velocity中的宏我们可以理解为函数。
①宏的定义
#macro(宏的名称 $参数1 $参数2 …)
   语句体(即函数体)
#end
②宏的调用
#宏的名称($参数1 $参数2 …)
说明:参数之间用空格隔开。
8.#stop
   停止执行模板引擎并返回,把它应用于debug是很有帮助的。
9.#include与#parse
#include和#parse的作用都是引入本地文件, 为了安全的原因,被引入的本地文件只能在TEMPLATE_ROOT目录下。
区别:
(1) 与#include不同的是,#parse只能指定单个对象。而#include可以有多个
如果您需要引入多个文件,可以用逗号分隔就行:
#include ("one.gif", "two.txt", "three.htm" )
在括号内可以是文件名,但是更多的时候是使用变量的:
#include ( “greetings.txt”, $seasonalstock )
(2) #include被引入文件的内容将不会通过模板引擎解析; 
而#parse引入的文件内容Velocity将解析其中的velocity语法并移交给模板,意思就是说相当与把引入的文件copy到文件中。
#parse是可以递归调用的,例如:如果dofoo.vm包含如下行:
Count down.<br>
#set ($count = 8)
#parse ("parsefoo.vm")
<br>All done with dofoo.vm!
那么在parsefoo.vm模板中,你可以包含如下VTL:
$count
#set($count = $count - 1)
#if ( $count > 0 )<br>
#parse( "parsefoo.vm" )
#else
<br>All done with parsefoo.vm!
#end的显示结果为:
Count down.
8
7
6
5
4
3
2
1
0
All done with parsefoo.vm!
All done with dofoo.vm!
注意:在vm中使用#parse来嵌套另外一个vm时的变量共享问题。如:
->a.vm 里嵌套 b.vm;
->a.vm 里定义了变量 $param;
->b.vm 里可以直接使用$param,无任何限制。
但需要特别注意的是,如果b.vm里同时定义有变量$param,则b.vm里将使用b.vm里定义的值。
10.转义字符'\'的使用
如果reference被定义,两个’\’意味着输出一个’\’,如果未被定义,刚按原样输出。如:
#set($email = "foo" )
$email
\$email
\\$email
\\\$email
输出:
foo
$email
\foo
\$email
如果$email 未定义
$email
\$email
\\$email
\\\$email
输出:
$email
\$email
\\$email
\\$email
 
11.内置对象
Velocity内置了一些对象,在vm模版里可以直接调用,列举如下:
$request、$response、$session,另外,模板内还可以使用 $msg内的消息工具访问 Struts 的国际化资源,达到简便实现国际化的方法。
12. 数组访问
对数组的访问在Velocity中存在问题,因为Velocity只能访问对象的方法,而数组又是一个特殊的Array,所以虽然数组可以进行循环列举,但却不能定位访问特定位置的元素,如 strs[2],数组对固定位置元素的访问调用了Array的反射方法get(Object array, int index),而Velocity没能提供这样的访问,所以数组要么改成List等其他类容器的方式来包装,要么就通过公用Util类的方式来提供,传入数组对象和要访问的位置参数,从而达到返回所需值的目的。


四、OSCache缓存

1、hibernate与OSCache对比
      hibernate 二级缓存仅仅针对实体进行缓存。
      oscache 针对整体或者局部进行缓存。速度更快,更全面。
http://java.net/downloads/oscache/  下载路径

2、配置

第一步:把上述两个jar文件放置在WEB-INF/lib目录下.

第二步:把oscache安装目录下的/etc/oscache.properties 文件放入 /WEB-INF/classes目录.开发阶段,我们可以把该文件放置在src目录.

下载路径:http://www.opensymphony.com/oscache/
oscache.jar
\lib\commons-logging.jar



3、实例

使用OSCache作页面局部缓存

我们使用Oscache的标签<oscache></oscache>来进行页面的局部缓存.使用方法如下:
<%@taglib uri="http://www.opensymphony.com/oscache" prefix=“oscache"%>
<oscache:cache>
<%=new Date() %>
</oscache:cache>
缓存的key将以请求的URI+查询字串组成,如果你访问/oscache/index.jsp?name=ttt和/oscache/index.jsp?name=ppp将得到两份缓存。缓存默认存放在application范围,缓存时间默认为3600秒,即1小时.
<oscache:cache  key=“name”>
        name=${param.name}
</oscache:cache>
这时候缓存将以name为key,不再是请求的URI+查询字串组成,所以如果你访问/oscache/index.jsp?name=ttt和/oscache/index.jsp?name=ppp将得到一份缓存。


<oscache:cache key="name" scope="session">
        name=${param.name}
</oscache:cache>
缓存范围设置为session,这时候缓存保存在用户的session中,如果用户的把浏览器关闭,再重新打开一个新浏览器,原来缓存的内容将不存在。

<oscache:cache key="name" time="10">
        name=${param.name}
</oscache:cache>
上面设置了缓存的时间为10秒,超过10秒后,缓存的内容将失掉。


<oscache:cache key="name" time="60" refresh="${param.refresh}">
        name=${param.name}
</oscache:cache>
refresh为true将会导致缓存的内容过期而被清除,简单地说,该属性为true用于清除缓存。

人为管理缓存<flush />标签:
<oscache:flush scope="application" /> 
清除application范围内的所有缓存 
<oscache:flush scope="session" key="foobar" />
清除session范围内的key为foobar的缓存。


<oscache:flush scope="application" group="currencyData" />
清除application范围内组名为currencyData内的所有缓存。

在局部缓存,显示动态人名的时候。可以这么做。

你好<SCRIPT Languge=JavaScript src="welcome.js"></SCRIPT>,欢迎访问。

welcome.js代码如下。

[html]  view plain copy print ?
  1. function readCookieByName(name){  
  2.     var nameOfCookie = name + "=";  
  3.     var x = 0;  
  4.     while ( x <= document.cookie.length ){  
  5.         var y = (x+nameOfCookie.length);  
  6.         if ( document.cookie.substring( x, y ) == nameOfCookie ) {  
  7.             if ( (endOfCookie=document.cookie.indexOf( ";", y )) == -1 )  
  8.             endOfCookie = document.cookie.length;  
  9.             return document.cookie.substring( y, endOfCookie );  
  10.         }  
  11.         x = document.cookie.indexOf( " ", x ) + 1;    
  12.         if ( x == 0 ) break;  
  13.     }  
  14.     return "";  
  15. }  
  16. function readWelcomeMsg(){  
  17.     try{  
  18.         var msg = readCookieByName("realName");  
  19.         if(msg!=""){  
  20.             return decodeURI(msg);  
  21.         }else{  
  22.             msg = readCookieByName("userName");  
  23.             if(msg!="") return msg;  
  24.         }         
  25.     } catch(e){  
  26.         ;  
  27.     }  
  28.     return "";  
  29. }  
  30. document.write(readWelcomeMsg());  



使用OSCache作页面全局缓存

页面全局缓存将使用Filter实现:

[html]  view plain copy print ?
  1. <filter>  
  2.       <filter-name>CacheFilter</filter-name>  
  3.       <filter-class>com.opensymphony.oscache.web.filter.CacheFilter</filter-class>  
  4.       <init-param>  
  5.           <param-name>time</param-name>  
  6.           <param-value>7200</param-value>  
  7.       </init-param>  
  8.       <init-param>  
  9.           <param-name>scope</param-name>  
  10.           <param-value>application</param-value>  
  11.       </init-param>  
  12. </filter>  
  13. <filter-mapping>  
  14.       <filter-name>CacheFilter</filter-name>  
  15.       <url-pattern>*.jsp</url-pattern>  
  16. </filter-mapping>  


这个filter应该放在最上面,这样才会第一个通过它,如果存在缓存,就不需要访问后面,直接返回

缓存的key将以请求的URI+查询字串组成,如果你访问/oscache/index.jsp?name=ttt和/oscache/index.jsp?name=ppp将得到两份缓存。缓存是在初次访问页面时进行的,后续的请求将会返回缓存中的内容。缓存中存放的内容为页面返回给用户的html源代码。

oscache.properties文件设置如下:

cache.memory=true
指定是否使用内存缓存,默认值为true,即使用内存缓存。
cache.capacity
指定缓存的容量,默认的容量是无限的。我们可以为它设置缓存数量,如:
cache.capacity=100000


如果我们要使用硬盘缓存,可以这样设置:
cache.memory=false
cache.path=d:\\cache  (指定,缓存保存的路径,注意:路径应采用双\符)
cache.persistence.class=com.opensymphony.oscache.plugins.diskpersistence.DiskPersistenceListener
cache.persistence.class用于设置持久化类。


五、SSI技术

1、SSI技术说明


<!--#include virtual="/global/foot.jsp"-->
类似jsp中<jsp:include page="/global/foot.jsp"/>
1.1、SSI技术不受运行环境影像,在java,dotnet,cgi等都可以ssi技术。
1.2、sii效率比jsp效率快。

2、SSI技术配置

tomcat 下使用ssi


1、把server/lib/servlets-ssi.renametojar的名称改名为servlets-ssi.jar (tomcat5.5有此步骤,tomcat6则没有此步骤)
2、设置conf/context.xml文件,在<Context>节点添加privileged="true"



3、在conf/web.xml中开启ssi,tomcat提供了两种开启ssi方式。一种是servlet,另一种是filter.
这里我们使用Servlet开启ssi。在web.xml中找到<servlet-name>ssi</servlet-name>,把对该Servlet的注释去掉。
使用SSI filter的话删除在SSI filter和filter-mapping周围的注释

然后根据shtml文件的编码格式指定inputEncoding和outputEncoding属性值。

<servlet>
        <servlet-name>ssi</servlet-name>
        <servlet-class>org.apache.catalina.ssi.SSIServlet</servlet-class>
        这里省略了一些代码
       <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>
        <load-on-startup>4</load-on-startup>
    </servlet>
当打开了上面servlet的注释之后,我们别忘了也要<servlet-mapping>的注释去掉,如:
    <servlet-mapping>
        <servlet-name>ssi</servlet-name>
        <url-pattern>*.shtml</url-pattern>
    </servlet-mapping>






3、SSI范例


3.1、include示范

<!--#include virtual="/global/foot.jsp"-->
<!--#include file="foot.jsp"-->



参数:
file 指定包含文件相对于本文档的位置
virtual 指定相对于服务器文档根目录的位置 如 /global/foot.html 表示


注意:文件名称必须带有扩展名。
示例:
<!--#flastmod file="foot.html"-->将当前目录下foot.html文件的最近更新日期插入到当前页面

<!--#fsize file="foot.html"-->将当前目录下news.html的文件大小入到当前页面

main.shtml内容

[html]  view plain copy print ?
  1. <html xmlns="http://www.w3.org/1999/xhtml"><HEAD>  
  2. <TITLE>测试</TITLE>  
  3. <META http-equiv="Content-Type" content="text/html; charset=UTF-8">  
  4. </HEAD>  
  5. <BODY>  
  6. <!--#include file="head.jsp" -->  
  7. <br>中部<br>  
  8. <!--#include file="foot.html" -->  
  9. </BODY></html>  


head.jsp内容:
<%@ page language="java" pageEncoding="UTF-8"%>
这是头部


foot.html内容:
这是尾部

3.2、SSI指令-- #flastmod 和 #fsize


#flastmod 和 #fsize 示范
作用:
#flastmod 文件最近更新日期
#fsize 文件的长度


语法:
<!--#flastmod file="文件名称"-->
<!--#fsize file="文件名称"-->


3.3、SSI指令-- #echo

#echo 示范
作用:将环境变量插入到页面中。
语法:
<!--#echo var="变量名称"-->

示例:
本文档名称:<!--#echo var="DOCUMENT_NAME"--> <br>
你的IP地址:<!--#echo var="REMOTE_ADDR"--> <br>
显示当前文档的虚拟路径:<!--#echo var="DOCUMENT_URI" -->


QUERY_STRING_UNESCAPED:显示未经转义处理的由客户端发送的查询字串,其中所有的特殊字符前面都有转义符"\"。
例如:<!--#echo var="QUERY_STRING_UNESCAPED" -->

请求完整路径为: <!--#echo var="DOCUMENT_URI" -->?<!--#echo var="QUERY_STRING_UNESCAPED" -->
<!--#config timefmt=“%Y-%m-%d %a %H:%M:%S”-->   %a表示星期几 ,这句是格式化下面输出的时间格式
现在时间:<!--#echo var="DATE_LOCAL"--> <br>


echo命令还可以显示以下环境变量:
SERVER_SOFTWARE:显示服务器软件的名称和版本。例如:
<!--#echo var="SERVER_SOFTWARE" --><br>
SERVER_NAME: 显示服务器的主机名称,DNS别名或IP地址。例如:
<!--#echo var="SERVER_NAME" --><br>
SERVER_PROTOCOL:显示客户端请求所使用的协议名称和版本,如HTTP/1.0。例如:
<!--#echo var="SERVER_PROTOCOL" --><br>
SERVER_PORT:显示服务器的响应端口。例如:
<!--#echo var="SERVER_PORT" --><br>
REQUEST_METHOD:显示客户端的文档请求方法,包括GET, HEAD, 和POST。例如:
<!--#echo var="REQUEST_METHOD" --><br>
REMOTE_HOST:显示发出请求信息的客户端主机名称。
<!--#echo var="REMOTE_HOST" --><br>
REMOTE_ADDR:显示发出请求信息的客户端IP地址。
<!--#echo var="REMOTE_ADDR" --><br>
AUTH_TYPE:显示用户身份的验证方法。
<!--#echo var="AUTH_TYPE" --><br>
REMOTE_USER:显示访问受保护页面的用户所使用的帐号名称。
<!--#echo var="REMOTE_USER" -->

3.4、SSI指令-- #set指令

#set
作用:可给变量赋值,以用于后面的if语句。

语法:
<!--#set var="变量名" value="变量值"-->


示例:
<!--#set var=“varname" value=“lihuoming"-->


3.5、SSI指令-- #if指令

#if
作用:创建可以改变数据的页面,这些数据根据使用if语句时计算的要求予以显示。
语法:
<!--#if expr="$变量名=\"变量值A\""-->
  显示内容
<!--#elif expr="$变量名=\"变量值B\""-->
  显示内容
<!--#else-->
  显示内容
<!--#endif"-->


示例:
<!--#set var="varname" value="b"-->
<!--#if expr="$varname=\"a\""-->
  A。
<!--#elif expr="$varname=\"b\"" -->
  B。
<!--#else-->
  other
<!--#endif"-->
注意:用于前面指令中的反斜杠,是用来代换内部的引号,以便它们不会被解释为结束表达式。不可省略。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值