设为首页 收藏本站
查看: 630|回复: 0

[经验分享] Tomcat的标签类实例缓存池控制

[复制链接]

尚未签到

发表于 2017-2-2 09:23:09 | 显示全部楼层 |阅读模式
支持现场时发现,对于自定义标签库(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/j2ee
http://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>
就可以了。

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-336386-1-1.html 上篇帖子: [Tomcat源码系列]结构解析 1)总体结构预览 下篇帖子: 检测tomcat服务状态,并能自动重启的代码
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表