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

一、compass实现搜索
1、配置

1.1、加入如下jar包。



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

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

   <bean id="compass" class="org.compass.spring.LocalCompassBean">
		<!-- 指定映射类方式 -->
		<property name="classMappings">
			<list>
				<value>com.nbchina.bean.article.Article</value>
				<value>com.nbchina.bean.article.ArticleClass</value>
			</list>
		</property>
		<property name="compassSettings">
			<props>
				<prop key="compass.engine.connection">file://e:/index</prop>
				<prop key="compass.engine.highlighter.default.formatter.simple.pre"><![CDATA[<font color='red'>]]></prop>
				<prop key="compass.engine.highlighter.default.formatter.simple.post"><![CDATA[</font>]]></prop>
				<prop key="compass.transaction.factory">org.compass.spring.transaction.SpringSyncTransactionFactory</prop>
			</props>
		</property>
		<property name="transactionManager" ref="transactionManager" />
	</bean>
	<!-- CompassGps为CompassGpsDevice提供Compass对象,他们一起为程序提供索引的实时更新 -->
	<bean id="compassGps" class="org.compass.gps.impl.SingleCompassGps" init-method="start" destroy-method="stop">
		<property name="compass" ref="compass" />
		<property name="gpsDevices">
			<list>
				<bean class="org.compass.spring.device.SpringSyncTransactionGpsDeviceWrapper">
					<property name="gpsDevice">
						<!-- 为gpsDevice属性注入针对JPA的GPS驱动 -->
						<bean class="org.compass.gps.device.jpa.JpaGpsDevice">
							<property name="name" value="jpaDevice" />
							<property name="entityManagerFactory" ref="entityManagerFactory" />
							<property name="injectEntityLifecycleListener" value="true"/>
						</bean>
					</property>
				</bean>
			</list>
		</property>
	</bean>


Article实体内容如下

@Entity  @Searchable //通过这个注解,指明该类跟lucene中的document映射
public class Article {


	@Id
	@GeneratedValue(strategy=GenerationType.AUTO)
	@SearchableId
	private Integer id;
	
	@ManyToOne(cascade=CascadeType.REFRESH,optional=false)
	@JoinColumn(name="acid") 
	@SearchableComponent
	private ArticleClass ac;
	
	//@SearchableComponent代表还要跟其他类关联
	//boost=2数字越大级别越高,代表标题检索到的排序在前。默认为1.
	//index=Index.NO代表不参与索引
	//store=Store.YES代表储存
	//name="titleName" 有些字段和关联的其他表字段相同,那么可以重命名。
	@Column(length=80,nullable=false)
	@SearchableProperty(boost=2,store=Store.YES, name="titleName")
	private String title;
	
	@Column(length=255)
	private String titleIntact;
	
	@Column(length=10)
	private String titleFontColor;
	
	@Column(length=255)
	private String linkURL;
	
	@Column(length=255)
	private String keyword;
	
	@Column(length=255)
	@SearchableProperty(index=Index.NO,store=Store.YES)
	private String intro;
	
	@Column(nullable=false)
	private Integer hits = 1;
	
	@Temporal(TemporalType.DATE) @Column(nullable=false)
	@SearchableProperty(index=Index.NO,store=Store.YES,format="yyyy-MM-dd")
	private Date updateTime = new Date();
	
	@Column(nullable=false)
	private Boolean onTop = false;
	
	@Column(nullable=false)
	private Boolean elite = false;
	
	@Column(nullable=false)
	private Boolean hot = false;
	
	@Column(nullable=false)
	private Integer status = 0;
	
	@Column(nullable=false)
	private Integer deleted = 0;
	
	@Column(length=80)
	private String editor = "admin";
	
	@Column(length=80)
	private String author = "佚名";
	
	@Column(length=80)
	private String copyFrom;
	
	@Lob @Column(nullable=false)
	@SearchableProperty(store=Store.YES)
	private String content;
	
	@Column(nullable=true)
	private Integer includeImage = 0;
	
	@Lob
	private String uploadFiles;
	
	@Column(length=255)
	private String includeImageURL;
	
	@Column(length=255)
	private String voiceURL;
	

	
}


@Entity @Searchable(root=false)
public class ArticleClass implements Serializable{

	//@Searchable(root=false)代表不是搜索的根类,是Article的配角,关联的类而已。
	@Id
	@GeneratedValue(strategy=GenerationType.AUTO)
	@SearchableProperty(index=Index.NO, store=Store.YES)
	private Integer id;
	
	@Column(length=36,nullable=false)
	@SearchableProperty(index=Index.NO, store=Store.YES)
	private String name;
	
	@Column(length=200)
	private String note;
	
	@Column(nullable=false)
	private Boolean visible=true;
	
	@Column(nullable=false)
	private Integer orderId=0;
	
	@Column(length=255)
	private String imageURL;
	
	@Column(length=10)
	private String level;



	@OneToMany(cascade={CascadeType.REFRESH,CascadeType.REMOVE},mappedBy="parent")
	private Set<ArticleClass> childs = new HashSet<ArticleClass>();
	
	
	@ManyToOne(cascade=CascadeType.REFRESH)
	@JoinColumn(name="parentid")	
	private ArticleClass parent;
	
	@OneToMany(mappedBy="ac", cascade=CascadeType.REMOVE)
	@SearchableReference   //表示引用article
	private Set<Article> articles = new HashSet<Article>();

}


建立ArticleSearchServiceBean.java

@Service @Transactional
public class ArticleSearchServiceBean extends CompassDaoSupport implements ArticleSearchService {
	
