我们在编写自定义标签的时候设置属性如下

public class InputTag extends TagSupport {private static final long serialVersionUID = 1L;private String onclick;private String style;private String styleClass;private String value;private String id;

在页面上如果同时使用两个标签:

 <h3:input type="button" οnclick="myFun()" name="name" id="id"style="style" styleClass="styleClass" value="中国人" url="url"pid="pid" isValidated="true">中国人</h3:input><h3:input type="button" οnclick="myFun()" name="name" id="id"style="style" styleClass="styleClass" value="美国人" url="url"pid="pid" isValidated="true"></h3:input>

从后台发现打印的InpuTag都是同一个对象!

发现这个后,我十分担心线程安全问题!比如这些getType();setType(); !

于是就看了下jsp生成的Servlet源代码

    out.write("\t<body>\r\n");out.write("\t\t");//调用InputTagif (_jspx_meth_h3_005finput_005f0(_jspx_page_context))return;out.write("\r\n");out.write("\t\t\r\n");out.write("\t\t");//调用InputTagif (_jspx_meth_h3_005finput_005f1(_jspx_page_context))return;out.write("\r\n");out.write("\t</body>\r\n");

再接着看_jspx_meth_h3_005finput_005f0方法

  private boolean _jspx_meth_h3_005finput_005f0(PageContext _jspx_page_context)throws Throwable {PageContext pageContext = _jspx_page_context;JspWriter out = _jspx_page_context.getOut();//  h3:input tag.InputTag _jspx_th_h3_005finput_005f0 = (tag.InputTag) _005fjspx_005ftagPool_005fh3_005finput_0026_005fvalue_005furl_005ftype_005fstyleClass_005fstyle_005fpid_005fonclick_005fname_005fisValidated_005fid.get(tag.InputTag.class);_jspx_th_h3_005finput_005f0.setPageContext(_jspx_page_context);_jspx_th_h3_005finput_005f0.setParent(null);// /button2.jsp(12,2) name = type type = null reqTime = true required = false fragment = false deferredValue = false expectedTypeName = null deferredMethod = false methodSignature = null_jspx_th_h3_005finput_005f0.setType("button");// /button2.jsp(12,2) name = onclick type = java.lang.String reqTime = false required = true fragment = false deferredValue = false expectedTypeName = null deferredMethod = false methodSignature = null    _jspx_th_h3_005finput_005f0.setPid("pid");// /button2.jsp(12,2) name = isValidated type = null reqTime = true required = false fragment = false deferredValue = false expectedTypeName = null deferredMethod = false methodSignature = null_jspx_th_h3_005finput_005f0.setIsValidated("true");int _jspx_eval_h3_005finput_005f0 = _jspx_th_h3_005finput_005f0.doStartTag();if (_jspx_eval_h3_005finput_005f0 != javax.servlet.jsp.tagext.Tag.SKIP_BODY) {do {out.write("\r\n");out.write("\t\t中国人\r\n");out.write("\t\t");int evalDoAfterBody = _jspx_th_h3_005finput_005f0.doAfterBody();if (evalDoAfterBody != javax.servlet.jsp.tagext.BodyTag.EVAL_BODY_AGAIN)break;} while (true);}if (_jspx_th_h3_005finput_005f0.doEndTag() == javax.servlet.jsp.tagext.Tag.SKIP_PAGE) {_005fjspx_005ftagPool_005fh3_005finput_0026_005fvalue_005furl_005ftype_005fstyleClass_005fstyle_005fpid_005fonclick_005fname_005fisValidated_005fid.reuse(_jspx_th_h3_005finput_005f0);return true;}
    _005fjspx_005ftagPool_005fh3_005finput_0026_005fvalue_005furl_005ftype_005fstyleClass_005fstyle_005fpid_005fonclick_005fname_005fisValidated_005fid.reuse(_jspx_th_h3_005finput_005f0);return false;}

最关键就是这句了,看他如何获得自定义标签对象: tag.InputTag _jspx_th_h3_005finput_005f0 = (tag.InputTag) _005fjspx_005ftagPool_005fh3_005finput_0026_005fvalue_005furl_005ftype_005fstyleClass_005fstyle_005fpid_005fonclick_005fname_005fisValidated_005fid.get(tag.InputTag.class);

解释下:

_jspx_th_h3_005finput_005f0 是InputTag 的实例 也就是<h3:input.

005fjspx_005ftagPool_005fh3_005finput_0026_005fvalue_005furl_005ftype_005fstyleClass_005fstyle_005fpid_005fonclick_005fname_005fisValidated_005

是TagHandlerPool的实例

自定义标签是通过这个TagHandlerPool.get 来获取的!

举一反三,有借就有还TagHandlerPool.reuse用来回收这个对象!

TagHandlerPool.get

TagHandlerPool.reuse

方法如下:

