- 浏览: 376864 次
- 性别:
- 来自: 深圳
文章分类
最新评论
-
zxjlwt:
学习论。确实很全啊。欢迎交流http://surenpi.co ...
eclipse dialog 对话框 大全 -
zxjlwt:
很好。http://surenpi.com
eclipse 源码泛读 -
string2020:
有卵用???
activiti 第一个例子 helloworld -
ysj_csdn:
能给个正确的例子?
activiti 第一个例子 helloworld -
zxjlwt:
学习了。http://surenpi.com
Eclipse扩展点介绍
AVA调试框架(JPDA)简介 调试客户端和JVM 既可以在同一台机器上,也可以远程调试。JDK 会包含一个默认的实现 jdwp.dll,JVM 允许灵活的使用其他协议代替 JDWP。SUN JDK 有两种方式传输通讯协议:Socket 和共享内存(后者仅仅针对 Windows),一般我们都采用 Socket 方式。 你可以用下面的参数,以调试模式启动JVM 如果是一个 JAVA 的调试客户端,只要实现 JDI 接口,利用JDWP协议,与虚拟机通讯,就可以调用JVMDI了。 下图为 JPDA 的基本架构: 参见:http://java.sun.com/j2se/1.4.2/docs/guide/jpda/architecture.html Eclipse作为一个基于 JAVA 的调试客户端,利用 org.eclipse.jdt.debug Plugin 提供了JDI 的具体实现。JDI 接口主要包含下面 4 个包 本文不对 JDI 进行深入阐述,这里重点介绍 JDI 中与断点相关的接口 JSR-45规范 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 Class(Hello_jsp.class) 以及 JSP 文件名/行号和 JAVA 行号之间的对应表(SMAP)。 Hello.jsp: greeting.jsp: 1 Hello There!<P> 2 Goodbye on <%= new java.util.Date() %> JSP 编译后产生的Hello_jsp.java 如下: Tomcat 又将这个 JAVA 代码编译为 Hello_jsp.class,他们位于: $Tomcat_install_path$\work\Standalone\localhost\_ 目录下。但是 JSP 文件名/行号和 JAVA 行号的对应表(以下简称SMAP) 在哪里呢?答案是,它保存在 Class 中。如果用 UltraEdit 打开这个 Class 文件,就可以找到 SourceDebugExtension 属性,这个属性用来保存 SMAP。 JVM 规范定义了 ClassFile 中可以包含 SourceDebugExtension 属性,保存 SMAP: 我用 javassist 做了一个测试(javassist可是一个好东东,它可以动态改变Class的结构,JBOSS 的 AOP就利用了javassist,这里我们只使用它读取ClassFile的属性) 这段代码显示了SourceDebugExtension 属性,你可以看到SMAP 的内容。编译JSP后,SMAP 就被写入 Class 中, 你也可以利用 javassist 修改 ClassFile 的属性。 下面就是 Hello_jsp.class 中保存的 SMAP 内容: 首先注明JAVA代码的名称:Hello_jsp.java,然后是 stratum 名称: JSP。随后是两个JSP文件的名称 :Hello.jsp、greeting.jsp。两个JSP文件共10行,产生的Hello_jsp共69行代码。最后也是最重要的内容就是源文件文件名/行号和目标文件行号的对应关系(*L 与 *E之间的部分) 在规范定义了这样的格式: 源文件行号 # 源文件代号,重复次数 : 目标文件开始行号,目标文件行号每次增加的数量 源文件行号(InputStartLine) 目标文件开始行号(OutputStartLine) 是必须的。下面是对这个SMAP具体的说明: 开发一个JSP编辑器 (1)点击 File 菜单,New -> Project -> Plug-in Project ; (2)输入项目名称 JSP_DEBUG,下一步; (3)输入 plugin ID : com.jsp.debug (4)选择用模板创建 使用 Plug-in with editor,输入 一个 jsp editor 就产生了。 运行这个Plugin,新建一个JAVA项目,新建一个 Hello.jsp 和 greeting.jsp,在 Navigator 视图双击 jsp,这个editor就打开了。 在JSP编辑器中设置断点 在 Eclipse 的实现中,添加断点实际上就是为 IFile 添加一个marker ,类型是IBreakpoint.BREAKPOINT_MARKER,然后将断点注册到 BreakpointManager。 BreakpointManager 将产生一个 BreakpointRequest,通知正在运行的JVM Target,如果此时还没有启动 JVM,会在 JVM 启动的时候,将所有断点一起通知 JVM Target。 添加断点使用一个 AbstractRulerActionDelegate,重载 createAction 方法,返回一个 IAction ManageBreakpointRulerAction动作: 为了将 ManageBreakpointRulerActionDelegate 添加到文本编辑器左侧标尺的鼠标右键菜单,并且能够处理左侧标尺的鼠标双击事件,在 plugin.xml 中加入定义。 处理双击事件: 添加右键菜单: ManageBreakpointRulerAction 是实际添加断点的Action,实现了 IUpdate 接口,这个Action的工作,就是判断当前选中行是否存在断点类型的 Marker,如果不存在创建一个,如果存在,将它删除。 update 方法会在点击时首先调用,这时就可以收集当前选中行是否有marker了(调用fetchBPMarkerList方法),如果有,就保存在 变量allMarkers 中。由于ManageBreakpointRulerAction每一次都产生一个新的实例,因此不会产生冲突。 下面是update的调用栈,可以看出,update方法是在鼠标点击事件中被调用的: updae被调用后,会执行 run 方法,就可以根据 allMarkers.isEmpty() 确定要删除还是添加 marker 了。 添加断点的时候,首先利用 IVerticalRulerInfo,获取鼠标点击的行号,根据行号,从 Document 模型中取得该行的描述IRegion,得到开始字符位置和结束字符位置,创建一个 JSP 断点。 注册 JSP 断点为支持 JSR-45 规范,Eclipse 中提供了 JavaStratumLineBreakpoint。不过它目前是一个 internal 的实现,在以后的版本中不能保证不作修改。这里为了简单起见,直接从 JavaStratumLineBreakpoint 继承。 查看 JavaStratumLineBreakpoint 的源代码可以知道,创建 JavaStratumLineBreakpoint 的时候做了两件事情: (1) 创建断点类型的 marker, 并且设置了marker的属性 (2) 将断点注册到断点管理器 下面是 JavaStratumLineBreakpoint 构造函数中的代码: 移除断点的时候,根据 marker 找到相应的 IBreakpoint,从 BreakpointManager 中移除 BreakpointManager 会自动删除 marker,通知 JVM Target。 JSPBreakpoint 重载了父类的addToTarget(JDIDebugTarget target) 方法。重载这个方法的目的是根据不同的应用服务器,设置不同的 referenceTypeName和sourcePath。我们知道,每种应用服务器编译 JSP 产生Java Class 名称的规则都不相同,例如Tomcat编译Hello.jsp 产生的Java 类名为 org.apache.jsp. Hello_jsp,而WebSphere6.0 却是 com.ibm._jsp._Hello。只有确定服务器类型,才能知道referenceTypeName 和souecePath应该是什么。目前通过启动 JVM 时target 名称来判断应用服务器类型: String targetString = target.getLaunch().getLaunchConfiguration().getName(); 如果targetString 包含 Tomcat ,就认为是 Tomcat。 产生 referenceTypeName 后首先创建一个 ClassPrepareRequest 通知,然后从vm中取出所有的classes,如果是当前的 Class,再创建一个添加断点通知。之所以这样做,是因为有可能这个 Class 还没有被 JVM 加载,直接通知 JVM 没有任何意义。在 Class 被加载的时候,JVM 会通知 Eclipse,这个时候,才产生添加断点通知。需要指出的是,本文示例代码获取 referenceTypeName 的方法不是很完善: (1) 仅仅实现了Tomcat 读者有兴趣可以实现更多的Web容器,例如 JBoss3 以上,WebSphere6.0 (2) 一些特殊情况没有处理例如 路径名为package的jsp,路径名或文件名带有数字的jsp 调试JSP (1)运行 JSP_DEBUG plugin (2)以 Debug 模式启动Tomcat: (我的 Tomcat 安装在 E:\Tomcat5_0_5 目录,JDK 安装在 D:\j2sdk1.4.2) -Xdebug -Xnoagent -Xrunjdwp:transport=dt_socket,address=8888,server=y,suspend=n 表示以调试方式启动,端口号是 8888 classpath中要加入 D:\j2sdk1.4.2\lib\tools.jar,因为我是 Tomcat5.0.5,如果是5.5就不需要了。 (3) 测试Hello.jsp (4)启动远程调试 点击 Debug 按钮,就可以连接到 Tomcat 上了。切换到 Debug 透视图,在Debug 视图中,能够看到所有 Tomcat 中线程的列表。 (5)调试Hello.jsp 结束语 但是启动server前,需要设置 JVM 参数 was.debug.mode = true 同时在 ibm-web-ext.xmi 中设置 利用本文的基本原理,我们也可以开发其他基于 JAVA 脚本语言的编辑器(例如 Groovy),为这个编译器加入 Debug 的功能。
JPDA是一个多层的调试框架,包括 JVMDI、JDWP、JDI 三个层次。JAVA 虚拟机提供了JPDA的实现。其开发工具作为调试客户端,可以方便的与虚拟机通讯,进行调试。Eclipse正是利用 JPDA调试JAVA应用,事实上,所有JAVA开发工具都是这样做的。SUN JDK 还带了一个比较简单的调试工具以及示例。
-Xdebug -Xnoagent -Xrunjdwp:transport=dt_socket,address=8000,server=y,suspend=n
-Xrunjdwp JVM 加载 jdwp.dll
transport=dt_socket 使用 Socket 传输
address 表示调试端口号
server=y 表示 JVM 作为服务器,建立 Socket
suspend=n 表示启动过程中,JVM 不会挂起去等待调试客户端连接
ComponentsDebugger Interface
/|-----------------------|
/ | VM |
debuggee ----( |-----------------------| <------- JVMDI - Java VM Debug Interface
\ | back-end |
\|-----------------------|
/ |
comm channel -( | <--------------- JDWP - Java Debug Wire Protocol
\ |
|---------------------|
| front-end |
|---------------------| <------- JDI - Java Debug Interface
| UI |
|---------------------|
com.sun.jdi
com.sun.jdi.connect
com.sun.jdi.event
com.sun.jdi.request
主要是JVM(VirtualMachine) 线程(ThreadReference) 调用栈(StackFrame) 以及类型、实例的描述。利用这组接口,调试客户端可以用类似类反射的方式,得到所有类型的定义,动态调用 Class 的方法。
封装了JVM 产生的事件, JVM 正是将这些事件通知给调试客户端的。例如 BreakpointEvent 就是 JVM 执行到断点的时候,发出的事件;ClassPrepareEvent就是 Class 被加载时发出的事件。
封装了调试客户端可以向 JVM发起的请求。例如 BreakpointRequest 向 JVM 发起一个添加断点的请求;ClassPrepareRequest 向 JVM 注册一个类加载请求,JVM 在加载指定 Class 的时候,就会发出一个 ClassPrepareEvent 事件。
JSR-45(Debugging Support for Other Languages)为那些非 JAVA 语言写成,却需要编译成 JAVA 代码,运行在 JVM 中的程序,提供了一个进行调试的标准机制。也许字面的意思有点不好理解,什么算是非 JAVA 语言呢?其实 JSP 就是一个再好不过的例子,JSR-45 的样例就是一个 JSP。
1<HTML>
2<HEAD>
3<TITLE>Hello Example</TITLE>
4</HEAD>
5<BODY>
6<%@ include file="greeting.jsp" %>
7</BODY>
8</HTML>
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 class Hello_jsp extends org.apache.jasper.runtime.HttpJspBase
8 implements org.apache.jasper.runtime.JspSourceDependent {
9
10private static java.util.Vector _jspx_dependants;
11
12static {
13 _jspx_dependants = new java.util.Vector(1);
14 _jspx_dependants.add("/greeting.jsp");
15}
16
17public 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 HttpSession session = 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();
36response.setContentType("text/html");
37pageContext = _jspxFactory.getPageContext(this, request, response,
38 null, true, 8192, true);
39application = pageContext.getServletContext();
40config = pageContext.getServletConfig();
41session = pageContext.getSession();
42out = pageContext.getOut();
43_jspx_out = out;
44
45out.write("<HTML>\r\n");
46out.write("<HEAD>\r\n");
47out.write("<TITLE>Hello Example");
48out.write("</TITLE>\r\n");
49out.write("</HEAD>\r\n");
50out.write("<BODY>\r\n");
51out.write("Hello There!");
52out.write("<P>\r\nGoodbye on ");
53out.write(String.valueOf( new java.util.Date() ));
54out.write(" \r\n");
55out.write("\r\n");
56out.write("</BODY>\r\n");
57out.write("</HTML> \r\n");
58 } catch (Throwable t) {
59if (!(t instanceof javax.servlet.jsp.SkipPageException)){
60 out = _jspx_out;
61 if (out != null && out.getBufferSize() != 0)
62out.clearBuffer();
63 if (pageContext != null) pageContext.handlePageException(t);
64}
65 } finally {
66 if (_jspxFactory != null) _jspxFactory.releasePageContext ( pageContext);
67 }
68}
69 }
SourceDebugExtension_attribute {
u2 attribute_name_index;
u4 attribute_length;
u1 debug_extension[attribute_length];
}
public static void main(String[] args) throws Exception{
String[]files = {
"E:\\Tomcat5_0_5\\work\\Catalina\\localhost\\_\\org\\apache\\jsp\\Hello_jsp.class",
};
for(int k = 0; k < files.length; k++){
String file = files[k];
System.out.println("Class : " + file);
ClassFile classFile = new ClassFile(new DataInputStream(new FileInputStream(file)));
AttributeInfo attributeInfo = classFile.getAttribute("SourceDebugExtension");
System.out.println("attribute name :" + attributeInfo.getName() + "]\n\n");
byte[]bytes = attributeInfo.get();
String str = new String(bytes);
System.out.println(str);
}
}
SMAP
E:\Tomcat5_0_5\work\Catalina\localhost\_\org\apache\jsp\Hello_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
(InputStartLine # LineFileID , RepeatCount : OutputStartLine , OutputLineIncrement)
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
Eclipse 提供了 TextEditor,作为文本编辑器的父类。由于 Editor 的开发不是本文的重点,不做具体论述。我们可以利用 Eclipse 的 Plugin 项目向导,生成一个简单的 JSP 编辑器:
Plugin Class name : com.jsp.debug.JSP_DebugPlugin
Java Package Name :com.jsp.editors
Editor Class Name :JSPEditor
File extension :jsp
在编辑器中添加断点的操作方式有两种,一种是在编辑器左侧垂直标尺上双击,另一种是在左侧垂直标尺上点击鼠标右键,选择菜单"添加/删除断点"。
public class ManageBreakpointRulerActionDelegate extends AbstractRulerActionDelegate{
protected IAction createAction(ITextEditor editor, IVerticalRulerInfo rulerInfo) {
return new ManageBreakpointRulerAction(rulerInfo, editor);
}
}
<extension point="org.eclipse.ui.editorActions">
<editorContribution
targetID="com.jiaoly.editors.JSPEditor"
id="com.jiaoly.debug.ManageBreakpointRulerActionDelegate">
<action
label="添加/删除断点"
class="com.jiaoly.debug.ManageBreakpointRulerActionDelegate"
actionID="RulerDoubleClick"
id="com.jiaoly.debug.ManageBreakpointRulerActionDelegate">
</action>
</editorContribution>
</extension>
<extension point="org.eclipse.ui.popupMenus">
<viewerContribution
targetID="#TextRulerContext"
id="com.jiaoly.debug.ManageBreakpointRulerActionDelegate">
<action
label="添加/删除断点"
class="com.jiaoly.debug.ManageBreakpointRulerActionDelegate"
menubarPath="addition"
id="com.jiaoly.debug.ManageBreakpointRulerActionDelegate">
</action>
</viewerContribution>
</extension>
public class ManageBreakpointRulerAction extends Action implements IUpdate{
private IVerticalRulerInfo rulerInfo;
private ITextEditor textEditor;
private String BPmarkerType ; //当点Marker的类型
private List allMarkers; //当前鼠标点击行所有的Marker
private String addBP; //Action 的显示名称
public ManageBreakpointRulerAction(IVerticalRulerInfo ruler, ITextEditor editor){
this.rulerInfo = ruler;
this.textEditor = editor;
BPmarkerType = IBreakpoint.BREAKPOINT_MARKER;
addBP = "添加/删除断点"; //$NON-NLS-1$
setText(this.addBP);
}
public void update() {
this.allMarkers = this.fetchBPMarkerList();
}
public void run(){
if(this.allMarkers.isEmpty())
this.addMarker();
else
this.removeMarkers(this.allMarkers);
}
}
ManageBreakpointRulerAction.update() line: 55
ManageBreakpointRulerActionDelegate(AbstractRulerActionDelegate).update() line: 114
ManageBreakpointRulerActionDelegate(AbstractRulerActionDelegate).mouseDown(MouseEvent) line: 139
protected void addMarker() {
IEditorInput editorInput= this.getTextEditor().getEditorInput();
IDocument document= this.getDocument();
//the line number of the last mouse button activity
int rulerLine= this.getRulerInfo().getLineOfLastMouseButtonActivity();
try{
int lineNum = rulerLine + 1;
if(lineNum > 0){
//Returns a description of the specified line
IRegion iregion = document.getLineInformation(lineNum - 1);
int charStart = iregion.getOffset();
int charEnd = (charStart + iregion.getLength()) - 1;
JSPDebugUtility.createJspLineBreakpoint(this.getResource(),
lineNum, charStart, charEnd);
}
}catch(CoreException coreexception){
coreexception.printStackTrace();
}
catch(BadLocationException badlocationexception){
badlocationexception.printStackTrace();
}
}
public class JSPBreakpoint extends JavaStratumLineBreakpoint {
public JSPBreakpoint(IResource resource, String stratum, String sourceName,
String sourcePath, String classNamePattern, int lineNumber,
int charStart, int charEnd, int hitCount, boolean register,
Map attributes) throws DebugException {
super(resource, stratum, sourceName, sourcePath, classNamePattern,
lineNumber, charStart, charEnd, hitCount, register, attributes);
}
}
resource.createMarker(markerType);
DebugPlugin.getDefault().getBreakpointManager().addBreakpoint(this); 断点管理器负责产生一个 BreakpointRequest,通知正在运行的JVM Target 如果此时还没有启动 JVM,会在 JVM 启动的时候,将所有断点一起通知 JVM Target。
IWorkspaceRunnable wr= new IWorkspaceRunnable() {
public void run(IProgressMonitor monitor) throws CoreException {
// create the marker
setMarker(resource.createMarker(markerType));
// modify pattern
String pattern = classNamePattern;
if (pattern != null && pattern.length() == 0) {
pattern = null;
}
// add attributes
addLineBreakpointAttributes(attributes, getModelIdentifier(), true,
lineNumber, charStart, charEnd);
addStratumPatternAndHitCount(attributes, stratum, sourceName,
sourcePath, pattern, hitCount);
// set attributes
ensureMarker().setAttributes(attributes);
register(register);
}
};
run(null, wr);
protected void register(boolean register) throws CoreException {
if (register) {
DebugPlugin.getDefault().getBreakpointManager().addBreakpoint(this);
} else {
setRegistered(false);
}
}
breakpointManager = DebugPlugin.getDefault().getBreakpointManager();
IBreakpoint breakpoint = breakpointManager.getBreakpoint(IMarker);
breakpointManager.removeBreakpoint(breakpoint, true);
public void addToTarget(JDIDebugTarget target) throws CoreException {
IMarker marker = this.getMarker();
IResource resource = marker.getResource();
String targetString = target.getLaunch().getLaunchConfiguration().getName();
IJSPNameUtil util = JSPDebugUtility.getJSPNameUtil(targetString);
// pre-notification
fireAdding(target);
String referenceTypeName;
try {
referenceTypeName = getPattern();
//如果没有设置 Pattern, 根据 Server 的类型, 产生新的 Pattern
if(referenceTypeName == null ||
"".equals(referenceTypeName.trim()) ||
"*".equals(referenceTypeName.trim())){
referenceTypeName = util.referenceTypeName(resource);
}
} catch (CoreException e) {
JDIDebugPlugin.log(e);
return;
}
this.ensureMarker().setAttribute(TYPE_NAME, referenceTypeName);
String sourcePath = util.sourcePath(resource);
this.ensureMarker().setAttribute(JSPBreakpoint.SOURCE_PATH, sourcePath);
String classPrepareTypeName= referenceTypeName;
//如果这时 class 还没有被加载, 注册一个 ClassPrepareRequest 请求
//
//当 class 加载的时候, 首先会触发 JavaBreakpoint 的 handleClassPrepareEvent 方法
//调用 createRequest(target, event.referenceType()) --> newRequest() -->
//createLineBreakpointRequest() 创建 enable或disable 断点的请求
//
// 设置 enable/disable 动作在 configureRequest() --> updateEnabledState(request) 方法中
// 根据 getMarker().getAttribute(ENABLED, false) 确定断点是否有效
registerRequest(target.createClassPrepareRequest(classPrepareTypeName), target);
// create breakpoint requests for each class currently loaded
VirtualMachine vm = target.getVM();
if (vm == null) {
target.requestFailed("Unable_to_add_breakpoint_-_VM_disconnected._1"),
null); }
List classes = null;
try {
classes= vm.allClasses();
} catch (RuntimeException e) {
target.targetRequestFailed("JavaPatternBreakpoint.0"), e);
}
if (classes != null) {
Iterator iter = classes.iterator();
while (iter.hasNext()) {
ReferenceType type= (ReferenceType)iter.next();
if (installableReferenceType(type, target)) {
createRequest(target, type);
}
}
}
}
现在我们可以调试 JSP 了。
首先在 run -> run 中添加一个 Run-time Workbench,点击 run 按钮,Eclipse 的Plugin开发环境会启动一个新的Eclipse,这个新启动的 Eclipse 中,我们创建的 JSP_DEBUG plugin 就可以使用了。新建 一个 JAVA 项目 Test (注意,一定要是JAVA项目),新建一个 Hello.jsp 和 greeting.jsp,打开Hello.jsp,在编辑器左侧标尺双击,就出现了一个断点。
windows 开始 -> 运行,键入 cmd,启动一个命令行窗口:
cd E:\Tomcat5_0_5\bin
D:\j2sdk1.4.2\bin\java
-Xdebug -Xnoagent -Xrunjdwp:transport=dt_socket,address=8888,server=y,suspend=n -Djava.endorsed.dirs="..\common\endorsed"
-classpath "D:\j2sdk1.4.2\lib\tools.jar;..\bin\bootstrap.jar"
-Dcatalina.base=".."
-Dcatalina.home=".."
-Djava.io.tmpdir="..\temp"
org.apache.catalina.startup.Bootstrap start
将 Hello.jsp 和 greeting.jsp 拷贝到 E:\Tomcat5_0_5\webapps\ROOT 目录,从浏览器访问 Hello.jsp http://localhost:8000/Hello.jsp。成功的话就可以继续下面的工作了,如果失败,检查你的Tomcat设置。
在 Eclipse 中启动远程调试,将 Eclipse 作为一个 Debug 客户端,连接到 Tomcat 。在 Java 透视图中,点击 Run -> Debug ,添加一个 Remote Java Application,名称是 Start Tomcat Server(不能错,因为我们要根据这个名称,判断当前的 Web Server 类型)
project是创建的 Test 项目
Port 为 8888,和启动 Tomcat 时设置的一样
为 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 编译的 Class,和 Tomcat 不一样,SMAP 文件会和java代码同时产生。
<jspAttributes xmi:id="JSPAttribute_0" name="keepgenerated" value="true"/>
<jspAttributes xmi:id="JSPAttribute_1" name="createDebugClassfiles" value="true"/>
<jspAttributes xmi:id="JSPAttribute_2" name="debugEnabled" value="true"/>
发表评论
-
离线使用tycho对eclipse RCP打包导出
2015-09-02 09:22 1225http://www.bubuko.com/infodetai ... -
RAP源码泛读及分析
2014-01-17 13:27 1136SWT、RWT如何保证大部 ... -
rap 的学习1
2013-10-27 22:02 774RAP 2.2 December 2013 (planne ... -
tycho 打包不同平台的RCP
2013-06-18 10:56 1140<configuration> < ... -
rap web开发
2013-04-10 17:12 885rap项目已经2.0(changelog) 这次改动 ... -
subversion升级到1.7
2012-09-07 15:37 1909http://www.cnblogs.com/xiziy ... -
ubuntu eclipse 中使用jadclipse java反编译
2012-09-07 11:04 11841:net.sf.jadclipse_3.3.0.jar 发 ... -
Nebula Project
2012-08-10 02:42 872http://www.eclipse.org/nebula/ -
Eclipse Plug-in dependencies – Required Bundle vrs. Import-Package
2012-07-19 00:32 3014http://www.vogella.com/blog/200 ... -
rcp培训
2012-07-19 00:22 1231<!-- @pa ... -
No schema found for … extension point 问题
2012-03-13 13:09 1574很多时候在编辑plugin.xml 文件的Extensi ... -
Eclipse中的org.eclipse.core.resources.markers扩展点
2011-11-09 11:26 1928扩展点配置如下:<extension ... -
gmf 优点
2011-09-28 15:09 963http://www.ibm.com/developerwor ... -
gef 与gmf的结合
2011-09-28 14:03 1014以前的项目已经就是直接用gef,自己写模型的。 今天研 ... -
rcp自动加载插件
2011-09-28 13:56 1193http://blog.ixpub.net/html/9 ... -
rcp DialogSettings IPreferenceStore IMemento
2011-09-22 14:31 1128三个不的不同点: IMemento 要求rc ... -
rcp IPreferenceStore
2011-09-22 14:21 1257IPreferenceStore store=Acti ... -
rcp DialogSettings
2011-09-22 14:10 1163Activator.getDefault().getDialo ... -
rcp IMemento 状态的保存
2011-09-22 13:50 1122rcp 可以对每个part进行状态的保存。 保存数据 ... -
gef ActionBarContributor
2011-09-22 01:10 1612public class GefActionBarCon ...
相关推荐
### 开发一个调试JSP的Eclipse插件 #### 知识点一:Eclipse中设置JSP断点的方法及远程调试JSP 在本文中,我们首先关注的是如何在Eclipse环境中设置JSP文件的断点,并进一步探索如何进行远程调试。JSP文件是一种...
本篇将详细介绍关于"html_jsp_xml编辑的eclipse插件"的相关知识点。 首先,我们来看如何安装描述中提到的GEF(Graphical Editing Framework)插件。GEF是Eclipse提供的一个用于创建图形化编辑器的框架,虽然主要...
总结:Eclipse的这款JSP插件以其独特的“随意拖动”功能,为JSP开发者提供了一个更为人性化和高效的开发环境。无论是初学者还是经验丰富的专业开发者,都能从中受益,让JSP页面的设计和编码变得更加简单和愉快。如果...
- **安装方法**: 参照《使用links方式安装Eclipse插件》教程 #### 三、环境配置 **1. 检查环境变量** - 右键点击“我的电脑” -> 高级 -> 环境变量 - **JAVA_HOME**: 指向JDK安装目录 - **TOMCAT_HOME**: 指向...
5. **Sysdeo Eclipse Tomcat Launcher plugin**:这是一个Eclipse插件,允许用户直接在Eclipse内启动和管理Tomcat服务器,简化了开发过程中的部署步骤。 6. **Eclipse版本与JDT**:Eclipse 3.1版本是针对该教程的...
例如,"Web Tools Platform"(WTP)是Eclipse的一个扩展,它包含了一些用于Web开发的工具,其中包括了预览功能,可以配置不同的浏览器作为预览目标,包括Internet Explorer。 至于"IE插件",这通常指的是安装在...
- **MyEclipse**:是一个商业的Eclipse插件集合,尤其适合Java EE开发,提供了一个集成的开发环境,包括数据库管理、服务器配置等功能。官方下载地址需访问MyEclipse官方网站。 4. **版本控制系统插件**: - **...
**JSR-45**(Debugging Support for Other Languages)为非 Java 语言(如 JSP)编写的程序提供了一个调试标准机制。这种机制使得非 Java 语言编写的应用能够编译成 Java 字节码,并在 JVM 上运行时进行调试。 **...
总的来说,Eclipse 插件 TomcatPlugin 是一个非常实用的开发工具,它使得在 Eclipse 中管理和调试 Tomcat 服务器变得更加便捷,提高了开发效率,降低了出错的可能性。如果你是一个经常使用 Eclipse 和 Tomcat 的 ...
【标题】"TomcatPlugin eclipse插件"是一个专门为Eclipse集成开发环境设计的插件,它的主要功能是方便开发者在Eclipse中管理和调试Tomcat服务器。这个插件极大地提升了Java Web应用开发的效率,因为它允许用户直接在...
Eclipse J2EE 是 Eclipse 的一个插件,用于支持 Java EE 开发。用户可以从 Eclipse 官方网站下载最新版本的 Eclipse J2EE。 三、下载和安装 Tomcat Tomcat 是一个流行的 Java 服务器,可以用于部署 Java Web 应用...
Eclipse作为一个开源的集成开发环境(IDE),其强大的可扩展性在于丰富的插件生态。以下是一些精选的Eclipse插件,它们能极大地提升开发者的生产力和开发体验。 1. PyDev:这款插件专为Python开发者设计,提供了...
【标题】"一个eclipse做的jsp" 暗示了这个项目是使用Eclipse IDE进行开发的JavaServer Pages(JSP)应用。Eclipse是一款广泛使用的开源集成开发环境,尤其在Java开发领域非常流行。JSP是Web开发中的一个重要组成部分...
开发人员需要一个强大的编辑工具来处理这两种语言,以提高代码质量和开发速度。"jsp/html editor插件"就是这样的工具,它提供了丰富的特性来提升开发体验。 **2. 插件支持的Eclipse版本** 此插件兼容Eclipse 3.x和...
RCP不仅仅是一个开发工具,更是一种设计理念,强调模块化和可扩展性,使得应用能够随着需求的变化而灵活调整。 #### 三、Java开发工具(JDT) Java Development Tools(JDT)是Eclipse平台提供的标准插件之一,...
接下来,我们要下载并安装Lomboz插件,这是一个用于Eclipse的Java EE开发工具包。Lomboz插件可以从ObjectWeb Forge站点获取,如Lomboz-wtp-emf-gef-jem-3.1.2.zip。注意,插件版本需与Eclipse版本匹配。 安装插件有...
Resin Eclipse插件是专为开发人员设计的一款集成开发环境(IDE)扩展,它使得在Eclipse中管理和调试Resin应用服务器变得更加便捷。Resin是一款高性能的Java应用服务器,广泛用于构建Web应用程序,特别是那些基于Java...
Geronimo的Eclipse插件就是在这样一个环境中运行,扩展了Eclipse对Geronimo服务器的支持。 **插件安装与使用** 要在Eclipse中安装Geronimo插件,通常需要通过Eclipse的“软件更新”功能来获取和安装。首先,需要...
- **PDE(Plugin Development Environment)**:用于创建、调试和管理Eclipse插件的工具集,对于扩展Eclipse平台非常关键。 - **Web和企业开发插件**:如Web Tools Project (WTP) 支持Java EE应用的开发,包括...