分享
 
 
 

J2EE和XML开发——用户接口(二)

王朝java/jsp·作者佚名  2006-01-08
窄屏简体版  字體: |||超大  

J2EE应用用户接口开发(二)

作者 KURT A. GABRICK

DAVID B. WEISS

出处 J2EE and XML Development第五章

地址 <http://www.manning.com/gabrick>

本文是J2EE和XML开发用户接口的第二部分,如果对文中的例子不熟悉请参见本文的第一部分--J2EE和XML开发用户接口(一) <http://www.csdn.net/develop/article/19/19844.shtm>。

四.J2EE联合XML的解决方案

首先我们要接触的XML架构是联合使用XSLT和J2EE表示层组件。XSLT提供了一种通用的方法,可以将XML文档转换成为各种输出格式。这使得瘦客户端用户接口开发变得十分简易。XSLT处理器的输出格式由XSL样式定义的转换规则决定。我们的例子需要HTML和WML格式的输出。如果你队XSLT使用不是很清楚,可以参见<http://www.zvon.org>网站提供的XSLT在线教程。

4. 1 将XSLT加入Web开发流程

在第一部分中,我们创建了一个servlet控制器,一个定制标记(同时也是一个JavaBean)和四个JSP页。将XSLT处理加进来,对我们的设计可以产生下列四个影响:

·不再需要使用我们设计的JSP

·不再需要使用我们设计的定制标记(同时也是JavaBean)

·我们需要一个新的出filter组件处理XSLT

·我们需要修改我们的WatchListJSPServlet移除JSP的转发语句

Filter过滤器是J2EE表示层框架中的新成员。它们对于将Web工作流程连接起来很有用处。一个过滤器可以被应用于特定的请求或者你的整个应用中。过滤器可以对请求进行预处理(当请求到达servlet前)或者后处理。在本文的例子中,我们只对任何被我们的servlet控制器处理的请求的后处理感兴趣。

XSLT请求处理流程开始于我们的servlet控制器接受到一个询问股价的请求。Servlet通过ListBuilder类与应用逻辑层交换信息,而ListBuilder类的返回一个JDOM文档。视图的选择逻辑现在将由我们新的过滤器组件处理,它将从XSL样式表中选择一个,而不是原来的JSP。

例子应用全新的体系结构如下图所描述。

4.1.1 XSLT过滤器处理过程

我们通过开发过滤器来开始我们XSLT的例子,这个过滤器将管理样式表的选择以及XSLT的转换过程。以下是有关与此过滤器如何工作的概括:

·每个从Watch List页来的Web请求都被过滤器拦截并且处理完成后交给控制器。

·JDOM文档经由HttpRequest对象返回给过滤器。

·过滤器决定设备的类型和用户所在地区。

·过滤器选择最合适的XSL样式并且调用XSLT处理器将JDOM结果转换为目标格式。

·过滤器发送经过XSLT转换的结果到客户的设备。在那里提交并显示。

4.1.2 修改servlet

因为我们的过滤器将选择合适的样式并且没有使用JSP的需要,所以我们修改WatchListServlet使它变得相当简单。它的源代码在列表8中显示。现在servlet与ListBuilder接口交互并且在HttpRequest对象中存储JDOM文档。

列表8

import org.jdom.*;

import java.io.*;

import javax.servlet.*;

import javax.servlet.http.*;

/**

* The stock watchlist servlet with XSLT

*/

public class WatchListServlet extends HttpServlet {

private ListBuilder builderInterface = new ListBuilder();

private ServletConfig config;

private ServletContext context;

public WatchListServlet() { super(); }

public void init(ServletConfig config)

throws ServletException {

this.config = config;

this.context = config.getServletContext();

}

public void doGet(HttpServletRequest request,HttpServletResponse response)

throws ServletException, IOException {

HttpSession session = request.getSession(false);

if (session == null) {

context.getRequestDispatcher("/login.jsp").forward(request, response);

return;

}

String userId = (String) session.getAttribute("userId");

Document quoteList = builderInterface.getWatchList(userId);

request.setAttribute("quoteList", quoteList);//不需要使用JavaBean包装文档

}

public void doPost(HttpServletRequest request,HttpServletResponse response)

throws ServletException, IOException {

doGet(request, response);

}

}

4.1.2 建造过滤器