   /*** Gets the next available tag handler from this tag handler pool,* instantiating one if this tag handler pool is empty.** @param handlerClass Tag handler class** @return Reused or newly instantiated tag handler** @throws JspException if a tag handler cannot be instantiated*/public Tag get(Class handlerClass) throws JspException {Tag handler = null;synchronized( this ) {if (current >= 0) {handler = handlers[current--];return handler;}}// Out of sync block - there is no need for other threads to// wait for us to construct a tag for this thread.try {Tag instance = (Tag) handlerClass.newInstance();AnnotationHelper.postConstruct(annotationProcessor, instance);return instance;} catch (Exception e) {throw new JspException(e.getMessage(), e);}}
    /*** Adds the given tag handler to this tag handler pool, unless this tag* handler pool has already reached its capacity, in which case the tag* handler's release() method is called.** @param handler Tag handler to add to this tag handler pool*/public void reuse(Tag handler) {synchronized( this ) {if (current < (handlers.length - 1)) {handlers[++current] = handler;return;}}// There is no need for other threads to wait for us to releasehandler.release();if (annotationProcessor != null) {try {AnnotationHelper.preDestroy(annotationProcessor, handler);} catch (Exception e) {log.warn("Error processing preDestroy on tag instance of " + handler.getClass().getName(), e);}}}

现在就明白了所有的tag对象都是有一个对象池来维护的,一是方便了重用,而是做到了线程同步。

总结:自定义标签是线程安全的,同时也是可重用的!

同时又有另一个疑问

synchronized( this ) {
            if (current >= 0) {
                handler = handlers[current--];
                return handler;
            }
        }

感觉这种方法可能只能在一个页面上共享,另一个页面上的tag估计是不能共享的!

后来看了下生成的servelt代码

如下:

public void _jspInit() {_tagpool = org.apache.jasper.runtime.TagHandlerPool.getTagHandlerPool(getServletConfig());_el_expressionfactory = _jspxFactory.getJspApplicationContext(getServletConfig().getServletContext()).getExpressionFactory();_jsp_annotationprocessor = (org.apache.AnnotationProcessor) getServletConfig().getServletContext().getAttribute(org.apache.AnnotationProcessor.class.getName());}

可以看到_tagpool 是根据ServletConifg来生成的

TagHandlerPool.getTagHandlerPool代码如下

 public static TagHandlerPool getTagHandlerPool( ServletConfig config) {TagHandlerPool result=null;String tpClassName=getOption( config, OPTION_TAGPOOL, null);if( tpClassName != null ) {try {Class c=Class.forName( tpClassName );result=(TagHandlerPool)c.newInstance();} catch (Exception e) {e.printStackTrace();result=null;}}if( result==null ) result=new TagHandlerPool();result.init(config);return result;}

jsp自定义标签 线程安全相关推荐

  1. jsp自定义标签学习

    简单的说明: 1,说明---jsp自定义标签: HelloWorld:jsp自定义标签的使用流程: QueryTag:带属性标签的定义以及连接数据库使用: IteratorTag:带标签体的标签定义以 ...

  2. 如何使用jsp自定义标签 JspTag 使用入门

    java开发中,sturts标签和c标签就是我们常用的两种标签,本文主要教大家如何定义自己的标签,已达到代码整合,公共化的目的.通过jsp自定义标签,可以将一个元素,或者一个表格,一个div甚至整个页 ...

  3. 转载:javaweb学习总结(二十三)——jsp自定义标签开发入门

    javaweb学习总结(二十三)--jsp自定义标签开发入门 转自:http://www.cnblogs.com/xdp-gacl/p/3916734.html 一.自定义标签的作用 自定义标签主要用 ...

  4. JSP自定义标签学习笔记

    http://blog.csdn.net/liangbinny/article/details/6309893 本文是本人学习<JavaWeb学习>书籍所记下的学习笔记 一.概述 JSP ...

  5. JSP自定义标签开发入门

    一般情况下开发jsp自定义标签需要引用以下两个包 import javax.servlet.jsp.*; import javax.servlet.jsp.tagext.*; 首先我们需要大致了解开发 ...

  6. html模板(base标签,meta标签,禁用浏览器缓存)+JSP自定义标签荔枝

    [1]html模板 <html> <head><!-- base标签表示uri相对路径的基准路径 --><base href="http://loc ...

  7. jsp自定义标签(taglib)编写的原理和实现

    jsp自定义标签(taglib)编写的原理和实现 转:http://www.javaeye.com/topic/157737 个tag就是一个普通的java类,它惟一特别之处是它必须继承TagSupp ...

  8. 浅谈JSP自定义标签实现过程

    (一) 没有正文的JSP自定义标签实现 (1):定义JSP自定义标签处理类 import java.io.IOException; import java.util.Date; import java ...

  9. JSP自定义标签详解(1)

    JSP自定义标签 自定义JSP标签概述 自定义JSP标签就是程序员定义的一种JSP标签,这种标签把那些信息显示逻辑封装在一个单独的Java类中,通过一个XML文件来描述它的使用.当页面中需要使用类似的 ...

  10. jsp自定义标签的问题Unable to load tag handler class

    本人在做jsp自定义标签的时候,报错: Unable to load tag handler class 后面找到原因是:在eclipse开发中,之前替换了一个jar包,原来的jar在下面视图中报红叉 ...

最新文章

  1. 使用Bioconda管理生信软件(以bwa为例)
  2. null?对象?异常?到底应该如何返回错误信息
  3. TCP选项:TCP_NODELAY和TCP_CORK
  4. springboot对于redis的增删改查
  5. freecplus框架简介
  6. python编程(nginx、uwsgi和webpy)
  7. 千脑智能理论:开启创造机器智能的路线图 | 《千脑智能》
  8. 推荐三十款最好的免费项目管理软件
  9. Java Web 项目基于IDEA的增量补丁打包插件
  10. Matlab遗传算法大纲
  11. 运算符之前加加后加加的运算规则
  12. 数学符号、希腊、拉丁字母、单位、标点的中英文读法
  13. java验证手机号码
  14. 图形界面介绍——Blockage相关
  15. 安装gin和mod使用
  16. 投资不足半年,字节跳动退出李子柒签约公司“微念”
  17. TypeError [ERR_INVALID_ARG_TYPE]: The “path“ argument must be of type string(已解决)
  18. 飞飞php影视系统源码怎么改,飞飞cms影视系统安装说明 飞飞影视系统建站流程...
  19. Charles设置代理后无法上网问题
  20. C语言实现不同进制之间的转换

热门文章

  1. 利用-flat.vmdk文件恢复虚拟机
  2. JavaScript实现输入框(密码框)出现提示语
  3. php期末作业总结,期末考试总结与反思(精选6篇)
  4. 5G 与 WIFI6 的对比
  5. 打印机打印的时候会打印计算机用户,打印机打印的时候出现administrator是什么意思...
  6. 循环结构:while和do...while循环语句
  7. js-xlsx使用-解析生成xlsx文件
  8. idea 2020.2隐藏了菜单栏Main Menu 恢复方法
  9. 如何实现网页视频聊天?
  10. 有一个小于500的三位数abc,对于这三个数,甲乙丙丁有如下说法:.......................请问2a+b-c等于多少?