??xml version="1.0" encoding="utf-8" standalone="yes"?>
探究其基于指针的 APIQ它?XML 作ؓ标记Q或事gQ流拉出
U别Q?中
Peter Nehrer (pnehrer@ecliptical.ca), 自由撰稿? 独立咨询N
2007 q?3 ?02 ?/p>
Streaming API for XML (StAX) 是用 Java?语言处理 XML 的最新标准。作ZU面向流的方法,无论从性能q是可用性上都优于其他方法,?DOM ?SAX。本pd分ؓ 3 部分Q本文是W?1 部分Q简要介l了 StAX 及其处理 XML 的基于指针的 API?/blockquote>从一开始,Java API for XML Processing (JAXP) 提供了两种Ҏ(gu)来处?XMLQ文对象模型(DOMQ方法是用标准的对象模型表示 XML 文QSimple API for XML (SAX) Ҏ(gu)使用应用E序提供的事件处理程序来处理 XML。JSR-173 提出了一U面向流的新Ҏ(gu)QStreaming API for XML (StAX)。其最l版本于 2004 q?3 月发布,q成Z JAXP 1.4Q将包含在即发布的 Java 6 中)的一部分?/p>
如其名称所暗示的那PStAX 把重Ҏ(gu)?i>?/i>上。实际上QStAX 与其他方法的区别在于应用程序能够把 XML 作ؓ一个事件流来处理。将 XML 作ؓ一l事件来处理的想法ƈ不新颖(事实?SAX 已经提出来了Q,但不同之处在?StAX 允许应用E序代码把这些事仉个拉出来,而不用提供在解析器方便时从解析器中接收事件的处理E序?/p>
StAX 实际上包括两套处?XML ?APIQ分别提供了不同E度的抽象。基于指针的 API 允许应用E序?XML 作ؓ一个标讎ͼ或事Ӟ来处理Q应用程序可以检查解析器的状态,获得解析的上一个标记的信息Q然后再处理下一个标讎ͼ依此cL。这是一U低?APIQ尽效率高Q但是没有提供底?XML l构的抽象。较为高U的Zq代器的 API 允许应用E序?XML 作ؓ一pd事g对象来处理,每个对象和应用程序交?XML l构的一部分。应用程序只需要确定解析事件的cdQ将其{换成对应的具体类型,然后利用其方法获得属于该事g的信息?/p>
回页?/b>
Z使用q两c?APIQ应用程序首先必获得一个具体的
XMLInputFactory
。根据传l的 JAXP 风格Q要用到抽象工厂模式Q?code>XMLInputFactory cL供了静态的newInstance
Ҏ(gu)Q它负责定位和实例化具体的工厂。配|该实例可设|定制或者预先定义好的属性(其名U在c?XMLInputFactory 中定义)。最后,Z使用Z指针?APIQ应用程序还要通过调用某个createXMLStreamReader
Ҏ(gu)获得一?span class="Apple-converted-space">
XMLStreamReader
。如果要使用Z事gq代器的 APIQ应用程序就要调?span class="Apple-converted-space"> createXMLEventReader
Ҏ(gu)获得一?span class="Apple-converted-space"> XMLEventReader
Q如清单 1 所C)?/p>XMLInputFactory
// get the default factory instance XMLInputFactory factory = XMLInputFactory.newInstance(); // configure it to create readers that coalesce adjacent character sections factory.setProperty(XMLInputFactory.IS_COALESCING, Boolean.TRUE); XMLStreamReader r = factory.createXMLStreamReader(input); // ... |
XMLStreamReader
?span class="Apple-converted-space"> XMLEventReader
都允许应用程序P代底层的 XML 。两U方法的差别在于如何公开解析后的 XML InfoSet 信息片段?code>XMLStreamReader 像一个指针,指在刚刚解析q的 XML 标记的后面,q提供了Ҏ(gu)获得更多关于该标记的信息。这U方法节U内存,因ؓ不用创徏新的对象。但是,业务应用E序开发h员可能会发现 XMLEventReader
更直观一些,因ؓ它实际上是一个标准的 Java q代器,?XML 变成了事件对象流。每个事件对象都装了它所表示的特?XML l构固有的信息。本pd的第二部分将详细讨论q种Z事gq代器的 API?/p>
使用哪种风格?API 取决于具体情c和Z指针?API 相比Q基于事件P代器?API h更多的面向对象特征。因此更便于应用于模块化的体pȝ构,因ؓ当前的解析器状态反映在事g对象中,应用E序lg在处理事件的时候不需要访问解析器/d器。此外,q可以?code>XMLInputFactory ?span class="Apple-converted-space"> createXMLEventReader(XMLStreamReader)
Ҏ(gu)?span class="Apple-converted-space"> XMLStreamReader
创徏 XMLEventReader
?/p>
StAX q定义了一U序列化?APIQJava 标准 XML 处理支持中一直缺的一U特性。和解析一P也包含两U风格的式 APIQ处理标记的底层 XMLStreamWriter
和处理事件对象的高层 XMLEventWriter
?code>XMLStreamWriter 提供了写入单?XML 记号Q比如开始和关闭标记或者元素属性)的方法,不检查这些标记是否格式良好。另一斚wQ?code>XMLEventWriter 允许应用E序向输Zd完整?XML 事g。第 3 部分详l讨?StAX 序列化器 API?/p>
开始学习一U新的处?XML ?API 之前Q可能要问是否值得q样做。事实上QStAX 所采用的基于拉的方法和其他Ҏ(gu)相比有一些突出的优点。首先,不管使用哪种 API 风格Q都是应用程序调用读取器Q解析器Q而不是相反。通过保留解析q程的控制权Q可以简化调用代码来准确地处理它预期的内宏V或者发生意外时停止解析。此外,׃该方法不Z处理E序回调Q应用程序不需要像使用 SAX 那样模拟解析器的状态?/p>
StAX 仍然保留?SAX 相对?DOM 的优炏V通过把重心从l果对象模型转移到解析流本nQ从理论上说应用E序能够处理无限?XML ,因ؓ事g固有的(f)时性,不会在内存中累积h。对于那些?XML 作ؓ消息传递协议而非表示文档内容的那些应用程序尤光要,比如 Web 服务或即时消息应用程序。比方说Q如果只是将其{换成特定于应用程序的对象模型然后将其丢弃,那么?Web 服务路由?servlet 提供一?DOM 没有多用处。?StAX 直接转化成应用程序模型效率更高。对?Extensible Messaging and Presence ProtocolQXMPPQ客hQ根本不能?DOMQ因?XMPP 客户?服务器流是随着用户输入的消息实时生成。等待流的关闭标{(以便最l徏?DOMQ就意味着{待整个会话l束。通过?XML 作ؓ一pd的事件来处理Q应用程序能够以最合适的方式响应每个事gQ比如显C收到的x消息{等Q?/p>
׃其双向性,StAX 也支持链式处理,特别是在事g层上。接收事Ӟ无论什么来源)的能力被装?XMLEventConsumerQXMLEventWriter 的扩展)接口中。因此,可以模块化地~写应用E序?XMLEventReaderQ也是一个普通的q代器,可以按P代器处理Q读取和处理 XML 事g、然后传递给事g消费者(如果需要可以进一步扩展处理链Q。在W?2 部分看刎ͼ也可使用应用E序提供的筛选器Q实C EventFilter 接口的类Q来定制 XMLEventReader 或者?EventReaderDelegate 修饰已有?XMLEventReader?/p>
总而言之,?DOM 以及 SAX 相比QStAX 使应用程序更贴近底层?XML。?StAXQ应用程序不仅可以徏立需要的对象模型Q而不需要处理标?DOMQ,而且可以随时q样做,而不必等到解析器回调?/p>
下一节将深入讨论Z指针?API 以及如何有效C用它处理 XML ?/p>
![]() ![]() |
![]()
|
如果使用Z指针?APIQ应用程序通过?XML 标记中Ud逻辑指针来处?XML。基于指针的解析器实质上是一个状态机Q在事g的驱动下从一个良好定义的状态{Ud另一个状态。这里的触发事g是随着应用E序使用适当的方法推动解析器在标记流中前q而解析出来的 XML 标记。在每个状态,都可使用一l方法获得上一个事件的信息。一般来_q每个状态下都能使用所有的Ҏ(gu)?/p>
使用Z指针的方法,应用E序首先必须通过调用?span class="Apple-converted-space"> createXMLStreamReader
Ҏ(gu)?span class="Apple-converted-space"> XMLInputFactory
得到 XMLStreamReader
。该Ҏ(gu)有多个版本,支持不同cd的输入。比方说Q可以创?span class="Apple-converted-space"> XMLStreamReader
解析 plain java.io.InputStream
?code>java.io.Reader 或?JAXP SourceQ?code>javax.xml.transform.SourceQ。从理论上说Q后一U办法很Ҏ(gu)和其?JAXP 技术交互,比如 SAX ?DOM?/p>
清单 2. 创徏 XMLStreamReader
解析 InputStream
URL url = new URL(uri); InputStream input = url.openStream(); XMLInputFactory factory = XMLInputFactory.newInstance(); XMLStreamReader r = factory.createXMLStreamReader(uri, input); // process the stream // ... r.close(); input.close(); |
XMLStreamReader
接口基本上定义了Z指针?APIQ虽然标记常量在其超cd XMLStreamConstants
接口中定义)。之所以称为基于指针,是因取器像是底层标记流上的指针。应用程序可以沿着标记向前推q指针ƈ分析当前指针所在位|的标记?/p>
XMLStreamReader
提供了多U方法导航标记流。ؓ了确定当前指针所指向的标讎ͼ或事Ӟ的类型,应用E序可以调用 getEventType()
。该Ҏ(gu)q回接口 XMLStreamConstants
中定义的一个标记常量。移动到下一个标讎ͼ应用E序可以调用 next()
。该Ҏ(gu)也返回解析的标记的类型,如果接着调用 getEventType()
则返回的值相同。只有当Ҏ(gu) hasNext()
q回 true Ӟ是说还有其他标记需要解析)才能调用该方法(以及其他Udd器的Ҏ(gu)Q?/p>
清单 3. 使用 XMLStreamReader
处理 XML 的常用模?/b>
// create an XMLStreamReader XMLStreamReader r = ...; try { int event = r.getEventType(); while (true) { switch (event) { case XMLStreamConstants.START_DOCUMENT: // add cases for each event of interest // ... } if (!r.hasNext()) break; event = r.next(); } } finally { r.close(); } |
q与其他几种Ҏ(gu)可以Ud reader
?span class="Apple-converted-space"> nextTag()
Ҏ(gu)蟩q所有的I白、注释或处理指oQ直到遇?span class="Apple-converted-space"> START_ELEMENT
?span class="Apple-converted-space"> END_ELEMENT
。该Ҏ(gu)在解析只含元素的内容时很有用Q如果在发现标记之前遇到非空白文本(不包括注释或处理指oQ,׃抛出异常?code>getElementText() Ҏ(gu)q回元素的开始和关闭标签Q即 START_ELEMENT
?span class="Apple-converted-space"> END_ELEMENT
Q之间的所有文本内宏V如果遇到嵌套的元素׃抛出异常?/p>
h意,q里?“标记??“事件?可以互换使用。虽然基于指针的 API 的文说的是事gQ但把输入源看成标记很方便。而且不容易造成混ؕQ因有一整套Z事g?APIQ那里的事g是真正的对象Q。不q,XMLStreamReader
的事件本质上q都是标记。比方说Q?code>START_DOCUMENT ?span class="Apple-converted-space"> END_DOCUMENT
事g不需要对应的标记。前一个事件是解析开始之前发生,后者则在没有更多解析工作要做的时候发生(比如解析完成最后一个元素的关闭标签之后Q读取器处于 END_ELEMENT
状态,但是如果没有发现更多的标记需要解析,d器就会切换到 END_DOCUMENT
状态)?/p>
在每个解析器状态,应用E序都可通过可用的方法获得相关信息。比如,无论当前是什么类型的事gQ?code>getNamespaceContext() ?span class="Apple-converted-space"> getNamespaceURI()
Ҏ(gu)可以获得当前有效的名U空间上下文和名U空?URI。类似的Q?code>getLocation() 可以获得当前事g的位|信息。方?code>hasName() ?span class="Apple-converted-space"> hasText()
可以分别判断当前事g是否有名Uͼ比如元素或属性)或文本(比如字符、注释或 CDATAQ。方?span class="Apple-converted-space"> isStartElement()
?code>isEndElement()?code>isCharacters() ?span class="Apple-converted-space"> isWhiteSpace()
可以方便地确定当前事件的性质。最后,Ҏ(gu) require(int
, String
, String
) 可以声明预期的解析器状态;除非当前事g是指定的cdQƈ且本地名和名U空_如果l出的话Q与当前事g匚wQ否则该Ҏ(gu)抛出异常?/p>
清单 4. 如果当前事g?span class="Apple-converted-space"> START_ELEMENT
使用有关的属性方?/b>
if (reader.getEventType() == XMLStreamConstants.START_ELEMENT) { System.out.println("Start Element: " + reader.getName()); for(int i = 0, n = reader.getAttributeCount(); i < n; ++i) { QName name = reader.getAttributeName(i); String value = reader.getAttributeValue(i); System.out.println("Attribute: " + name + "=" + value); } } |
创徏之后Q?code>XMLStreamReader 从 START_DOCUMENT
状态开始(?span class="Apple-converted-space"> getEventType()
q回 START_DOCUMENT
Q。处理标记的时候应考虑到这一炏V和q代器不同,不需要先Ud指针Q?span class="Apple-converted-space"> next()
Q来q入合法的状态。同样地Q当d器{换到最l状?span class="Apple-converted-space"> END_DOCUMENT
之后Q应用程序也不应再移动它。在q种状态下Q?code>hasNext() Ҏ(gu)返?false?/p>
START_DOCUMENT
事g提供了获取关于文本w信息的Ҏ(gu)Q如 getEncoding()
?code>getVersion() ?span class="Apple-converted-space"> isStandalone()
。应用程序也可调?span class="Apple-converted-space"> getProperty(String)
获得命名属性的|不过一些属性仅在特定状态做了定义(比方_如果当前事g?DTDQ则属?code>javax.xml.stream.notations ?span class="Apple-converted-space"> javax.xml.stream.entities
分别q回所有的W号和实体声明)?/p>
?span class="Apple-converted-space"> START_ELEMENT
?span class="Apple-converted-space"> END_ELEMENT
事g中,可以使用和元素名UC及名U空间有关的Ҏ(gu)Q如 getName()
?code>getLocalName()?code>getPrefix() ?span class="Apple-converted-space"> getNamespaceXXX()
Q,?span class="Apple-converted-space"> START_ELEMENT
事g中还可用与属性有关的Ҏ(gu)Q?code>getAttributeXXX()Q?/p>
ATTRIBUTE
?span class="Apple-converted-space"> NAMESPACE
也被识别为独立的事gQ虽然在解析 典型?XML 文时不会用到。但是当 ATTRIBUTE
?span class="Apple-converted-space"> NAMESPACE
节点作ؓ XPath 查询l果q回时可以用?/p>
和基于文本的事gQ如 CHARACTERS
?code>CDATA?code>COMMENT ?span class="Apple-converted-space"> SPACE
Q,可用各U?span class="Apple-converted-space"> getTextXXX()
Ҏ(gu)取得文本。可以分别?span class="Apple-converted-space"> getPITarget()
?span class="Apple-converted-space"> getPIData()
?span class="Apple-converted-space"> PROCESSING_INSTRUCTION
的目标和数据?code>ENTITY_REFERENCE ?span class="Apple-converted-space"> DTD
也支?code>getText()Q?code>ENTITY_REFERENCE q支?span class="Apple-converted-space"> getLocalName()
?/p>
解析完成后,应用E序关闭d器ƈ释放解析q程中获得的资源。请注意q样q没有关闭底层的输入源?/p>
清单 5 提供了一个完整的例子Q用基于指针的 API 处理 XML 文。首先取?span class="Apple-converted-space"> XMLInputFactory
的默认实例ƈ创徏一?span class="Apple-converted-space"> XMLStreamReader
解析l定的输入流。然后不断检查读取器的状态,Ҏ(gu)当前事g的类型报告某些信息(比如?span class="Apple-converted-space"> START_ELEMENT
状态下报告元素名及元素属性)。最后,遇到 END_DOCUMENT
时关闭读取器?/p>
清单 5. 使用 XMLStreamReader
解析 XML 文的完整例?/b>
XMLInputFactory factory = XMLInputFactory.newInstance(); XMLStreamReader r = factory.createXMLStreamReader(input); try { int event = r.getEventType(); while (true) { switch (event) { case XMLStreamConstants.START_DOCUMENT: out.println("Start Document."); break; case XMLStreamConstants.START_ELEMENT: out.println("Start Element: " + r.getName()); for(int i = 0, n = r.getAttributeCount(); i < n; ++i) out.println("Attribute: " + r.getAttributeName(i) + "=" + r.getAttributeValue(i)); break; case XMLStreamConstants.CHARACTERS: if (r.isWhiteSpace()) break; out.println("Text: " + r.getText()); break; case XMLStreamConstants.END_ELEMENT: out.println("End Element:" + r.getName()); break; case XMLStreamConstants.END_DOCUMENT: out.println("End Document."); break; } if (!r.hasNext()) break; event = r.next(); } } finally { r.close(); } |
通过调用 XMLInputFactory
的带有基本读取器?span class="Apple-converted-space"> createFilteredReader
Ҏ(gu)和一个应用程序定义的{选器Q即实现 StreamFilter
的类实例Q,可以创徏{选过?span class="Apple-converted-space"> XMLStreamReader
。导航筛选过的读取器Ӟd器每ơ移动到下一个标C前都会询问筛选器。如果筛选器认可了当前事Ӟ将其公开l筛选过的读取器。否则蟩q这个标记ƈ查下一个,依此cL。这U方法可以让开发h员创Z个仅处理解析内容子集的基于指针的 XML 处理E序Qƈ与针对不同的扩展的内Ҏ(gu)型的{选器l合使用?/p>
执行更复杂的操作,可以创徏 StreamReaderDelegate
的子cdƈ重写合适的Ҏ(gu)。然后用这个子cȝ实例包装基本 XMLStreamReader
Q从而ؓ应用E序提供一个修改过的基?XML 的视图。可通过q种技术对 XML 执行简单的转换Q比如筛掉或者替换特定的标记Q甚臛_加新的标记?/p>
清单 6 用定制的 StreamReaderDelegate
包装了基?span class="Apple-converted-space"> XMLStreamReader
Q重写了 next()
Ҏ(gu)来蟩q?span class="Apple-converted-space"> COMMENT
?span class="Apple-converted-space"> PROCESSING_INSTRUCTION
事g。用该d器时Q应用程序不用担心会遇到q种cd的标记?/p>
清单 6. 使用定制?span class="Apple-converted-space"> StreamReaderDelegate
{选注释和处理指o
URL url = new URL(uri); InputStream input = url.openStream(); XMLInputFactory f = XMLInputFactory.newInstance(); XMLStreamReader r = f.createXMLStreamReader(uri, input); XMLStreamReader fr = new StreamReaderDelegate(r) { public int next() throws XMLStreamException { while (true) { int event = super.next(); switch (event) { case XMLStreamConstants.COMMENT: case XMLStreamConstants.PROCESSING_INSTRUCTION: continue; default: return event; } } } }; try { int event = fr.getEventType(); while (true) { switch (event) { case XMLStreamConstants.COMMENT: case XMLStreamConstants.PROCESSING_INSTRUCTION: // this should never happen throw new IllegalStateException("Filter failed!"); default: // process XML normally } if (!fr.hasNext()) break; event = fr.next(); } } finally { fr.close(); } input.close(); |
![]() ![]() |
![]()
|
可以看到Q基于指针的 API 主要是ؓ了提高效率。所有的状态信息可以直接从读取器获得Q不需要创建额外的对象。非帔R用于性能和低内存占用臛_重要的应用程序?/p>
Z早就认识C拉式 XML 解析的好处。事实上QStAX 本n源于一U称?span class="Apple-converted-space"> XML Pull Parsing 的方法。XML Pull Parser API cM?StAX 所提供的基于指针的 APIQ可以通过分析解析器的状态获得上一个解析事件的信息Q然后移动到下一个,依此cL。但没有提供Z事gq代器的 API。这是一U非常轻型的Ҏ(gu)Q特别适合资源受限的环境,比如 J2ME。但是,很少有实现提供企业Ҏ(gu)如验证Q因?XML Pull 一直未受到企业 Java 开发h员的x?/p>
Z以往拉式解析器实现的l验QStAX 的创选择了在Z指针?API 之外增加一U面向对象的 API。虽?span class="Apple-converted-space"> XMLEventReader
接口看v来似乎很单,但是Z事gq代器的Ҏ(gu)h一个基于指针的Ҏ(gu)不具备的重要优点。通过解析器事g变成一U对象,从而让应用E序可以采用面向对象的方式处理它们。这样做有助于模块化和不同应用程序组件之间的代码重用?/p>
清单 7. 使用 StAX XMLEventReader
解析 XML
XMLInputFactory inputFactory = XMLInputFactory.newInstance(); XMLEventReader reader = inputFactory.createXMLEventReader(input); try { while (reader.hasNext()) { XMLEvent e = reader.nextEvent(); if (e.isCharacters() && ((Characters) e).isWhiteSpace()) continue; out.println(e); } } finally { reader.close(); } |
![]() ![]() |
![]()
|
本文介绍?StAX 及其Z指针?API。第 2 部分深入讨Z件P代器 API?/p>
![]() | ||
![]() |
Peter Nehrer 是一名专长于Z Eclipse 的企业解x案和 Java EE 应用E序的Y仉问。他创徏?Ecliptical Software Inc.Qƈ且是一些和 Eclipse 有关的开放源码项目的贡献者。他拥有从马萨诸塞州大学阉K斯特校区获得的计机U学士学位?/p> |
下蝲地址1:
http://cid-519b3f7aa2172030.skydrive.live.com/self.aspx/java/jrebel.rar
下蝲地址2:
http://beansoft.java-cn.org/download/jrebel.rar
New Features in EJB 3.1 - Part 2, http://www.theserverside.com/tt/articles/article.tss?l=NewFeaturesEJB31
Enterprise Java Community: The New Features in EJB 3.1 - Part 3 Enterprise Java Community- The New Features in EJB 3.1 - Part 3
看看下面的链接:
JSR 316: Java EE 6, http://jcp.org/en/jsr/detail?id=316.
成员列表Q以前的反叛者,L(fng)不用EJB的Spring后台公司Q红字部分,也加入了Java EE 6 的大家庭Q看来新版Java EE也许是大势所啊Q呵呵)Q?/p>
再看Spring直接开始了作ؓEJB容器的实现的支持目Q我一直说Spring只不q是另一个Application ServerQ而且q不是性能很好的那U)Q现在终于得C验证Q红字的是 Rod 大叔QJava的开源,大多数最后都会成立公司,成ؓ商业目来运营,从Hibernate,JBoss再到SpringQ无一例外Q盖目代码大了以后Q就是开源了Q外Z看不懂)Q?/p>
http://static.interface21.com/projects/pitchfork/files/m4/docs/reference/html_single/
Version 1.0-m4
At the moment, Spring JEE support understands the following annotations, which are part of the JSR 250 and JSR 220:
JSR 250 injection annotations (javax.annotation): @PostCostruct, @PreDestroy and @Resource
EJB3 interception annotations (javax.interceptor): @AroundInvoke, @ExcludeClassInterceptors, @ExcludeDefaultInterceptors, @Interceptors, @Invocation
EJB3 transaction annotations (javax.ejb): @Stateless, @ApplicationException and @TransactionAttribute
EJB3 injection annotation (javax.ejb): @EJB (since M2)
In short, Spring can understand Java EE 5.0 injection, interception and transactional metadata.
如无法全屏,L(fng)击这里:http://6.cn/watch/4599331.html
图文版说明及无声视频请参?a href="/beansoft/archive/2008/04/17/193691.html">独家QJava EE 5 中文 API 文在线阅读和操作视?/a>
最q互联网上挂起了一股到处散发广告传单,严重q扰工作学习的歪风。我x技术的爱国的话多分n点资料和l验吧!q样L那些整天只知道空谈爱国,动辄抵制XX的“爱国青q”强炏V多share是最大的爱国Q?/p>
相比较微软的开发工兯l的中文文档外,Java 的API长期以来只有英文Q还好最q已l有了中文的Java SE文。不q,Java EE 5 的中文API 却难得一见,然而,q运的是现在我们l于可以看到中文?Java EE 5文了,虽然有些遗憾只能在线览Q不qL没有强,以后它们肯定会提供中文版的文档包下蝲的!
q个阅读文的地址是http://doc.java.sun.com/DocWeb/Q而且Q它采用开源的协议Q读者可以注册一个用户参与翻译。也正因为如此,我认为其中的文q不全面Q需要有条g的h共同参与完成中文化文。下面我们就看看如何阅读中文文?/p>
q入首页Q?/p>
如果要查看单中文文档,可以在“EJB日”上点右键,选择菜单“在新窗口中打开”即可。如下图所C:
下面是操作视频: