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

【SAP PO】SAP PO 接口配置完整教程之一RFC服务发布 SAP RFC开发,PO接口配置 阅读详情

一、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 包


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



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"



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 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指令。

使用JAVA 的 POI 库 将DOC文件转为DOCX文件 java使用POI库,将doc文件转为docx文件 阅读详情

相关推荐

Windows系统监控实战:Grafana+Prometheus+node_exporter配置全攻略

本文提供了一套完整的Windows系统监控解决方案,详细介绍了如何使用Grafana、Prometheus和node_exporter(Windows版为windows_exporter)构建可视化监控平台。从环境准备、组件安装配置,到数据可视化与常见问题排查,手把手指导您实现从数据采集到仪表盘展示的全过程,帮助您从被动救火转向主动预警,有效保障Windows服务器稳定运行。

assembly8low的博客 247

Compass应用学习之搭建开发环境及书写compass工具类

[b]1.引入包搭建开发环境[/b] Common-logging.jar, Compass-2.2.0.jar Lucene-analyzers.jar, Lucene-core.jar Lucene-highlighter.jar, Lucene-queries.jar Lucene-snowball.jar, Lucene-spellchecker.jar Je-anal...

宁死致远,持之以恒 256

CentOS7下Graylog3.0高效日志管理:从零搭建到实战应用

本文详细介绍了在CentOS7操作系统上从零开始搭建Graylog3.0日志管理平台的完整过程。内容涵盖Java环境准备、MongoDB与Elasticsearch依赖安装、Graylog Server核心配置,并实战演示了通过Graylog Sidecar集中管理日志采集器以及配置邮件告警功能,为中小型团队提供了一个比ELK更轻量、易维护的一体化日志解决方案。

weixin_29207149的博客 85

使用compass+lucene实现简单的全文检索功能

