JSP中插件设计_jsp中插件设计

2020-02-29 其他范文 下载本文

JSP中插件设计由刀豆文库小编整理,希望给你工作、学习、生活带来方便,猜你可能喜欢“jsp中插件设计”。

开发一个调试JSP的Eclipse插件

本文通过开发一个JSP 编辑器插件的示例,介绍了 Eclipse 中设置 JSP 断点的方法,以及如何远程调试 JSP。作为基础知识,本文的前两部分描述了 JAVA Debug 和 JSR-45 的基本原理。

环境要求: 本文的代码是在 Eclipse3.0.0,JDK1.4.2 和 Tomcat5.0.5 上测试过的。

JAVA 调试框架(JPDA)简介

JPDA 是一个多层的调试框架,包括 JVMDI、JDWP、JDI 三个层次。JAVA 虚拟机提供了 JPDA 的实现。其开发工具作为调试客户端,可以方便的与虚拟机通讯,进行调试。Eclipse 正是利用 JPDA 调试 JAVA 应用,事实上,所有 JAVA 开发工具都是这样做的。SUN JDK 还带了一个比较简单的调试工具以及示例。

 JVMDI 定义了虚拟机需要实现的本地接口

 JDWP 定义了JVM与调试客户端之间的通讯协议

调试客户端和JVM 既可以在同一台机器上,也可以远程调试。JDK 会包含一个默认的实现 jdwp.dll,JVM 允许灵活的使用其他协议代替 JDWP。SUN JDK 有两种方式传输通讯协议:Socket 和共享内存(后者仅仅针对 Windows),一般我们都采用 Socket 方式。

你可以用下面的参数,以调试模式启动JVM-Xdebug-Xnoagent-Xrunjdwp:transport=dt_socket,addre=8000,server=y,suspend=n-Xrunjdwp JVM 加载 jdwp.dll transport=dt_socket 使用 Socket 传输 addre 表示调试端口号 server=y 表示 JVM 作为服务器,建立 Socket suspend=n 表示启动过程中,JVM 不会挂起去等待调试客户端连接

 JDI 则是一组JAVA接口

如果是一个 JAVA 的调试客户端,只要实现 JDI 接口,利用JDWP协议,与虚拟机通讯,就可以调用JVMDI了。

下图为 JPDA 的基本架构:

