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

[经验分享] 解析tomcat tagplugin

[复制链接]

尚未签到

发表于 2017-1-20 06:32:14 | 显示全部楼层 |阅读模式
  利用JSP实现动态页面,常常会写一个自定义标签来实现页面的组件化设计。一般是写一个类让它继承TagSupport类,然后将页面的逻辑封装在TagSupport中,然后在tld文件中添加自定义标签的属性及标签名称声明。 之后就可以在jsp页面使用自定义标签了,以上提到的自定义标签只是一个大概,在此不赘述了。
  另外实现页面组件化设计还有另外一个途径,那就是通过tagplugin来实现。

package org.apache.jasper.compiler.tagplugin;
public interface TagPlugin {
void doTag(TagPluginContext ctxt);
}

package org.apache.jasper.compiler.tagplugin;
public interface TagPluginContext {
boolean isScriptless();
// 是否设置了自定义标签上的值
boolean isAttributeSpecified(String attribute);
// 以该自定义标签为上线文,取得该自定义标签所对应的临时变量名   
String getTemporaryVariableName();
// 在JSP生成java文件的过程中会在import区块中导入import的内容   
void generateImport(String s);
//
void generateDeclaration(String id, String text);
/**
* Generate Java source codes
*/
void generateJavaSource(String s);
//
boolean isConstantAttribute(String attribute);
// 取得自定义标签定义的属性值,isAttributeSpecified()方法为查询该属性值是否有值
String getConstantAttribute(String attribute);
// 由于属性值是可以写el的,所以在标签生成结果时候,会在生成java文件的过程中自动调用解析el语法的功能模块
void generateAttribute(String attribute);
// 生成自定义标签的body内容,注意:如果在doTag函数中中没有调用该方法的话,tagmanager会在标签解析呃呃最后自动调用标签的内容块
void generateBody();
void dontUseTagPlugin();
TagPluginContext getParentContext();
void setPluginAttribute(String attr, Object value);
Object getPluginAttribute(String attr);
}
  以上这两个接口是包装在tomcat的jasper.jar这个jar包中的。

 下面介绍如何在web应用中实现一个简单的tagplugin
  首先,写一个类实现TagPlugin 接口:

public class NameTagPlugin implements TagPlugin {
private static int count = 1;
public void doTag(TagPluginContext ctx) {
System.out.println(ctx.getTemporaryVariableName());
ctx.generateDeclaration("cssDependants","private static final java.util.List css_dependants = new java.util.ArrayList(1); ");
if (ctx.isAttributeSpecified("name")) {
ctx.generateDeclaration("cssDependantsPath" + (count++),
"static{css_dependants.add(\""
+ ctx.getConstantAttribute("name") + "\");}");
}
System.out.println(ctx.getConstantAttribute("name"));
}
}
  注意:以上这个类需要放在 $catalina_home$/common/classes这个目录下,因为tagplugin这个类是在jsp编译成java文件的时候调用的,当java文件被编译成class字节码之后就不会调用tagplugin了。
  TagPluginContext类的generateDeclaration有两个参数,id和 content,当在一个pagecontext中重复调用generateDeclaration()这个方法如果前后两次调用id参数是一样的,那么在java文件中生成的declaration块就会显示第一次调用所输入content内容。
  以上这段代码会使自定义标签编译成java文件的时候生成,如下内容(代码片段):

public final class nametagtest_jsp extends org.apache.jasper.runtime.HttpJspBase
implements org.apache.jasper.runtime.JspSourceDependent {
private static final java.util.List css_dependants = new java.util.ArrayList(1);
static{css_dependants.add("hello");}
static{css_dependants.add("code");}
private static java.util.List _jspx_dependants;
static {
_jspx_dependants = new java.util.ArrayList(1);
_jspx_dependants.add("/WEB-INF/koubeitagtest.tld");
}
  再写一个自定义标签(这个尽量简单一些,写一个类似helloworld的就行了)

public class TestTag extends TagSupport {
private String name;
public int doStartTag() throws JspException {
try {
this.pageContext.getOut().write(name);
} catch (IOException e) {
throw new JspException(e);
}
return EVAL_BODY_INCLUDE;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
  将自定义标签声明在/WEB-INF/koubeitagtest.tld,这个文件中。

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<taglib xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.0" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-jsptaglibrary_2_0.xsd">
<display-name>koubeitest</display-name>
<tlib-version>2.2.4</tlib-version>
<short-name>tt</short-name>
<uri>koubeitest-tags</uri>
<tag>
<name>name</name>
<tag-class>com.koubei.example.tag.TestTag</tag-class>
<body-content>JSP</body-content>
<attribute>
<name>name</name>
<required>false</required>
<rtexprvalue>false</rtexprvalue>
</attribute>
</tag>
</taglib>

  创建tagPlugins.xml文件,注意文件名不能有错误,大小写不能错。存放在WEB-INF文件夹下,当时我因为文件名写成了tagplugin.xml造成plugin没有起作用。

<?xml version="1.0"?>
<tag-plugins>
<tag-plugin>
<tag-class>com.koubei.example.tag.TestTag</tag-class>
<plugin-class>com.koubei.example.tag.NameTagPlugin</plugin-class>
</tag-plugin>
</tag-plugins>


 总结:


  • 使用tagplugin和customtag都是为了在jsp页面中实现页面组件化设计的,但是他们两个各有侧重,tagplugin是在jsp编译成java文件的编译期使用的(tomcat中是使用JDTCompiler来编译的),而customTag是在jsp页面运行期执行的,tagplugin只会执行一次,而customtag会jsp页面运行的时候每次都执行的。
  • 在试验过程中发现,tagplugin和customtag这两种技术的使用是互斥的,如果在tagPlugins.xml中为某个自定义标签配置了插件的话那么,改custometag的dostart和doend方法就都不会执行了,而且全要依赖在tagplugin的dotag方法中在jsp编译的时候预先静态写入到java文件中的内容来执行了(这点稍微有点不爽)
  • 何时应该使用tagplugin这个技术,原先有的内容生成如果是在自定义标签输出的,但是这个内容又不是以来每个访问页面的用户身份而取得的就能用tagplugin技术,这样会大幅提升页面运行的效率。 唯一不足的是,使用tagplugin还是要写一个plugin所对因的customtag,说白了这个customtag就是一个傀儡。

运维网声明 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-330779-1-1.html 上篇帖子: tomcat catalina.bat 下篇帖子: 花生壳+Tomcat
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

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

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

扫描微信二维码查看详情

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


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


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


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



合作伙伴: 青云cloud

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