我们的过滤器是一个实现了javax.servlet.Filter接口的类。J2EE Web容器使用基于URL的模式匹配调用过滤器和servlet。当一个过滤器和特定的URL模式匹配时,容器调用doFilter方法,它的签名如下:

public void doFilter(ServletRequest request,

ServletResponse response,FilterChain chain)

throws IOException, ServletException;

FilterChain参数是在请求时所有需要被处理的过程的集合,包括servlet、JSP和其他的可能被调用的过滤器。因为我们的过滤器做的是后处理,所以方法doFilter的所有操作之前必须执行FilterChian: chain.doFilter(request,response);

这个实际上通过Web容器调用了WatchListServlet,由它在请求对象中存储我们所需的JDOM文档。然后,我们在doFilter方法中获得此文档。

HttpServletRequest httpRequest = (HttpServletRequest) request;

Document outputDoc = (Document) httpRequest.getAttribute("quoteList");

下一步,我们调用一些辅助方法决定选取哪一个样式用做转换

String outputFormat = getOutputFormat(httpRequest);

String locale = getLocaleString(httpRequest);

String stylesheetPath = getStylesheet(outputFormat, locale);

这些方法的主体在列表9中。它们和第一部分的那些方法很相似。现在我们已经有了XML文档以及使用哪一个样式,我们可以使用JAXP API进行转换了。

TransformerFactory myFactory = TransformerFactory.newInstance();

Transformer myTransformer =

myFactory.newTransformer(new StreamSource(stylesheetPath));

JDOMResult result = new JDOMResult();

myTransformer.transform( new JDOMSource(outputDoc ),result );

现在只剩下利用HttpResponse对象将XSLT的输出写会客户端的逻辑了。

Document resultDoc = result.getDocument();

XMLOutputter xOut = new XMLOutputter();

if (outputFormat.equals("wml"))

response.setContentType("text/vnd.wap.wml");

PrintWriter out = response.getWriter();

xOut.output( resultDoc, out );

列表9提供了完整的XSLTFilter类的实现代码

import javax.servlet.*;

import javax.servlet.http.*;

import java.io.*;

import java.util.*;

import org.jdom.*;

import org.jdom.output.*;

import org.jdom.transform.*;

import javax.xml.transform.*;

import javax.xml.transform.stream.*;

public class XSLTFilter implements Filter {

private FilterConfig filterConfig;

public void init(FilterConfig filterConfig)throws ServletException {

this.filterConfig = filterConfig;

}

public FilterConfig getFilterConfig() {

return this.filterConfig;

}

public void setFilterConfig(FilterConfig filterConfig) {

this.filterConfig = filterConfig;

}

public void doFilter(ServletRequest request,ServletResponse response,

FilterChain chain)throws IOException,ServletException {

try {

chain.doFilter(request,response);

HttpServletRequest httpRequest=(HttpServletRequest) request;

Document outputDoc=(Document) httpRequest.getAttribute("quoteList");

if (outputDoc == null) return;

String outputFormat = getOutputFormat(httpRequest);

String locale = getLocaleString(httpRequest);

String stylesheetPath=getStylesheet(outputFormat, locale);

TransformerFactory myFactory=TransformerFactory.newInstance();

Transformer myTransformer=

myFactory.newTransformer(new StreamSource(stylesheetPath));

JDOMResult result = new JDOMResult();

myTransformer.transform(new JDOMSource( outputDoc ), result );

Document resultDoc = result.getDocument();

XMLOutputter xOut = new XMLOutputter();

if (outputFormat.equals("wml"))

response.setContentType("text/vnd.wap.wml");

PrintWriter out = response.getWriter();

xOut.output( resultDoc, out );

} catch (Exception e) {

System.out.println("Error was:" + e.getMessage());

}

}

private String getOutputFormat(HttpServletRequest request) {

String userAgent = request.getHeader("User-Agent");

// this is where your robust user-agent lookup should happen

if (userAgent.indexOf("UP.Browser") >= 0)

return "wml";

return "html";

}

private String getLocaleString(HttpServletRequest request) {

Enumeration locales = request.getHeaders("Accept-Language");

while (locales.hasMoreElements()) {

String locale = (String) locales.nextElement();

if (locale.equalsIgnoreCase("en_GB"))

return "en_GB";

}

return "en_US";

}

private String getStylesheet(String outputFormat, String locale) {

if (locale.equals("en_US")) {

if (outputFormat.equals("html"))

return "watchlist.html.en_US.xsl";

else

return "watchlist.wml.en_US.xsl";

} else {

if (outputFormat.equals("html"))

return "watchlist.html.en_GB.xsl";

else

return "watchlist.wml.en_GB.xsl";

}

}

public void destroy() {}

}