	@Resource
	public void setSessionFactory(Compass compass){
		super.setCompass(compass);
	}
	
	public QueryResult<Article> search(String key, int startIndex, int maxResult) {
		return this.getCompassTemplate().execute(new ArticleResultCallback(key, startIndex, maxResult));
	}

}

建立ArticleResultCallback.java

public class ArticleResultCallback implements CompassCallback<QueryResult<Article>> {
	private String key;
	private int startIndex;
	private int maxResult;

	public ProductResultCallback(String key, int startIndex, int maxResult) {
		this.key = key;
		this.startIndex = startIndex;
		this.maxResult = maxResult;
	}

	public QueryResult<Article> doInCompass(CompassSession session) throws CompassException {
		List<Article> articles = new ArrayList<Article>();
		CompassHits hits = session.find(key);
		int lastIndex = startIndex + maxResult - 1;
		if(lastIndex>(hits.length()-1)) lastIndex = hits.length()-1;
		for(int i=startIndex; i<=lastIndex; i++){
			Article article = (Article) hits.data(i);
			if(hits.highlighter(i).fragment("title")!=null){//处理高亮显示
				article.setTitle(hits.highlighter(i).fragment("title"));
			}
			articles.add(article);
		}
		QueryResult<Article> qr = new QueryResult<Article>();
		qr.setResultlist(articles);
		qr.setTotalrecord(hits.length());//设置查询到的总记录数
		return qr;
	}

}

ArticleSearchAction内加入如下内容

		QueryResult<Article> qr = articleSearchService.search("关键字", pageView.getFirstResult(), pageView.getMaxresult());
		
		pageView.setQueryResult(qr);



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

order实体内加入

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

OrderServiceBean内加入

	public Order getLockOrder(String orderid, String employee){
		em.createQuery("update Order o set o.employee=?1 where o.orderid=?2 and o.employee is null")
			.setParameter(1, employee).setParameter(2, orderid).executeUpdate();
		em.flush();
		return this.find(orderid);
	}
	public void unLock(String orderid){
		em.createQuery("update Order o set o.employee=?1 where o.orderid=?2")
		.setParameter(1, null).setParameter(2, orderid).executeUpdate();
	}

action内加入

if(!order.getEmployee().equals(username)){
			request.setAttribute("message", "该订单已被"+ order.getEmployee() + "锁定");
			return mapping.findForward("message");	
		}


jsp内判断

<c:if test="${empty entry.employee || entry.employee==employee.username}"><a href="">载入订单</a></c:if>
<c:if test="${!empty entry.employee && entry.employee!=employee.username}">被${entry.employee}锁定</c:if>



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

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

		try{
			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");
			Velocity.init(prop);
			System.out.println("Velocity Initialized");
		}catch( Exception e ){
			System.out.println("VSelocity error");
			e.printStackTrace();
		}

引入Velocity1.6 jar 包
compass实现搜索、订单载入功能、velocity模版静态化、OSCache优化性能、SSI实现_第1张图片

2、实例

WebRoot-WEB-INF-VM目录下建立mailContent.vm
文件内容如下
<html>
<head>
<title>测试</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
</head>
尊敬的客户:${userName}
</body>
</html>
使用代码如下
			Template template = Velocity.getTemplate("mailContent.vm","UTF-8");
			VelocityContext context = new VelocityContext();
			context.put("userName", "测试名");
			StringWriter writer = new StringWriter();
			template.merge(context, writer);
			writer.flush();
			String mailContent = writer.toString();
			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

compass实现搜索、订单载入功能、velocity模版静态化、OSCache优化性能、SSI实现_第2张图片

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代码如下。

function readCookieByName(name){
	var nameOfCookie = name + "=";
	var x = 0;
	while ( x <= document.cookie.length ){
		var y = (x+nameOfCookie.length);
		if ( document.cookie.substring( x, y ) == nameOfCookie ) {
			if ( (endOfCookie=document.cookie.indexOf( ";", y )) == -1 )
			endOfCookie = document.cookie.length;
			return document.cookie.substring( y, endOfCookie );
		}
		x = document.cookie.indexOf( " ", x ) + 1;	
		if ( x == 0 ) break;
	}
	return "";
}
function readWelcomeMsg(){
	try{
		var msg = readCookieByName("realName");
		if(msg!=""){
			return decodeURI(msg);
		}else{
			msg = readCookieByName("userName");
			if(msg!="") return msg;
		}		
	} catch(e){
		;
	}
	return "";
}
document.write(readWelcomeMsg());



使用OSCache作页面全局缓存

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

<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>*.jsp</url-pattern>
</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"

compass实现搜索、订单载入功能、velocity模版静态化、OSCache优化性能、SSI实现_第3张图片

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>

compass实现搜索、订单载入功能、velocity模版静态化、OSCache优化性能、SSI实现_第4张图片

compass实现搜索、订单载入功能、velocity模版静态化、OSCache优化性能、SSI实现_第5张图片


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 xmlns="http://www.w3.org/1999/xhtml"><HEAD>
<TITLE>测试</TITLE>
<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
</HEAD>
<BODY>
<!--#include file="head.jsp" -->
<br>中部<br>
<!--#include file="foot.html" -->
</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"-->
注意:用于前面指令中的反斜杠,是用来代换内部的引号,以便它们不会被解释为结束表达式。不可省略。


一般来说ssi大多使用include指令。

你可能感兴趣的:(compass实现搜索、订单载入功能、velocity模版静态化、OSCache优化性能、SSI实现)