java_2008_4_4 2010-01-19 11:26
浏览 210
已采纳

Tomcat 中的一些类的存在是否有意义

在 Tomcat 6 有 org.apache.jasper.tagplugins.jstl.core 包。这个包下有一些类,如 Catch.java,If.java,Choose.java,When.java 等等。它们好像和“核心标签库”有着什么关系。且都实现了 org.apache.jasper.compiler.tagplugin.TagPlugin 接口的 doTag(TagPluginContext ctxt) 方法。看了下 Tomcat 的 API。 其中对 TagPlugin 接口的说明是:
This interface is to be implemented by the plugin author, to supply an alternate implementation of the tag handlers. It can be used to specify the Java codes to be generated when a tag is invoked. An implementation of this interface must be registered in a file named "tagPlugins.xml" under WEB-INF

对 doTag 方法的说明是:
Generate codes for a custom tag.

按照接口和其方法的说明做了测试。发现 JSP 转译成的 Java 文件中,产生的代码不同。
其不同在于:
如果没有使用 TagPlugins 那么对标签的处理是在“标签类”中
如果使用了 TagPlugins 只不过是将处理的代码转译到了 JSP 所对应的 Java 文件中。
且如果要使用 TagPlugins ,“标签类”和对应的 tld 文件并不能缺少。且功能,效果完全和纯使用 “标签” 一样。

于是便产生了疑问:这些类的存在到底有着怎样的意义。在什么情况下使用?

  • 写回答

4条回答 默认 最新

  • yooylet 2010-01-19 21:27
    关注

    之前我没看过core包内的类的源码,甚至不知道还有tagplugin,前面的回答基于我的直觉。不过既然你这么认真,我就去找了找源码。代码支持了我的推测。
    [quote]org.apache.jasper.compiler.tagplugin
    Interface TagPlugin

    All Known Implementing Classes:
    Catch, Choose, ForEach, ForTokens, If, Import, Otherwise, Out, Param, Redirect, Remove, Set, Url, When [/quote]
    只有其中Choose,ForEach,If,Otherwise,Out,When 这五个逻辑控制类是final,其他是public。我想这应该能体现出作者希望被别人继承的目的了吧,否则他没必要这样取舍。
    至于什么时候需要写插件不是很清楚吗?——在你需要自定义如何翻译jsp到java代码的时候——这问题也需要具体问题具体分析。
    我们来看看其中的一个类的源码:
    [code="java"]
    package org.apache.jasper.tagplugins.jstl.core;

    import org.apache.jasper.compiler.tagplugin.TagPlugin;
    import org.apache.jasper.compiler.tagplugin.TagPluginContext;

    public class Param implements TagPlugin {

    public void doTag(TagPluginContext ctxt) {
    
        //don't support the body content
    
        //define names of all the temp variables
        String nameName = ctxt.getTemporaryVariableName();
        String valueName = ctxt.getTemporaryVariableName();
        String urlName = ctxt.getTemporaryVariableName();
        String encName = ctxt.getTemporaryVariableName();
        String index = ctxt.getTemporaryVariableName();
    
        //if the param tag has no parents, throw a exception
        TagPluginContext parent = ctxt.getParentContext();
        if(parent == null){
            ctxt.generateJavaSource(" throw new JspTagExcption" +
            "(\"<param> outside <import> or <urlEncode>\");");
            return;
        }
    
        //get the url string before adding this param
        ctxt.generateJavaSource("String " + urlName + " = " +
        "(String)pageContext.getAttribute(\"url_without_param\");");
    
        //get the value of "name"
        ctxt.generateJavaSource("String " + nameName + " = ");
        ctxt.generateAttribute("name");
        ctxt.generateJavaSource(";");
    
        //if the "name" is null then do nothing.
        //else add such string "name=value" to the url.
        //and the url should be encoded
        ctxt.generateJavaSource("if(" + nameName + " != null && !" + nameName + ".equals(\"\")){");
        ctxt.generateJavaSource("    String " + valueName + " = ");
        ctxt.generateAttribute("value");
        ctxt.generateJavaSource(";");
        ctxt.generateJavaSource("    if(" + valueName + " == null) " + valueName + " = \"\";");
        ctxt.generateJavaSource("    String " + encName + " = pageContext.getResponse().getCharacterEncoding();");
        ctxt.generateJavaSource("    " + nameName + " = java.net.URLEncoder.encode(" + nameName + ", " + encName + ");");
        ctxt.generateJavaSource("    " + valueName + " = java.net.URLEncoder.encode(" + valueName + ", " + encName + ");");
        ctxt.generateJavaSource("    int " + index + ";");
        ctxt.generateJavaSource("    " + index + " = " + urlName + ".indexOf(\'?\');");
        //if the current param is the first one, add a "?" ahead of it
        //else add a "&" ahead of it
        ctxt.generateJavaSource("    if(" + index + " == -1){");
        ctxt.generateJavaSource("        " + urlName + " = " + urlName + " + \"?\" + " + nameName + " + \"=\" + " + valueName + ";");
        ctxt.generateJavaSource("    }else{");
        ctxt.generateJavaSource("        " + urlName + " = " + urlName + " + \"&\" + " + nameName + " + \"=\" + " + valueName + ";");
        ctxt.generateJavaSource("    }");
        ctxt.generateJavaSource("    pageContext.setAttribute(\"url_without_param\"," + urlName + ");");
        ctxt.generateJavaSource("}");
    }
    

    }
    [/code] [url]http://www.google.com/codesearch/p?hl=zh-CN#cM_OVOKybvs/tomcat/tomcat-6/v6.0.10/src/apache-tomcat-6.0.10-src.zip|KNqCNnRERSg/apache-tomcat-6.0.10-src/java/org/apache/jasper/tagplugins/jstl/core/Param.java&q=org.apache.jasper.tagplugins.jstl.core.url&d=13[/url]
    从注释和代码可以分析出这个Param类是用来翻译url后的查询参数的,如果你不同意它生成的java代码,譬如想把" String " + encName + " = pageContext.getResponse().getCharacterEncoding();"这里的编码写死为utf8,你当然就可以继承Param.java,用你的代码覆写它。部署以后tomcat就会按你的意愿来翻译了。
    还要解释吗?
    还有更复杂的需求,例如我们知道如果一个jsp太复杂以致某个生成的java block超过了64k,javac就会发生编译错误。我们一般用include来切分页面,有了tagplugin机制,你可以自定义自己的翻译程序,自动把大jsp翻译成几个java文件来规避变异错误。

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(3条)

报告相同问题?

悬赏问题

  • ¥15 maple软件,用solve求反函数出现rootof,怎么办?
  • ¥65 汇编语言除法溢出问题
  • ¥15 Visual Studio问题
  • ¥15 state显示变量是字符串形式,但是仍然红色,无法引用,并显示类型不匹配
  • ¥20 求一个html代码,有偿
  • ¥100 关于使用MATLAB中copularnd函数的问题
  • ¥20 在虚拟机的pycharm上
  • ¥15 jupyterthemes 设置完毕后没有效果
  • ¥15 matlab图像高斯低通滤波
  • ¥15 针对曲面部件的制孔路径规划,大家有什么思路吗