首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 软件管理 > 软件架构设计 >

Tomcat的标签种实例缓存池控制

2012-09-12 
Tomcat的标签类实例缓存池控制支持现场时发现,对于自定义标签库(tld),Tomcat/JBoss和其他一些中间件,如金

Tomcat的标签类实例缓存池控制
支持现场时发现,对于自定义标签库(tld),Tomcat/JBoss和其他一些中间件,如金蝶Apusic表现的不一样。Tomcat会把自定义标签的类实例缓存起来,为下一个用户/请求使用——更确切的说,是维护了一个标签处理器缓存池,可以减少标签类对象的new操作,在一定程度上提升性能,应用服务器代码可以参考org.apache.jasper.runtime.TagHandlerPool。这是Tomcat的缺省行为。然而,对于其他中间件,如Apusic,缺省行为则不一样,它总是为处理某个请求new一个全新的标签类对象。差别是细微的,但给用户应用的可移植性造成了影响。

例如有这样的标签类,在判断age字段为空时,向页面输出一个请求参数的信息:

package com.yd.mytag;import java.io.IOException;import javax.servlet.ServletRequest;import javax.servlet.jsp.JspException;import javax.servlet.jsp.JspTagException;import javax.servlet.jsp.tagext.TagSupport;public class HelloWorldTag extends TagSupport {/****/private static final long serialVersionUID = -3626997868569105660L;public String age;public String getAge() {return age;}public void setAge(String age) {this.age = age;}public HelloWorldTag(){System.out.println("HelloWorldTag init=======================");System.out.println("AGE IS "+age);}//private static final long serialVersionUID = 3174234039143531070L;public int doStartTag() throws JspException {return EVAL_BODY_INCLUDE;}public int doEndTag() throws JspException {//String age="";try {ServletRequest request =(ServletRequest)this.pageContext.getRequest();System.out.println(request.getParameter("age"));if(age==null || age.equals(""))//{//    age="blank";// }else {age = request.getParameter("age");//}pageContext.getOut().write("age is "+age);pageContext.getOut().flush();} catch (IOException ex) {throw new JspTagException("ERROR");}finally{}return EVAL_PAGE;}public void release(){//age="";}}


简单的JSP页面如下:

<%@ page language="java" import="java.util.*" pageEncoding="utf-8" %><%@ taglib uri="/tld/helloworld" prefix="mytag" %><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"><html><head><title>MyJSP</title></head><body><h1>customized tag</h1><br><mytag:helloworld></mytag:helloworld><br><a href="index.jsp?age=testone" >testone</a><a href="index.jsp?age=testtwo" >testtwo</a><a href="index.jsp?age=99999" >9999999</a></body></html>


以下是web.xml

<?xml version="1.0" encoding="UTF-8"?><web-app version="2.4"xmlns="http://java.sun.com/xml/ns/j2ee"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://java.sun.com/xml/ns/j2eehttp://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"><welcome-file-list><welcome-file>index.jsp</welcome-file></welcome-file-list><jsp-config><taglib><taglib-uri>/tld/helloworld</taglib-uri><taglib-location>/WEB-INF/tlds/helloworld.tld</taglib-location></taglib></jsp-config></web-app>


有这样的hellowworld.tld在WEB-INF/tlds下:

<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE taglib PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN""http://java.sun.com/dtd/web-jsptaglibrary_1_2.dtd"><taglib><tlib-version>1.0</tlib-version><jsp-version>1.4</jsp-version><short-name>mytag</short-name><tag><name>helloworld</name><tag-class>com.yd.mytag.HelloWorldTag</tag-class><body-content>empty</body-content></tag></taglib>


于是,产生的结果是,在缺省的Tomcat上,age的值随着HelloWorldTag的实例被池化复用而随之“缓存”起来,jsp页面的输出随着几个链接的点击不会根据parameter的变化而变化,不是开发人员希望看到的行为,但其他应用服务器,如Apusic却可以。初看来这似乎是Tomcat的bug,但实际深入APP SERVER的源代码和实现机制分析,Tomcat不但机制更为合理(提供了提升性能的缓存),而且很灵活的可以将它的行为配置得和Apusic等应用服务器一直,即绕开TagHandlerPool,方法如下:

在$TOMCAT_HOME/conf/web.xml中,找到有

<servlet-name>JSP-Compiler</servlet-name><servlet-class>org.apache.jasper.servlet.JspServlet</servlet-class>

的一段配置,加入以下参数即可:

<init-param><param-name>tagpoolMaxSize</param-name><param-value>0</param-value><!--0表示空,-1表示无限大--></init-param>


此外,根据Tomcat官方文档http://tomcat.apache.org/tomcat-6.0-doc/jasper-howto.html,enablePooling这个参数似乎也有同样的功效,不幸的是,根据我的实验,单独设置enablePooling为false并不能够解决上面的问题。

对于JBoss,由于web部分基本是采用Tomcat内核,因此,修改JBoss的deploy/jboss-web.

deployer/conf/web.xml(针对版本4.2~4.3)
找到这一部分:
<servlet><servlet-name>jsp</servlet-name><servlet-class>org.apache.jasper.servlet.JspServlet</servlet-class>.....<load-on-startup>3</load-on-startup></servlet>


在<load-on-startup>3</load-on-startup>之前加入这一段:
<init-param><param-name>tagpoolMaxSize</param-name><param-value>0</param-value></init-param>

就可以了。

热点排行