4.1.3 开发样式

最后,我们需要四个新的,供XSLT使用的XSL样式,提供XML到输出的转换功能。我们需要把前一部分开发的JSP、JavaBean和定制标记转换为四个XSLT转换规则。尽管有许多不同的方法开发XSL样式,最直接的方式就是基于模板方法。XSL样式的这种方式与我们JSP中的模板方式十分类似。

列表10包含XSL样式,它将股票引用列表XML文档转换在为HTML格式,地区是美国。注意这个文件与HTML文件的区别,最主要的是它将整个文档用<xsl:sytlesheet>元素和全局的<xsl:template>元素包装起来。<xsl:stylesheet>元素指明这个文件是一组转换规则,而<xsl:template>元素是应用与XML文档根节点的全局转换规则。对于XSLT开发的分析超出了本文的范围,但它是使用不同方式转换XML的强有力的工具。

列表10 美国地区生成HTML的样式

<?xml version="1.0" encoding="UTF-8"?>

<xsl:stylesheet xmlns:xsl=<http://www.w3.org/1999/XSL/Transform> version="1.0">

<xsl:output method="html" doctype-public="-//W3C//DTD XHTML 1.0 Strict//EN"/>

<xsl:template match="/"> <!-全局转换规则的开始à

<html>

<head><title>Your Watch List</title></head>

<body>

<h1>Your Stock Price Watch List</h1>

<h3>Hello,

<xsl:value-of select="/customer[@first-name]"/>! <!-使用Xpath选取用户名à

</h3>

<h3>

Here are the latest price quotes for

your watch list stocks.

</h3>

<p><i>

Price quotes were obtained at

<xsl:value-of select="/quote-list[@time]"/> <!-从quote-list文档中获得产生时间à

on

<xsl:value-of select="/quote-list[@date]"/> <!-从quote-list文档中获得产生日期à

</i></p>

<table cellpadding="5" cellspacing="0" border="1">

<tr>

<th>Stock Symbol</th>

<th>Company Name</th>

<th>Last Price</th>

<th>Easy Actions</th>

</tr>

<xsl:for-each select="//quote"> <!-迭代文档中所有的quote元素à

<tr>

<td><xsl:value-of select="@symbol"/></td>

<td><xsl:value-of select="@name"/></td>

<td>$$

<xsl:value-of select="./price[@currency=USD]"/>

</td>

<td>

<a href="http://www.exampleco.com/buyStock?symbol=

<xsl:value-of select="@symbol"/>">

buy

</a>

&nbsp;&nbsp;&nbsp;

<a href="http://www.exampleco.com/sellStock?symbol=

<xsl:value-of select="@symbol"/>">

sell

</a>

</td>

</tr>

</xsl:for-each>

</table>

</body>

</html>

</xsl:template>

</xsl:stylesheet>

4.2 分析结果

XSLT架构使我们的例子获得更好模块化和伸缩性。它允许我们创建单一的,整体的表示层,这就能为各种客户类型和地区提供合适的服务。当需要加入新的客户类型和地区时,我们仅仅需要向框架添加额外的样式并且适当的选取它们。通过使样式的选取变得可配置,我们能够减少为了创建单一文档而加入的扩展过程并且更新我们的Web应用配置文件使得过滤器可以被使用。

此架构的另外一个主要的优势是它可以更加有效地划分开发角色。显示页面作者可以实现XSL并且开发者能够集中精力在生成XML的过程上。这些任务能在互相独立的情况下完成。

然而,角色分离的优势面临着自身的挑战。例如,使用XSL开发用户接口比使用标准的HTML要困难的多,并且需要更多网页设计师不熟悉的编程技巧。人们期待着不久的将来图形工具能处理这个问题。实际运用这个架构的另一个挑战是,当前在IT产业中还比较缺乏足够的XSLT技术支持。虽然这将随着时间而改变,但是它已经成为将XML整合到表示层的障碍。

导读

本文的第三部分,将针对文章的例子介绍如何使用XSLT为XML生成PDF文档以及Web发布框架Cocoon。

更多信息

1. <http://www.theserverside.com/>

2. <http://www.javaworld.com/>

本文由starchu1981保留版权,如果需要转贴请写明作者和出处。

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有