* H1 _ }6 m {( Z+ R J0 f' x* i0 F% `0 q2 \<LI>将 JSP 和 HTML 文件 <CODE>jsp/*</CODE> 复制到 <CODE>Webapps/JSPMath</CODE> 内的任何目录下。 ( @4 Q' D6 u, ~4 C8 \+ M 9 |! z7 t" k3 ^2 {6 n( v1 ~& s3 i ?# J
<LI>现在,可以通过将浏览器指向 <CODE>Test01.html</CODE> 或 <CODE>Test02.html</CODE> 来开始测试。</LI></OL>$ k( J# K8 s$ F/ a
<P>一旦安装了应用程序,就可以遵循本节中的步骤来查看示例是如何工作的。</P>( {3 Y! c$ c! ]( T
<P><A>正在运行的示例代码</A> 6 @2 u9 e6 S" [/ E样本代码包含两种新的 JSP 定制标记。<CODE><LatexRaw></CODE> 标记将原始 LaTeX 文本转换成 HTML 图像标记。可以使用它在单个图像中显示多个公式、表或简短文本标题。<CODE><LatexMath></CODE> 标记只将单个公式图像的数学方式 LaTeX 文本转换成 HTML 图像标记。可以使用它来实现公式的快速显示。</P>2 E" o2 s# }3 y2 S/ I! c3 a
<P>每个标记都有两个属性,<CODE>height</CODE> 和 <CODE>width</CODE>,它们对应于结果 <CODE><IMG></CODE> 标记中的属性 <CODE>height</CODE> 和 <CODE>width</CODE>。这些属性不是必需的。</P>; ?1 U2 h z6 H+ [4 Q7 ^5 x# e
<P>下面的屏幕快照显示了正在运行的定制标记。Test01.html 在两个大文本域中采集 LaTeX 文本字符串。该页面顶部的两个小的文本输入框采集用户期望的其中一个结果图像的高度和宽度。在 Test01.jsp 中,我们将以这里指定的用户期望尺寸和由 ImageMagick 指定的缺省尺寸显示图像,以演示如何在定制标记中使用尺寸属性。已填写的 HTML 表单出现在浏览器中,如图 6 所示。</P> [0 [7 ^# E1 `$ D5 e<P><A><B>图 6. LaTeX Math 输入表单</B></A><IMG src="http://www-900.ibm.com/developerWorks/cn/java/j-jspmath/fig06.gif"></P>+ ^; {2 h& I0 a3 S; O
<P>当我们在 Test01.html 中提交表单时,它将数据张贴到 JSP 页面 Test01.jsp 上,该页面显示了生成的公式图像,如图 7 所示。第一个图像是由标记 <CODE><LatexMath></CODE> 使用来自 HTML 输入表单中 <CODE>MathText</CODE> 域(单行文本域)的数学方式 LaTeX 文本生成的。请注意,第一个图像的 <CODE><LatexMath></CODE> 标记具有两个属性。然后按照用户指定的 <CODE>height</CODE> 和 <CODE>width</CODE> 属性的尺寸来显示图像。按照与第一个图像相同的方法来生成第二个图像,只是以缺省尺寸来显示第二个图像(生成第二个图像的标记没有尺寸属性)。第三个图像是混合文本和数学符号的示例,它由从 <CODE>RawMathText</CODE> 输入域(大型多行文本域)中的 LaTeX 文本的标记 <CODE><LatexRaw></CODE> 生成。指定的高度和宽度域不适用于这个图像。</P># g9 ?& G9 l/ Y: s: u- P& O
<P><A><B>图 7. 数学图像输出</B></A><IMG src="http://www-900.ibm.com/developerWorks/cn/java/j-jspmath/fig07.gif"></P> ! Y6 @, i4 c& Y, D6 a7 I<P>清单 1 显示了 Test01.jsp 中的代码,它们可以实现以上所有目标。</P>: ?/ y1 E* Y* G) y% A" B9 d
<P><A><B>清单 1. Test01.jsp</B></A> % s2 ~2 V6 S- i: ~9 k6 z( {- P
<TABLE cellSpacing=0 cellPadding=5 width="100%" bgColor=#cccccc border=1>$ p, i* d. U/ r1 o2 L5 K
8 w7 X8 K$ r# P( e7 V" \
<TR>4 w# o( ~* t$ o/ a! z
<TD><PRE><CODE><%@ taglib uri="/WEB-INF/tlds/SlowMathTaglib.tld" prefix="SlowMathTag" %><% String mathText = request.getParameter( "MathText" ); String rawMathText = request.getParameter( "RawMathText" ); String height = request.getParameter( "height" ); String width = request.getParameter( "width" );%><html><head> <title>JSPMath test without image cache</title></head><body bgcolor=white><p><font color=green> Math formula in desired dimensions: </font><p><SlowMathTagatexMath height="<%=height%>" width="<%=width%>"> <%=mathText%></SlowMathTagatexMath><p><font color=green> Math formula in default dimensions: </font><p><SlowMathTagatexMath> <%=mathText%></SlowMathTagatexMath><p><font color=green> Latex segment in default dimensions: </font><p><SlowMathTagatexRaw> <%=rawMathText%></SlowMathTagatexRaw></body></html></CODE></PRE></TD></TR></TABLE></P> . Q- A K7 i) F0 r2 q<P>清单 2 显示了在一次执行中 JSP 容器发送到 Web 浏览器的实际 HTML 代码。</P> . I: g2 v' c. e+ v, y0 Q7 C) N<P><A><B>清单 2. 从 Test01.jsp 发送到浏览器的 HTML 代码</B></A> + J: [+ ]. Z% p<TABLE cellSpacing=0 cellPadding=5 width="100%" bgColor=#cccccc border=1>& P" k1 W: b! a1 m$ ?( H* F
: {9 V* e0 S0 @7 V<TR>' { t3 D1 q* P) h# c5 G& f
<TD><PRE><CODE><html><head> <title>JSPMath test without image cache</title></head><body bgcolor=white><p><font color=green> Math formula in desired dimensions: </font><p><IMG SRC="http://localhost:8080/JSPMath/images/image1009709773390.gif" height=20 width=150 /><p><font color=green> Math formula in default dimensions: </font><p><IMG SRC="http://localhost:8080/JSPMath/images/image1009709776535.gif" /><p><font color=green> Latex segment in default dimensions: </font><p><IMG SRC="http://localhost:8080/JSPMath/images/image1009709777612.gif" /></body></html></CODE></PRE></TD></TR></TABLE></P> 7 v5 P R c. J<P>这里的 GIF 图像是由标记处理器生成的。如图 7 所示,使用用户指定的尺寸放大的图像看起来不是很平滑。有关出现这一情况的原因以及如何在 UNIX/Linux 系统上处理它,请参考标题为“<a href="http://www-900.ibm.com/developerWorks/cn/java/j-jspmath/index.shtml#sidebar2" target="_blank" ><FONT color=#000000>矢量图与位图的对比</FONT></A>”的边注。</P>+ s% I+ ~2 [) Q0 j
<P>我们如何实现这些定制标记操作呢?请继续阅读,找出答案。</P>( Q- O- F& T! r; ^% Z
<P><A>一种简单(但缓慢)的方法</A> * C& x9 A$ N6 K2 a/ J/ J2 W可以用很简单和直接的方式实现上面的示例。对于本文,您应该已经知道如何实现 JSP 定制标记处理器了。如果您想更新一下您的知识,请参考下面的<a href="http://www-900.ibm.com/developerWorks/cn/java/j-jspmath/index.shtml#resources" target="_blank" ><FONT color=#000000>参考资料</FONT></A>一节。</P>+ A5 j: w' R7 `7 J N+ r
<P><CODE><SlowMathTag:*></CODE> 标记处理器调用静态方法 <CODE>support.MathUtil.latex2gif()</CODE> 以生成 GIF 图像。让我们研究一下这种方法的源代码以及它是如何工作的。</P> * j- c* s X9 z<P>首先,该方法确定当前标记生成的 GIF 图像以及中间文件的唯一名称,如清单 3 所示。那些文件的根名称是当前时间的毫秒值。</P>$ Q/ |! a$ `# d1 i6 a3 K! M
<P><A><B>清单 3. 生成文件名</B></A> 4 {- @; {. d4 R9 d
<TABLE cellSpacing=0 cellPadding=5 width="100%" bgColor=#cccccc border=1> 4 {5 B% o3 J4 j$ j n6 l- T( H) [, @9 _ B* W! T) ^& _
<TR>. H* t) s7 M* G' z$ c0 m* Z
<TD><PRE><CODE>Date now = new Date ();String filename = "image" + Long.toString(now.getTime());// ...File f = new File(path + filename + ".tex");</CODE></PRE></TD></TR></TABLE></P> 3 J# k0 X g7 h6 B* R& b<P>接下来,该方法从标记主体中采集内容,然后组装成一个完整的 LaTeX 输入文件,如清单 4 所示。JSP 容器用字符串变量 <CODE>latexStr</CODE> 将标记主体传送到方法 <CODE>latex2gif()</CODE>。使用 <CODE>\pagestyle{empty}</CODE> 命令以消除在结果页面底部显示的页号。使用 <CODE>\batchmode</CODE> 命令使 LaTeX 处理器在非交互方式下执行。</P>* e3 D; W+ [# W! O
<P><A><B>清单 4. 汇编 LaTeX 输入文件</B></A> + o$ E8 C& `; }<TABLE cellSpacing=0 cellPadding=5 width="100%" bgColor=#cccccc border=1> 4 g1 M: R: g3 n3 w6 r0 L 4 b- o: N ^3 ?: r' n% X! B<TR> x3 q7 i$ N$ I% P# Z<TD><PRE><CODE>private static String latexHead = "\\batchmode\n" + "\\documentclass[12pt]{article}\n" + "\\pagestyle{empty}\n" + "\\begin{document}\n";private static String latexEnd = "\\end{document}\n";// ...// String variable "latexStr" contains the body of the current tag.// Process modes.if ( mode.equals("displaymath") ) { latexStr = "\\Large\n\\begin{displaymath}\n" + latexStr.trim() + "\\end{displaymath}\n";} else { // Unrecognized modes are raw latex strings.}// Write content into a latex file.FileWriter fw = new FileWriter(f);fw.write( latexHead, 0, latexHead.length() );fw.write( latexStr, 0, latexStr.length() );fw.write( latexEnd, 0, latexEnd.length() );</CODE></PRE></TD></TR></TABLE></P> 6 c# q5 q% t, K<P>现在,该方法执行命令 <CODE>latex</CODE>、<CODE>dvips</CODE> 和 <CODE>convert</CODE>,以在服务器方的预先配置目录 <CODE>path</CODE> 下生成最终的 GIF 图像,如清单 5 所示。</P>; J' _9 B! D, n1 {, y% `# v# r
<P><A><B>清单 5. 生成 GIF 文件</B></A> , G5 o/ ?- f7 J! ]8 g5 a3 ?- }" v5 x<TABLE cellSpacing=0 cellPadding=5 width="100%" bgColor=#cccccc border=1> , t9 U" d! S5 f: ^+ t8 Y" n/ Y7 D: L# a9 N+ m4 e: i1 k1 @; z9 }
<TR> / ]2 ?# t/ Y/ |; R- @0 _<TD><PRE><CODE>private static String latexCommand = "/usr/bin/latex";private static String dvipsCommand = "/usr/bin/dvips";private static String convertCommand = "/usr/X11R6/bin/convert -antialias -crop 0x0";// ...public static synchronized String latex2gif (String path, String mode, String latexStr) throws Exception { // Generate root file name and create ".tex" file // ... // Get Runtime. Runtime r = Runtime.getRuntime(); Process p; File imagePath = new File( path ); // ... // Run latex in directory "imagePath". p = r.exec(latexCommand + " " + filename + ".tex", null, imagePath); if ( p.waitFor() != 0 ) throw new Exception("Error in Latex\n"); // Run dvips in directory "imagePath". p = r.exec(dvipsCommand + " -o " + filename + ".ps " + filename + ".dvi", null, imagePath); if ( p.waitFor() != 0 ) throw new Exception("Error in dvips\n"); // Run convert in directory "imagePath". p = r.exec(convertCommand + " " + filename + ".ps " + filename + ".gif", null, imagePath); if ( p.waitFor() != 0 ) throw new Exception("Error in convert\n"); // ...}</CODE></PRE></TD></TR></TABLE></P>) N* N7 p; {' H) P$ s% V, s& ?; g
<P>最后,该方法删除所有中间文件,如清单 6 所示。</P>2 X+ P, Y1 G( s2 S3 q
<P><A><B>清单 6. 删除中间文件</B></A> : H! ?& s$ O" ~) ?' h7 d+ N
<TABLE cellSpacing=0 cellPadding=5 width="100%" bgColor=#cccccc border=1> 8 K: [6 Y$ m: j E6 _6 N8 i$ u2 B
<TR> & `- G/ R8 l" \# l<TD><PRE><CODE>f = new File(path + filename + ".tex");f.delete();f = new File(path + filename + ".log");f.delete();f = new File(path + filename + ".aux");f.delete();f = new File(path + filename + ".dvi");f.delete();f = new File(path + filename + ".ps");f.delete();</CODE></PRE></TD></TR></TABLE></P>- m3 S$ Q0 b5 ?4 X! f* w9 E% y
<P>现在,标记处理器可以将生成的 GIF 图像的 <CODE><IMG></CODE> HTML 标记写入服务器输出流。</P>0 C1 M' T- j7 G: Q3 M; D' X
<P>刚刚描绘的方法很简单,但是正如我们马上就会看到的它很慢而且容易出错。在接下来的几节中,我们将讨论改进这一解决方案的性能和健壮性的方法。</P> + ?% f0 I8 o" C<P><A>通过高速缓存改进性能</A>, O7 f R; j* d2 z. G0 h
从 LaTeX 输入文本生成图像是很慢的,因为它涉及多个外部程序。在上一节的简单实现中,每次调用 <CODE><SlowMathTag:*></CODE> 定制标记处理器时,它都必须生成一个新图像。这样效率是非常低的。在示例应用程序中,Test01.jsp 中的两个 <CODE><SlowMathTagatexMath></CODE> 标记需要为每个访问者两次生成相同的公式图像,只是为了用不同的尺寸来显示它。现实世界中,应用程序很可能比示例应用程序复杂得多,并且生成不必要的图像带来的性能开销可能很严重。想象一下,我们的站点将提供动态数学考试,并且许多访问者会遇到相同的考试题目。为每个访问者一次次地重新生成同一公式的图像太昂贵了。</P> 5 h8 E$ r" F- q }5 X<P>对于一个规模可伸缩的解决方案,我们需要对生成的图像进行高速缓存,然后在将来需要的时候重用它们。可以将 LaTeX 文本用作图像名称的<I>键</I>。如果标记处理器第二次遇到同一个 LaTeX 文本,则它可以找出高速缓存图像的文件名,然后直接返回它。可以将一对对的 LaTeX 文本和图像名称存储在 SQL 数据库以便长久保存和快速搜索。可以使用具有不同作用域的数据库访问 JavaBean 来对那些高速缓存的图像的访问作进一步的调节。虽然对于读者来说,这样的调节可能是一个有趣的实践,但是却超出了本文的范围。</P>: O5 P3 ?; {2 a z
<P>这里,我们将把高速缓存的图像作为静态数据成员存储在标记处理器助手类中。那些静态数据成员具有与 JSP 服务器容器相同的生命期。如果更改网站,然后重新启动服务器,则会丢弃旧的高速缓存。将高速缓存的 LaTeX 文本和图像名称存储在两个静态的 <CODE>Vector</CODE> 中。当标记处理器遇到 LaTeX 文本字符串时,它遍历高速缓存的 LaTeX 文本 <CODE>Vector</CODE>。如果它发现一个匹配项,则返回相应的图像名称。如果没发现,则继续生成一个新的公式图像并将新的 LaTeX 文本/图像对存储在高速缓存中。清单 7 说明了这个方法。</P>1 V V; l- a& L) f4 n+ Q! D
<P><A><B>清单 7. MathUtil.getImage()</B></A> * [8 V2 c# z" X( Y- j<TABLE cellSpacing=0 cellPadding=5 width="100%" bgColor=#cccccc border=1>% r- H! w- K+ R/ U
' ?; o8 k7 ]& X; N0 T3 X: l<TR>! E8 r0 a3 b4 a. n
<TD><PRE><CODE>public static synchronized String getImage (String path, String mode, String latexStr) throws Exception { // Formatted string stored in the latexStrVec vector. String comp = "MODE=" + mode + "\nLaTeX=" + latexStr.trim(); // Iterate through the "latexStrVec" cache and check if any // element matches the input string and mode. for (int i = 0; i < latexStrVec.size(); i++) { String l = (String) latexStrVec.elementAt(i); if ( comp.equals(l) ) { // Return the cached image name if a match is found. return (String) imageNameVec.elementAt(i); } } // If no match is found, generate a new image // and store it in the cache. return storeImage(mode, latexStr, latex2gif(path, mode, latexStr) );}</CODE></PRE></TD></TR></TABLE></P> 4 O# }* q* B) A! @+ g<P>Test02.html 和 Test02.jsp 将高速缓存改良的标记处理器用于 <CODE><MathTag:*></CODE> 标记。尝试它们,然后在 <CODE><SlowMathTag:*></CODE> 标记上感受这一改进。</P>" K5 N/ N' N! w3 ^
<P><A>减少中间文件</A>+ A8 _9 _2 y& x+ o) W$ d6 a7 g7 e
正如我们所见,实用程序使用很慢的磁盘文件互相通信,并且我们需要在完成该过程时删除所有中间文件。那些中间文件不仅造成了不必要的开销还容易导致磁盘和文件系统错误。在 UNIX/Linux 系统中,可以使用管道连接不同程序的输入和输出,并且部分消除对中间文件的需要。因为 Java 运行时不直接支持 UNIX 管道,所以我们必须从 shell 调用它们,如清单 8 所示。</P>8 U7 O; X1 z2 S2 R# T- S6 l0 L
<P><A><B>清单 8. 使用管道输入/输出调用命令</B></A> " h5 l! N' t4 _
<TABLE cellSpacing=0 cellPadding=5 width="100%" bgColor=#cccccc border=1>. M6 [5 Y; x; Z) ^* W
4 }5 I* d5 U2 x' b ] , @0 E. G7 Q, c- v4 \<LI>在“<a href="http://www-106.ibm.com/developerWorks/java/library/j-taglib/" target="_blank" ><FONT color=#000000>Take control of your JSP pages with custom tags</FONT></A>”一文中,Jeff K. Wilson 提供了定制标记库如何允许您向 JSP 添加更复杂逻辑、更稳定地控制数据显示以及在标记中共享数据的详细信息。" v' p; T g& _8 ]5 ^9 e. ^
) j- |+ C* x! ^. h1 w. a 5 K9 J& f7 s* ]7 `2 @5 |$ m3 [ f/ Z<LI><I><A herf="http://www.manning.com/fields2/">Web Development with JavaServer Pages, 2nd Edition</A> 一书(由 </I>D. K. Fields,M. A. Kolb 和 Shawn Bayern 合著)(Manning Publications,2001 年)是一本几乎包含了 JSP 各个方面的好书。 ; c, Y: b" b9 o. f% I7 \. }: z $ R* H% p$ I; X2 _# _, n; u" K+ e9 K# [# h4 c
<LI><I><A herf="http://www.manning.com/shachor/">JSP Tag Libraries</A>(</I>由 Gal Shachor、Adam Chace 和 Magnus Rydin 合著)(Manning Publications,2001 年)对于如何设计和实现 JSP 定制标记库有一些好的示例和解释。 2 C F) h/ @, U/ U# B1 g1 t, H/ e8 b& _- M; ^, z7 ?- ]' f
* r/ D1 Q" Z( T. L- V) }" e* Q<LI>在“<a href="http://www-106.ibm.com/developerWorks/java/library/j-jsptags.html" target="_blank" ><FONT color=#000000>JSP taglibs: Better usability by design</FONT></A>”(developerWorks,2001 年 12 月)中 Noel J. Bergman 讨论了 JSP 定制标记设计问题。 1 ]: E" [& u7 c" G* H) m1 L7 r 6 ?2 A4 t3 J% \( A9 I# F, V" G 8 s3 [: Z7 G3 A" b ^) p5 H<LI>WebSphere 开发者园地为那些想关注<a href="http://www-106.ibm.com/developerWorks/cgi-bin/click.cgi?url=http://www7b.boulder.ibm.com/wsdd/library/tutorials/vajwebsph353/Part-I/JSP11Part-I.html&origin=j" target="_blank" ><FONT color=#000000>将 JSP 定制标记和 VisualAge for Java 和 WebSphere Studio 组合起来</FONT></A>的人提供了一个很好的教程。</LI></UL> 2 S+ c8 u+ j6 h% w; q( A<P><B>工具</B></P> $ A, t2 a, {! x<UL>+ R/ e9 c) t; j: c
<LI>研究一下 <a href="http://www.latex-project.org/" target="_blank" ><FONT color=#000000>LaTeX</FONT></A> 项目的主页。5 ~+ h3 a8 B" q4 q7 `* S# d: y
( X" n$ i( a& [) w4 g- p 3 d; L5 ^# ~: T8 Y. H) U<LI>查看 <a href="http://www.imagemagick.org/" target="_blank" ><FONT color=#000000>ImageMagick</FONT></A> 图像操作工具。! c) C# Y7 ?- R# w( L5 d) i5 f1 Q
' I$ {, H( b( m) O
JavaServer Pages 技术和 LaTeX 帮助的联机科学教育与研究 $ s/ g1 ?/ r8 p Y7 y
) ?( g4 J% g$ o A% l. K1 P: t2 aBuilding dynamic Web sites with mathematical content ; ]( u: v( @, r/ ?. z" R* x/ [1 `1 B; c; m8 z2 m: b0 |( H. K( }
JavaServer Pages technology and LaTeX help online science education and research " E: x, g1 x" Z4 c+ r4 V+ S) |
$ x+ m* w$ X; {" D1 }8 S) ]Michael Juntao Yuanjuntao@astro.as.utexas.edu) : Y9 r8 L, G/ s& B; c8 N1 A0 g) {博士研究生,德州大学奥斯汀分校 ( V6 ?2 T6 C: E8 |; f& V9 x, _2002 年 2 月 * U/ z% K4 o/ ]4 A4 x$ Q- B' C* K5 l! Z; _. y) ?
Mathematical formulae, with their subscripts, superscripts, and special symbols, are devilishly difficult to translate into HTML. Most scientists and mathematicians use the flexible LaTeX text processor to create aesthetically pleasing formulae -- but how can you convert this output to a Web-friendly form? In this article, Michael Yuan shows how JSP pages and custom tags can get LaTeX-formatted formulae onto the Web in a fashion that is easy for the author and doesn't require any special client-side software. As he iterates through increasingly efficient methods, you'll see how server-side Java technology can harness the power of disparate third-party tools to solve seemingly intractable problems. Share your thoughts on this article with the author and other readers in the discussion forum by clicking Discuss at the top or bottom of the article. ' a9 P3 u, F, R
The Internet and the Web were originally designed by scientists to exchange scientific and mathematical research information. Ironically, after more than 30 years of Internet and 10 years of Web development, there is still no easy way to publish mathematics-intensive content on the Web. Web mathematical communication standards, such as the W3C's MathML recommendation, have been developed; but to use them, both the author and the reader of mathematical content need special software, like the techexplorer mathematical browser plug-in from IBM for Netscape Navigator and Internet Explorer. (See Resources for links to TechExplorer and MathML.) Users are reluctant to install special client-side software because of the technical difficulties, costs, and security risks involved. Thus, the adoption of those standards is limited to small research cycles, and the vast majority of Internet users cannot use them. Today, the most convenient way to share mathematical information on the Web is still to convert all nontext formulae into snapshot images and then insert those images into standard HTML pages. ( x% U3 x; O6 w) k5 r3 G, b) j# w7 M' j9 M
Most modern GUI-based mathematical authorizing tools have options to save documents as "Web pages"; these tools generate formulae images and static HTML pages for you. This is convenient if you just want to publish static content, such as your thesis, on the Web. But the days for static Web sites are long gone as user participation has become integral in most sites. Advanced mathematical Web sites should publish content dynamically from back-end databases and allow users to submit their own content to share with other users (examples include interactive exam systems and research collaboration systems). 2 x2 l, A- O: C9 t$ Y' { ' u: V9 `- L: r! |3 \# gThis article will show you one solution to the problem. The sample code provides a means by which marked-up text representing a mathematical formula can quickly and easily be transformed into a Web-ready graphic file displaying that formula. Along the way, you'll see one approach to a more general conundrum: we'll use JSP pages and custom tags to link several disparate and unconnected tools into a single program. When you're working on tricky dynamic Web applications, remember that you don't have to start from scratch; the solution may be available in a different form, waiting for you to harness it. 8 F) _9 d6 y) z/ [1 C! j4 v
' F7 w9 G: r& Z, J1 u0 ] 6 @$ V! d5 D8 G/ H- } : D* G* q0 _% \( c将含有下标、上标和特殊符号的数学公式转换成 HTML 非常困难。大多数科学家和数学家使用灵活的 LaTeX 文本处理器来创建外表美观的公式 — 但是如何将这个输出转换成 Web 友好的格式呢?在本文中,Michael Yuan 说明了如何使用 JSP 页面和定制标记将 LaTeX 格式的公式放到 Web 上,这种方法对于编写者来说很简便并且不需要任何特定的客户机端软件。正如他在各种日益有效的方法中反复说明的,您会发现服务器方 Java 技术如何利用不同的第三方工具来解决看似很难处理的问题。通过单击本文顶部或底部的讨论在论坛中将您对本文的想法与作者和其他读者一起分享。 / P+ h' ^6 i( \8 G* u因特网和 Web 最初是由科学家设计用来交换科学和数学研究信息的。出乎意料的是,经过因特网 30 多年的发展以及 Web 10 年的发展,仍然没有一种简便的方法将数学密集型内容发布到 Web 上。已经开发了 Web 数学通信标准,例如 W3C 的 MathML 建议;但是为了使用它们,数学内容的作者和读者都需要特定软件,比如用于 Netscape Navigator 和 Internet Explorer 的 IBM techexplorer 数学浏览器插件。(请参阅参考资料以获取到 TechExplorer 和 MathML 的链接。)由于技术困难、成本和安全性危险因素,用户不太愿安装特定客户机端软件。因此,使那些标准的采用被限制在狭窄的研究领域,并且广大因特网用户无法使用它们。当前在 Web 上共享数学信息最方便的方法仍是将所有非文本公式转换成快照图像,然后将那些图像插入标准 HTML 页面。 " J5 e) |# t7 y8 O" L- T2 s( }
, Q" c0 l( {+ c( Y
最新的基于 GUI 的数学权威性工具具有将文档保存为“Web 页面”的选项;这些工具为您生成公式图像和静态 HTML 页面。如果您只是想在 Web 上发布静态内容,例如论文,则这种方法是很方便的。但是,静态网站的时代已经早就过去了,因为在大多数网站中用户的参与已经变得不可缺少。高级数学网站应该从后台数据库中动态地发布内容并允许用户提交他们自己的内容以与其他用户分享(示例包括交互式考试系统和研究协作系统)。 6 }1 |6 T5 l( o: |3 Q8 R \( O9 h% z$ \0 q+ Y
本文将向您展示该问题的一种解决方案。样本代码提供了一种方法,它可以快速简便地将表示数学公式的标记文本转换成显示该公式的可用于 Web 的图形文件。在此过程中,您会看到解决更多一般性难题的方法:我们将使用 JSP 页面和定制标记将几个完全不同的且互不相连的工具链接在单个程序中。当您使用多变的动态 Web 应用程序时,请记住不必从头做起;解决方案也可以其它形式提供,这由您控制。 7 l9 ^! o, y# [' S$ e! Y% g- @+ ?( t
$ Q( p# _' j& s中文:<a href="http://www-900.ibm.com/developerWorks/cn/java/j-jspmath/index.shtml" target="_blank" ><FONT color=#000000>http://www-900.ibm.com/developerWorks/cn/java/j-jspmath/index.shtml </FONT></A>2 k9 v) S. a) Q: Y- w