这个例子使用Struts2+Spring2+Hibernate3组合来配合Compass2+Lucene2实现全文检索功能。首先看一下工程使用到的jar包以下是工程的文件结构:这个工程是在MyEclipse6下开发的。数据库使用MySQL5。新建数据库,库名:compass。/*MySQL Data TransferSource Host: localhostSou

【昆山人在上海】 8571

48V电动车电池包拆解:硬核入门BMS硬件设计与故障排查

BMS(电池管理系统)是锂电应用的核心安全与性能保障模块,其本质是融合电化学、模拟电路、嵌入式控制与热管理的交叉系统。理解BMS不能止步于SOC算法或通信协议,而需回归硬件本体——从电压采样精度、MOSFET驱动时序、被动均衡散热设计到NTC热耦合布局,每一处物理实现都直接决定系统可靠性。48V平台因兼具安全性(<60V ELV)、复杂度(13–14串)与产业普及性,成为BMS工程实践的理想标本。本文聚焦真实电池包中的PCB级设计缺陷识别、关键参数现场验证(如±5mV采样误差、5mΩ导通内阻)、UART协议

weixin_29191081的博客 232

ShaderJoy —— 简单又神奇的 “合体” 函数【GLSL】

smin 函数 它实际上有两种常见的实现方式 多项式 指数 多项式 smin 函数图 其对应的代码为 float smin( float a, float b ) { // 多项式 const float k = 0.5; float h = clamp(0.5 + 0.5 * (b - a) / k, 0.0, 1.0); return mix(b, a, h) - k * h * (1.0 - h); } 从上图中我们可以很明显的看出有两处不连...

ShaderJoy 的兴趣技术杂货铺 1857

can't find class org.compass.spring.device.SpringSyncTransactionGpsDeviceWrapper--compass找不到

<br />Caused by: org.springframework.beans.factory.CannotLoadBeanClassException : Cannot find class [org.compass.spring.device.SpringSyncTransactionGpsDeviceWrapper]<br /> <br />导入的compass的jar包版本问题,compass-2.2中没有org.compass.spring.device.SpringSyncTransac

archie2010的专栏 1560

第81篇:Vibe Coding时代:LangGraph + Eval评估体系实战,解决 Agent 优化全靠感觉的问题

本文介绍了一个为LangGraph Coding Agent设计的评估体系解决方案。文章首先指出了当前AI Coding Agent开发中的常见问题:优化过程缺乏客观评估标准,导致改进效果难以量化。随后提出了一个完整的评估框架,包括评估指标(任务成功率、质量指标、安全指标、成本指标和流程指标)、项目结构设计和评估案例集。 核心内容包括: 设计了JSON格式的评估案例集,覆盖正常任务、边界任务和高风险场景 实现了模拟Agent输出的演示代码 构建了多维度评分系统,包括关键词匹配、禁用词检测和成本评估 提供了评

sundong_81的博客 47

使用 Velocity 实现客户端和服务器端模板

Velocity 是一种通用的、开放源代码的模板解决方案,可以在报告生成/数据转换应用程序中独立使用,也可以在 MVC 模型框架中作为视图组件。本文中,Sing Li 介绍了 Velocity,并说明如何将其模板处理功能集成到客户端独立应用程序、服务器端 Web 应用程序或者 Web 服务中。在 HTML 或者 XML 这样的标准表示或交换格式中,文本性数据的操作和转换是一种频繁而且通常非常单

joy的专栏 1872

2026 蓝牙技术趋势展望:信道探测、Auracast、高吞吐 HID 与 AI 融合引领行业变革

蓝牙技术2026年展望:信道探测、Auracast广播音频和AI融合将引领创新。蓝牙信道探测技术将实现亚米级精确定位,在工业资产追踪和汽车数字钥匙领域大显身手。Auracast广播音频将持续拓展公共场所应用,提升音频包容性体验。高数据吞吐量和超低延迟功能将支持AR/VR等新兴场景。AI与蓝牙的深度融合将推动可穿戴设备智能化发展,实现实时健康监测和个性化音频服务。蓝牙技术凭借其多功能性和创新力,正成为连接万物的关键技术,持续推动行业变革和生活品质提升。

专业开发者的博客,一个从事Android WiFi和蓝牙的工程师 113

044、手持视频抖动严重?OpenCV 光流 + IMU 融合的电子防抖工程方案

本文探讨了基于OpenCV光流和IMU融合的手持视频电子防抖方案。作者从实际工程经验出发,分析了纯光流和纯IMU方案的局限性,指出时间戳对齐和坐标系标定是关键挑战。文章详细介绍了融合滤波器的实现方法,推荐互补滤波替代卡尔曼滤波,并提出了动态调整融合系数的策略。在光流算法优化方面,建议采用网格化FAST特征点和前后向误差检测。最后分享了运动补偿裁剪策略和多线程流水线设计,强调在嵌入式设备上使用NEON指令优化性能。该方案通过精确的时间同步和传感器融合,有效解决了手持拍摄中的高频抖动问题。

ai技术增长的博客 250

PowerDesigner15在win7-64位系统下对MySQL 进行反向工程以及建立物理模型产生SQL语句步骤图文傻瓜式详解

PowerDesigner15在win7-64位系统下对MySQL 进行反向工程以及建立物理模型产生SQL语句步骤图文傻瓜式详解 64位系统下一些注意事项。以及拷贝mysql数据库的一些注意事项。

大苯熊-我的书房 1万+

flowable工作流看这一篇就够了(基础篇)

接下来我们构建一个非常简单的请假流程,Flowable引擎需要流程定义为BPMN 2.0格式,这是一个业界广泛接受的XML标准。在Flowable术语中,我们将其称为一个流程定义(process definition)。一个流程定义可以启动多个流程实例(process instance)。流程定义可以看做是重复执行流程的蓝图。在这个例子中,流程定义定义了请假的各个步骤,而一个流程实例对应某个雇员提出的一个请假申请。

qq_38196449的博客 2万+

resin-4.0.37设置编码格式

Resin中就要修改配置文件来设置编码格式,方法如下:   打开C:\resin-4.0.37\conf\resin.xml文件   找到                                       expand-preserve-fileset="WEB-INF/work/**"                       multiversion-rou

大苯熊-我的书房 6668

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

Data-Structures-and-Algorithm-Analysis-in-Java.pdf

作者: Weiss, Mark A. 出版社: Addison Wesley Data Structures and Algorithm Analysis in Java is an “advanced algorithms” book that fits between traditional CS2 and Algorithms Analysis courses. In the old ACM Curriculum Guidelines, this course was known as CS7. This text is for readers who want to learn good programming and algorithm analysis skills simultaneously so that they can develop such programs with the maximum amo...

Struts2.3+Spring2.5.6+JPA(Hibernate3)项目移植入WebLogic12容器,并整合入MyEclipse10 图文详解

1、Struts2.3+Spring2.5.6+JPA(Hibernate3) 首先确保在tomcat7下启动运行无错误。   2、下载oepe-indigo-installer-12.1.1.0.1.201203120349-12.1.1-win32.exe,具体哪儿下载就不多说了。   3、安装oepe-indigo-installer-12.1.1.0.1.201203120349-

大苯熊-我的书房 4202

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

MyEclipse10.5 本地无网络安装SVN1.10.0并解决64位系统下出现的JavaHL错误、连接有问题错误。

与myeclise8.6本无无网络安装svn不一样。以前通过MyEclipse 10\dropins目录下建立xxx.link的方式指向MyEclipse 10\MyPlugs\svn 不行。按照其他文章所述,把link更改为lnk也无效。  总之通过link方式指向,肯定行不通的。 对于网络安装,我不详细讲解了。对于网络安装实在不感兴趣,时间的漫长是主要原因。 对于本无无网络

大苯熊-我的书房 3288

ssm框架搭建

这个是一个在idea上成功跑起来的ssm框架项目,保存在这里方便以后使用直接下载

FusionCharts报表

Fusioncharts 报表工具 1. Fusioncharts 介绍: Fusioncharts是一个基于Flash的图表组件,可以用来提供数据驱动的动态图标,fusioncharts可用于任何网页脚本语言如, HTML格式,JSP技术等等。提供交互式和强大的动态图标,fusioncharts充分利用流体美丽的Flash为模板,使用XML作为其数据接口,创造紧凑,互动和真正的动态图表。

大苯熊-我的书房 2445

mavn学习笔记(未整理)

path  mvn -version http://localhost:8081/nexus NEXUS_HOME=C:\nexus-2.1.1-bundle\nexus-2.1.1 %NEXUS_HOME%\bin\jsw\windows-x86-64 把C:\apache-maven-3.1.1\conf\settings.xml拷贝到D:/Maven

大苯熊-我的书房 2212

关于URL编码的经验。

<br />java.net.URLEncoder.encode("中文或者english或者其它字符","UTF-8");<br />java.net.URLDecoder.decode(inputvalue, "UTF-8");<br />这两个类怎么用,其他文章已经写的很多,我不复述了。<br /> <br />在编码方面。很多人会碰到各种乱码问题。手段很多。但有些很麻烦也不怎么管用。<br /> <br />一般来说,jsp文件需要utf-8编码格式,页面需要设定<br /><%@ page lan

大苯熊-我的书房 1565

JDK安装

配置环境变量:右击“我的电脑”-->"高级"-->"环境变量" 1)在系统变量里新建JAVA_HOME变量,变量值为:C:\Users\Administrator\AppData\Local\Genuitec\Common\binary\com.sun.java.jdk.win32.x86_64_1.6.0.013(根据自己的安装路径填写,示例为myeclipse10.5安装自带的jdk

大苯熊-我的书房 1475

MyEclipse开发邮件提示出错。NoClassDefFoundError: com/sun/mail/util/LineInputStream

<br />、用myEclipse进行开发,发送邮件,运行时可能会出现以下的<br />Exception in thread "main" java.lang.NoClassDefFoundError: com/sun/mail/util/LineInputStream<br />原因是jar包版本不统一,解决方法如下:<br /><br />删除Java EE 5 Libraries/javaee.jar/mail里的包有东西.<br /><br />具体方法如下:<br />用rar打开C:/User

大苯熊-我的书房 1290

云计算Saas

云计算Saas  笔记陆续添加中.... OSGI virgo-tomcat-server-3.0.2

大苯熊-我的书房 1267

对于框架Hibernate以及iBatis的个人认知

问题一:很多新手感觉框架繁琐,绕来绕去。是否有用,是否好!问题二:很多新手感觉H难以学习,配置方面弄得心烦意乱,有必要用H么!好,就以上问题,高人有高人的解答。但往往让新手看的心理缥缈,因为高人会从理论的角度说一大偏让新手更加莫不找头脑的言语。现在我就以一个刚刚做过SSH2以及SSI2的新人的角度来作为解答!希望能给与各位新人解惑!就个人目前状态,增对框架甚至Java莫名其妙。学习路程也比较颠倒。所以通过学习,把实例Struts+Spring+hibernate的项目完整的学习了一边,但学了会忘记,所以又自

大苯熊-我的书房 1224

浮点数的运算

问题的提出: 如果我们编译运行下面这个程序会看到什么? public class Test{     public static void main(String args[]){         System.out.println(0.05+0.01);

大苯熊-我的书房 1164

又一灵异事件--iBatis不支持枚举类型

<br />2.3.0.677版本不支持枚举。<br /> <br />2.3.4.726及以上支持枚举。害的我还以为自己写错了。

大苯熊-我的书房 976
上一篇: Android Service 服务(三)—— bindService与remoteService
下一篇: FusionCharts报表
webrobot
博客等级 码龄23年 111粉丝 69原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值