Components Debugger Interface / |-----------------------| / | VM | debuggee----(|-----------------------|

参见:http://java.sun.com/j2se/1.4.2/docs/guide/jpda/architecture.HTML

Eclipse作为一个基于 JAVA 的调试客户端,利用 org.eclipse.jdt.debug Plugin 提供了JDI 的具体实现。JDI 接口主要包含下面 4 个包

com.sun.jdi com.sun.jdi.connect com.sun.jdi.event com.sun.jdi.request

本文不对 JDI 进行深入阐述,这里重点介绍 JDI 中与断点相关的接口。

 com.sun.jdi

主要是JVM(VirtualMachine)线程(ThreadReference)调用栈(StackFrame)以及类型、实例的描述。利用这组接口,调试客户端可以用类似类反射的方式,得到所有类型的定义,动态调用 Cla 的方法。 com.sun.jdi.event

封装了JVM 产生的事件,JVM 正是将这些事件通知给调试客户端的。例如 BreakpointEvent 就是 JVM 执行到断点的时候,发出的事件;ClaPrepareEvent就是 Cla 被加载时发出的事件。 com.sun.jdi.request

封装了调试客户端可以向 JVM发起的请求。例如 BreakpointRequest 向 JVM 发起一个添加断点的请求;ClaPrepareRequest 向 JVM 注册一个类加载请求,JVM 在加载指定 Cla 的时候,就会发出一个 ClaPrepareEvent 事件。

JSR-45规范

JSR-45(Debugging Support for Other Languages)为那些非 JAVA 语言写成,却需要编译成 JAVA 代码,运行在 JVM 中的程序,提供了一个进行调试的标准机制。也许字面的意思有点不好理解,什么算是非 JAVA 语言呢?其实 JSP 就是一个再好不过的例子,JSR-45 的样例就是一个 JSP。

JSP的调试一直依赖于具体应用服务器的实现,没有一个统一的模式,JSR-45 针对这种情况,提供了一个标准的模式。我们知道,JAVA 的调试中,主要根据行号作为标志,进行定位。但是 JSP 被编译为 JAVA 代码之后,JAVA 行号与 JSP 行号无法一一对应,怎样解决呢?

JSR-45 是这样规定的:JSP 被编译成 JAVA 代码时,同时生成一份 JSP 文件名和行号与 JAVA 行号之间的对应表(SMAP)。JVM 在接受到调试客户端请求后,可以根据这个对应表(SMAP),从 JSP 的行号转换到 JAVA 代码的行号;JVM 发出事件通知前, 也根据对应表(SMAP)进行转化,直接将 JSP 的文件名和行号通知调试客户端。

我们用 Tomcat 5.0 做个测试,有两个 JSP,Hello.JSP 和 greeting.JSP,前者 include 后者。Tomcat会将他们编译成 JAVA 代码(Hello_JSP.java),JAVA Cla(Hello_JSP.cla)以及 JSP 文件名/行号和 JAVA 行号之间的对应表(SMAP)。

Hello.JSP: 1 2 3 4 5 6 7 8

greeting.JSP: Hello There!2 Goodbye on

JSP 编译后产生的Hello_JSP.java 如下:

Hello_JSP.java: 1 package org.apache.JSP;2 3 import javax.servlet.*;4 import javax.servlet.http.*;5 import javax.servlet.JSP.*;6 7 public final cla Hello_JSP extends org.apache.jASPer.runtime.HttpJSPBase 8 implements org.apache.jASPer.runtime.JSPSourceDependent { 9 10 private static java.util.Vector _JSPx_dependants;11 12 static { 13 _JSPx_dependants = new java.util.Vector(1);14 _JSPx_dependants.add(“/greeting.JSP”);15 } 16 17 public java.util.List getDependants(){ 18 return _JSPx_dependants;19 } 20 21 public void _JSPService(HttpServletRequest request, HttpServletResponse response)22 throws java.io.IOException, ServletException { 23 24 JSPFactory _JSPxFactory = null;25 PageContext pageContext = null;26 HttpSeion seion = null;27 ServletContext application = null;28 ServletConfig config = null;29 JSPWriter out = null;30 Object page = this;31 JSPWriter _JSPx_out = null;32 33 34 try { 35 _JSPxFactory = JSPFactory.getDefaultFactory();36 response.setContentType(“text/HTML”);37 pageContext = _JSPxFactory.getPageContext(this, request, response, 38 null, true, 8192, true);39 application = pageContext.getServletContext();40 config = pageContext.getServletConfig();41 seion = pageContext.getSeion();42 out = pageContext.getOut();43 _JSPx_out = out;44 45 out.write(“rn”);46 out.write(“rn”);47 out.write(“rn”);49 out.write(“rn”);50 out.write(“rn”);51 out.write(“Hello There!”);52 out.write(“ rnGoodbye on ”);53 out.write(String.valueOf(new java.util.Date()));54 out.write(“ rn”);55 out.write(“ rn”);56 out.write(“rn”);57 out.write(“rn”);58 } catch(Throwable t){ 59 if(!(t instanceof javax.servlet.JSP.SkipPageException)){ 60 out = _JSPx_out;61 if(out!= null && out.getBufferSize()!= 0)62 out.clearBuffer();63 if(pageContext!= null)pageContext.handlePageException(t);64 } 65 } finally { 66 if(_JSPxFactory!= null)_JSPxFactory.releasePageContext(pageContext);67 } 68 } 69 } Tomcat 又将这个 JAVA 代码编译为 Hello_JSP.cla,他们位于: $Tomcat_install_path$workStandalonelocalhost_ 目录下。但是 JSP 文件名/行号和 JAVA 行号的对应表(以下简称SMAP)在哪里呢?答案是,它保存在 Cla 中。如果用 UltraEdit 打开这个 Cla 文件,就可以找到 SourceDebugExtension 属性,这个属性用来保存 SMAP。

JVM 规范定义了 ClaFile 中可以包含 SourceDebugExtension 属性,保存 SMAP:

SourceDebugExtension_attribute { u2 attribute_name_index;u4 attribute_length;u1 debug_extension[attribute_length];}

我用 javaist 做了一个测试(javaist可是一个好东东,它可以动态改变Cla的结构,JBOSS 的 AOP就利用了javaist,这里我们只使用它读取ClaFile的属性)

public static void main(String[] args)throws Exception{ String[]files = {

“E:Tomcat5_0_5workCatalinalocalhost_orgapacheJSPHello_JSP.cla”, };for(int k = 0;k

这段代码显示了SourceDebugExtension 属性,你可以看到SMAP 的内容。编译JSP后,SMAP 就被写入 Cla 中, 你也可以利用 javaist 修改 ClaFile 的属性。

下面就是 Hello_JSP.cla 中保存的 SMAP 内容:

SMAP E:Tomcat5_0_5workCatalinalocalhost_orgapacheJSPHello_JSP.java JSP *S JSP *F + 0 Hello.JSP /Hello.JSP + 1 greeting.JSP /greeting.JSP *L 1:45 2:46 3:47 3:48 4:49 5:50 1#1:51 1:52 2:53 7#0:56 8:57 *E

首先注明JAVA代码的名称:Hello_JSP.java,然后是 stratum 名称: JSP。随后是两个JSP文件的名称 :Hello.JSP、greeting.JSP。两个JSP文件共10行,产生的Hello_JSP共69行代码。最后也是最重要的内容就是源文件文件名/行号和目标文件行号的对应关系(*L 与 *E之间的部分)

在规范定义了这样的格式:

源文件行号 # 源文件代号,重复次数 : 目标文件开始行号,目标文件行号每次增加的数量

(InputStartLine # LineFileID , RepeatCount : OutputStartLine , OutputLineIncrement)

源文件行号(InputStartLine)目标文件开始行号(OutputStartLine)是必须的。下面是对这个SMAP具体的说明:

1:45 2:46 3:47 3:48 4:49 5:50(没有源文件代号,默认为Hello.JSP)

开始行号 结束行号 Hello.JSP: 1->Hello_JSP.java: 45 2->46 3->47 48 4->49 5->50 1#1:51 1:52 2:53(1#1表示 greeting.JSP 的第1行)greeting.JSP: 1->Hello_JSP.java: 51 52 2->53 7#0:56 8:57(7#0表示 Hello.JSP 的第7行)Hello.JSP: 7->Hello_JSP.java: 56 8->57 调试JSP

现在我们可以调试 JSP 了。

(1)运行 JSP_DEBUG plugin

首先在 run->run 中添加一个 Run-time Workbench,点击 run 按钮,Eclipse 的Plugin开发环境会启动一个新的Eclipse,这个新启动的 Eclipse 中,我们创建的 JSP_DEBUG plugin 就可以使用了。新建 一个 JAVA 项目 Test(注意,一定要是JAVA项目),新建一个 Hello.JSP 和 greeting.JSP,打开Hello.JSP,在编辑器左侧标尺双击,就出现了一个断点。

(2)以 Debug 模式启动Tomcat:

windows 开始->运行,键入 cmd,启动一个命令行窗口:

cd E:Tomcat5_0_5bin

(我的 Tomcat 安装在 E:Tomcat5_0_5 目录,JDK 安装在 D:j2sdk1.4.2)D:j2sdk1.4.2binjava-Xdebug-Xnoagent-Xrunjdwp:transport=dt_socket,addre=8888,server=y, suspend=n-Djava.endorsed.dirs=“..commonendorsed”-clapath “D:j2sdk1.4.2libtools.jar;..binbootstrap.jar”-Dcatalina.base=“..”-Dcatalina.home=“..”-Djava.io.tmpdir=“..temp” org.apache.catalina.startup.Bootstrap start

-Xdebug-Xnoagent-Xrunjdwp:transport=dt_socket,addre=8888,server=y,suspend=n 表示以调试方式启动,端口号是 8888 clapath中要加入 D:j2sdk1.4.2libtools.jar,因为我是 Tomcat5.0.5,如果是5.5就不需要了。

(3)测试Hello.JSP

将 Hello.JSP 和 greeting.JSP 拷贝到 E:Tomcat5_0_5webappsROOT 目录,从浏览器访问 Hello.JSP http://localhost:8000/Hello.JSP。成功的话就可以继续下面的工作了,如果失败,检查你的Tomcat设置。

(4)启动远程调试

在 Eclipse 中启动远程调试,将 Eclipse 作为一个 Debug 客户端,连接到 Tomcat。在 Java 透视图中,点击 Run->Debug,添加一个 Remote Java Application,名称是 Start Tomcat Server(不能错,因为我们要根据这个名称,判断当前的 Web Server 类型)

project是创建的 Test 项目

Port 为 8888,和启动 Tomcat 时设置的一样

点击 Debug 按钮,就可以连接到 Tomcat 上了。切换到 Debug 透视图,在Debug 视图中,能够看到所有 Tomcat 中线程的列表。

(5)调试Hello.JSP

为 Hello.JSP 添加断点,然后从浏览器访问Hello.JSP,就可以在断点处挂起了。你可以使用单步执行,也可以在Variables视图查看JSP中的变量信息。

由于 Eclipse 自身的实现,现在的 JSP Editor 有一个问题,单步执行到 include JSP 行后,会从Hello.JSP的1行再次执行。这是因为 Eclipse JDT Debug视图缓存了 StackFrame 中已经打开的Editor,StackFrame不改变时,不会再重新计算当前调试的是否是其他Resource。本来应该打开 greeting.JSP的,现在却从 Hello.JSP 的第 1 行开始执行了。

结束语

很多集成开发环境都支持 JSP 的调试,在 Eclipse 中也有 MyEclipse 这样的插件完成类似的功能。但是在 JSR-45 规范产生前,每种应用服务器对 JSP Debug 的实现是不一样的,例如 WebSphere 5 就是在 JSP 编译产生的 JAVA 代码中加入了两个数组,表示源文件和行号的对应信息。Tomcat 率先实现了 JSR-45 规范,WebSphere 6.0 现在也采取这种模式,有兴趣的话,可以查看 WebSphere 6.0 编译的 Cla,和 Tomcat 不一样,SMAP 文件会和java代码同时产生。

但是启动server前,需要设置 JVM 参数 was.debug.mode = true

同时在 ibm-web-ext.xmi 中设置

利用本文的基本原理,我们也可以开发其他基于 JAVA 脚本语言的编辑器(例如 Groovy),为这个编译器加入 Debug 的功能。

《JSP中插件设计.docx》
将本文的Word文档下载,方便收藏和打印
推荐度:
JSP中插件设计
点击下载文档
相关专题 jsp中插件设计 设计 插件 jsp jsp中插件设计 设计 插件 jsp
[其他范文]相关推荐
    [其他范文]热门文章
      下载全文