nothing
天外飞仙.....
CJSDN高级会员
发贴: 1636
积分: 131
|
于 2003-05-26 00:22
下一代WEB开发模型
发布日期:2003-3-30 发 布 者:51jsp.net 自从Web诞生之日起,Web开发者都试图为如何更好、更快、更加方便的开发出动态Web页面而绞尽了脑汁。从最开始的CGI开始,然后是各种嵌入式脚本语言(PHP、ASP、JSP),接着又在各种脚本语言的基础上发展各种应用框架或是模板语言。
但是如上这些林林总总的解决方案却仍然面临这样一个尴尬的问题,那就是:和传统发展了十几年的桌面IDE集成开发环境相比,这些开发方式仍然显得是那么的原始。WEB开发者不得不面对嵌入式脚本语言、HTML、JavaScript以及SESSION数据库连接等等各式各样混杂在一起的复杂问题,开发者需要学习和使用这些所有的东西。没有什么东西可以帮助开发者有效而又一致的管理它们。光从开发者使用的工具就知道了:看看有多少人还在使用UltraEdit和vi,其它的工具能够带来多大的帮助?更多的时候是在增加麻烦而已。
现在事情似乎有了一丝转机。微软随着ASP.NET推出的一个全新开发模式:基于事件驱动的WebForm。完全类似传统GUI程序的开发方式,通过在功能强大的Visual Studio.NET集成环境的拖放、事件编程,就可以完成大部分WEB开发工作。然后系统自动将其转换到传统WEB运行模式。开发效率得以大大提升。与此同时,在Java的WEB解决方案中也诞生了一项类似的技术――ECHO。同样也是基于事件驱动的开发方式。虽然到目前为止还为没有如Visual Studio.NET一般完善的IDE集成环境。但是在诸如Eclipse中实现它也并非难事。
作为一项全新开发技术,WebForm和ECHO究竟能为Web开发领域带来多大影响现在还很难说。毕竟WEB和传统的GUI开发有着巨大差异。WEB有着无比丰富的页面表现形式,绝非那千篇一律的Windows窗口可以比,开发者在开发不得不考虑到这一点,如何和页面美工配合作出功能完善而又漂亮的页面,绝非易事。还有一个重要的问题那就是WEB的执行效率。显然,复杂的驱动模型带来的是更低的效率。如何平衡好这之间的关系,仍然需要仔细考虑。
在这个专题里,我们列出ASP.Net和JSP中相关的一些技术背景,但是更多是我们希望你能加入到这项新技术的话题讨论中。
Web开发框架中的架构模式比较(一)
发布日期:2003-3-30 发 布 者:51jsp.net 转 自:http://www.csdn.net Web开发框架中的架构模式比较 (Wang Hailong)
目录 Web开发框架中的架构模式比较... 1
目录... 1
序... 1
架构模式Architectural Pattern的基本概念... 2
Server Page (页面内容和逻辑)... 2
ASP.Net的例子... 3
JSP的例子... 5
XSP的例子... 7
页面控件重用... 8
页面内容和表现风格的分离,(XSLT)... 9
页面输入验证 Validation. 12
ASP.Net的例子... 12
Apache Struts的例子... 13
Apache Cocoon的例子... 14
Database driven page. 15
多语言支持... 16
用户身份确认Authentication 和授权Authorization. 17
ASP.Net的服务器端配置文件web.config例子。(节录)... 17
Java web 框架的服务器端配置文件web.xml例子。... 18
SOAP Web Service. 19
序 本文讨论两大类web开发框架——java web框架和微软的.Net框架之间的架构模式的比较。
涉及到的Java web 框架包括:Cocoon,Struts,Axis,Xalan等Apache开源项目,SourceForge.net的开源项目Echo。
涉及到的架构模式Architectural Pattern包括:
Server Page, (页面内容和逻辑)
页面控件重用,(TagLib)
页面内容和表现风格的分离,(XSLT)
页面输入验证 Validation,
Database driven page,
多语言支持,
用户身份确认Authentication 和授权Authorization,
SOAP Web Service。
架构模式Architectural Pattern的基本概念 软件开发中的模式,根据处理问题的粒度不同,从高到低,分为3个层次:
架构模式 Architectural Pattern
设计模式 Design Pattern
实现模式 Implementation Pattern
架构模式 Architectural Pattern 是模式中的最高层次,表示最基本的系统组成,通常提供一组预定义的子系统。比如,用户和文件系统安全策略模型,N-tier结构,组件对象服务,名字服务(Naming Service),服务端Session Keeping and Tracing;再比如,Container模式——在J2EE技术中,web server是servlet和jsp的container,Application Server是EJB的Container;还有,我们熟知的MVC结构也属于架构模式的层次。
设计模式 Design Pattern是模式中的第二层次,用来处理程序设计中反复出现的问题。 例如,[Gang of Four]总结的23个基本设计模式 —— Factory Pattern, Observer Pattern等等。
实现模式 Implementation Pattern 是最低也是最具体的层次,处理具体到编程语言的问题。比如,类名,变量名,函数名的命名规则;异常处理的规则,等等。
本文通过举例(java和.Net)说明web开发框架中的一些架构模式。
Server Page, (页面内容和逻辑)
页面控件重用,(TagLib)
页面内容和表现风格的分离,(XSLT)
页面输入验证 Validation,
Database driven page,
多语言支持,
用户身份确认Authentication 和授权Authorization,
SOAP Web Service。
Web开发框架中的架构模式比较(二)
发布日期:2003-3-30 发 布 者:51jsp.net Server Page (页面内容和逻辑) Server Page技术也可以称为服务端脚本技术。
ASP.Net的服务端脚本语言包括VB.Net,C#.Net,J#.Net,JScript.Net。微软的IIS Web Server支持多种服务端脚本语言,是微软的战略决策之一。当然,既然这些Web服务程序的脚本只能运行在IIS Web Server中,那么也就只能运行在Windows平台上。这里有一点很值得注意,ASP.Net的服务端脚本的用法和JSP(还有后面提到的XSP)大不一样。ASP.Net的服务端脚本和页面元素之间的交互,如同客户端JavaScript一般。难怪,JScript.Net也被包括到服务端脚本之列。这种方式的优越性显而易见,ASP.Net程序员在处理一般的Web界面交互事件时,不用考虑很多HTTP Request – Response Cycle,而JSP(或XSP)程序员必须时时刻刻把这一点记在脑子里。JSP(或XSP)一般只用来动态生成网页,不进行事件处理。Java Web框架通常采取MVC (Model – View - Control)结构,页面交互转换的事件机制在Control部分实现。稍后会举例说明。
JSP的服务端脚本语言包括Java。根据最新推出的JSP2.0规范(可从java.sun.com站点下载),可以看出,JSP力图向XML规范靠拢,并引入Expression Language和大量的TagLib,试图尽量把Java语言代码从JSP页面中清除出去,以解决JSP页面固有的Java Code Pollution问题。JSP页面现在确实好看了许多,更加结构化,更加清晰。但在我看来,不过是拿另一种脚本语言(TagLib和Expression Language)来取代Java Code中的一部分功能罢了,副作用就是要求页面设计或编程人员多掌握一门语言。而且,在实际应用的要求中,要想使这门新语言达到java语言的灵活和强大,不是一件容易的事情,而且可能会令TagLib和Expression Language越来越庞大复杂,难以掌握。稍后会举例说明。
基于java的另一种Server Page技术是Apache Cocoon项目中的XSP技术。(如果需要进一步了解Apache Cocoon和XSP,请访问xml.apache.org站点)。Apache Cocoon项目大量使用SAX/XSLT技术。XSP用来为后续的转换处理管道Pipeline提供XML内容,而且XSP页面本身的生成,也要经过不少XSLT转换。XSP技术中也包括TagLib的概念,称为LogicSheet,表现形式也和JSP中相似,但实现原理完全不同。JSP的TagLib通过Java Tag Extension Class实现,XSP的TagLib(LogicSheet)通过XSLT转换实现。XSP技术的LogicSheet机制能够把页面的内容和逻辑从物理上分离开,分成几个不同的文件。稍后会举例说明。
ASP.Net的例子 例子1。说明服务端脚本调用Page_Load()函数(ASP.Net的内嵌初始化函数)生成页面元素的例子,从.Net框架文档中摘出。
<%@ Page Language="C#" %> <%@ Import Namespace="System.Data" %> <HTML> <script runat="server"> void Page_Load(Object sender, EventArgs e) { DataTable dt = new DataTable(); DataRow dr; dt.Columns.Add(new DataColumn("IntegerValue", typeof(Int32))); dt.Columns.Add(new DataColumn("StringValue", typeof(string))); dt.Columns.Add(new DataColumn("DateTimeValue", typeof(DateTime))); dt.Columns.Add(new DataColumn("BoolValue", typeof(bool))); dt.Columns.Add(new DataColumn("CurrencyValue", typeof(double))); for (int i = 0; i < 9; i++) { dr = dt.NewRow(); dr[0] = i; dr[1] = "Item " + i.ToString(); dr[2] = DateTime.Now; dr[3] = (i % 2 != 0) ? true : false; dr[4] = 1.23 * (i+1); dt.Rows.Add(dr); } MyRepeater.DataSource=new DataView(dt); MyRepeater.DataBind(); } </script> <body> <h3>Data Binding with the HtmlAnchor</h3> <p> <form runat=server> <asp:Repeater id="MyRepeater" runat="server"> <ItemTemplate> Link for <a href=''<%# DataBinder.Eval(Container, "DataItem.StringValue", "detailspage.aspx?id={0}") %>'' runat="server"> <%# DataBinder.Eval(Container, "DataItem.StringValue") %> </a> <p> </ItemTemplate> </asp:Repeater> </form> </body> </HTML>
例子2。说明web界面中的事件响应机制。并说明了如何在Web 窗体页中注册和声明自定义服务器控件。该控件的标记前缀是 Custom,它创建的类出现在 CustomWebFormsControls 命名空间中。它是使用 Custom:MyButton 标记在页的正文中声明的。我们可以看到TagLib的影子。
<%@ Register TagPrefix="Custom" Namespace="CustomWebFormsControls" Assembly="CustomControls" %>
<HTML>
<script language="C#" runat=server>
private void Button_Click(Object sender, EventArgs e) {
TextBox.BackColor = System.Drawing.Color.Green;
TextBox.Text = "You clicked the button";
}
</script>
<body>
<form method="POST" action="MyButton.aspx" runat=server>
Here is our custom button.<br>
<Custom:MyButton id="Button" OnClick="Button_Click"
runat=server/>
<br>
<br>
<asp:TextBox id = "TextBox" Text = "Click the button"
Width = "200" BackColor "Cyan" runat=server/>
<br>
</form>
</body>
</HTML>
JSP的例子 例子1。
下面的文件是Apache Struts项目的struts-config.xml配置文件例子,从struts用户文档中摘录。Apache Struts采用MVC (Model – View - Control)结构。struts-config.xml是重要的Control部分的配置文件,定义页面之间的交互,相当于用户界面的事件机制。
<struts-config>
<form-beans>
<form-bean
name="logonForm"
type="org.apache.struts.webapp.example.LogonForm" />
</form-beans>
<global-forwards
type="org.apache.struts.action.ActionForward" />
<forward
name="logon"
path="/logon.jsp"
redirect="false" />
</global-forwards>
<action-mappings>
<action
path="/logon"
type="org.apache.struts.webapp.example.LogonAction"
name="logonForm"
scope="request"
input="/logon.jsp"
unknown="false"
validate="true" />
</action-mappings>
</struts-config>
例子2。下面的JSP例子从JSP2.0规范中摘录,说明TagLib和Expression Language在JSP中看起来是什么样子。注意,<%@ taglib prefix=”c” uri=”http://java.sun.com/jstl/core” %>,其中,JSTL表示JSP Standard Tag Library。${x}和${result}是Expression Language的用法。
<%-- page.jsp --%>
<%@ taglib prefix=”c” uri=”http://java.sun.com/jstl/core” %>
<%@ taglib prefix=”my” tagdir=”/WEB-INF/tags” %>
<c:set var=”x” value=”1”/>
${x} <%-- (x == 1) --%>
<my:example var=”x”>
${x} <%-- (x == 2) --%>
${result} <%-- (result == null) --%>
<c:set var=”x” value=”3”/>
<c:set var=”result” value=”invisible”/>
</my:example>
${x} <%-- (x == 4) --%>
${result} <%-- (result == ‘invisible’) --%>
<%-- /WEB-INF/tags/example.tag --%>
<%@ attribute name=”var” required=”true” %>
<%@ variable alias=”result” name-from-attribute=”var” scope=”AT_BEGIN” %>
<%@ taglib prefix=”c” uri=”http://java.sun.com/jstl/core” %>
${x} <%-- (x == null) --%>
${result} <%-- (result == 1) --%>
<c:set var=”x” value=”ignored”/>
<c:set var=”result” value=”2”/>
<jsp:doBody/>
${x} <%-- (x == ‘ignored’) --%>
${result} <%-- (result == 3) --%>
<c:set var=”x” value=”still_ignored”/>
<c:set var=”result” value=”4”/>
XSP的例子 下面的例子从Apache Cocoon项目的用户文档中摘录。说明LogicSheet在XSP中的使用。LogicSheet在XSP的作用,相当于TagLib在JSP中的作用。JSP的TagLib通过Java Tag Extension Class实现,XSP的TagLib(LogicSheet)通过XSLT转换实现。
文件1是XSP文件,greeting3.xml;文件2是LogicSheet文件,logicsheet.greeting.xsl;生成的结果是文件3,greeting.xml。
文件1 —— greeting3.xml
<?xml version="1.0"?>
<xsp:page
xmlns:xsp="http://apache.org/xsp"
xmlns:greeting="http://duke.edu/tutorial/greeting">
<greeting>
<greeting:hello-world/>
</greeting>
</xsp:page>
文件2 —— logicsheet.greeting.xsl
<?xml version="1.0"?>
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xsp="http://apache.org/xsp"
xmlns:greeting="http://duke.edu/tutorial/greeting"
version="1.0">
<xsl:template match="xsp:page">
<xsl:copy>
<xsl:apply-templates select="@*"/>
<xsl:apply-templates/>
</xsl:copy>
</xsl:template>
<xsl:template match="greeting:hello-world">
<!-- more complex XSLT is possible here as well -->
<xsp:logic>
// this could be arbitrarily complex Java code, JDBC queries, etc.
String msg = "Hello, world!";
</xsp:logic>
<xsp:expr>msg</xsp:expr>
</xsl:template>
<!-- This template simply copies stuff that doesn''t match other -->
<!-- templates and applies templates to any children. -->
<xsl:template match="@*|node()" priority="-1">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
文件3 —— 结果 greeting.xml
<?xml version="1.0"?>
<greeting>Hello, world!</greeting>
注意,logicsheet.greeting.xsl文件,java代码嵌在<xsp:logic>和</xsp:logic>中间。XSP或者LogicSheet文件中的java代码中能够很自然地嵌入xml元素。而在JSP页面中,java代码和HTML元素交织在一起。
页面控件重用 正如前面所述,JSP和XSP中的页面控件重用,主要通过TagLib机制对html元素进行封装,实现页面控件的重用。。比如,Struts重定义了几乎所有html元素标签;Sun公司提出了SP Standard Tag Lib标准;Apache Jakarta Taglibs项目提供了括JSTL在内的多类TagLib的实现。Apache Cocoon项目提供了一些内嵌的LogicSheet —— Request, Form等。用户自定义控件,需要继承实现Java Tag Extension Class ——javax.servlet.jsp.tagext.TagSupport 。
有些java web框架走向另一个方向。SourceForge.net的java开源项目Echo是一个典型的例子。Echo不使用JSP,甚至不使用html,只使用Servlet。Echo提供了一组类似于Swing的接口,程序员可以象开发Applet程序一样写Web程序。Echo框架是事件驱动的框架。程序员书写的类Swing控件,会被Echo框架翻译成对应的html元素。用户自定义控件,只需要按照类Swing接口,生成自定义的控件类即可。
ASP.Net的页面控件重用方式和TagLib机制类似。同时,ASP.Net又是事件驱动的框架,这一点和Echo框架类似。ASP.Net似乎找到了一个比较好的平衡点。ASP.Net定义了两组服务器控件 —— HTML服务器控件,和Web服务器控件。HTML服务器控件封装了简单的html页面元素,比如,form,button,input等;Web服务器控件封装了更为复杂多样的页面控件,比如,asp:Calendar,asp:CheckBoxList等。HTML服务器控件在页面中的书写方法不带前缀,几乎和普通html页面元素一样,只是扩展了一些属性。Web服务器控件带有asp前缀。可以把HTML服务器控件类比为基本的TagLib,可以把Web服务器控件类比为扩展的TagLib。用户自定义控件需要继承System.Web.UI.WebControls.WebControl或者System.Web.UI. Control。并按照类似于TagLib声明的格式,写在页面文件中:<%@ Register TagPrefix= "myNameSpace" TagName="myUserControl" Src="userControl1.ascx" %>
Web开发框架中的架构模式比较(三)
发布日期:2003-3-30 发 布 者:51jsp.net 页面内容和表现风格的分离,(XSLT) 页面内容和表现风格分离的第一步,是CSS风格文件和HTML页面的分离,但是,HTML的页面内容和显示元素还是紧紧捆绑在一起。XML推广之后,XSLT也大行其道,大量地应用在web发布系统中。ASP.Net和java web框架都在朝这个方向走,只是java web框架走得更快,更远。下面进行说明。
在处理XSLT时,SAX接口要比DOM接口快得多,而且几乎不占据内存空间。令人不安的是,.Net框架到现在还没有提供SAX接口。微软提供了一套MSXML SDK,其中包含了基于COM组件的SAX实现,并提供了在VB和VC中应用的实例。MSXML SAX的VC用例中,需要包含头文件msxml2.h。这就是说,.Net框架无法以一种自然的方式调用MSXML SAX。还有,.Net框架的XSLT是如何实现的,即,System.Xml.Xsl.XslTransform是用什么方式实现的,是调用SAX接口,还是DOM接口。如何使用.Net框架组成一条XSLT的处理管道?我也找不到方法。也没有发现这方面的例子。
Apache Xerce项目支持XML处理,提供Java和C++版本,并提供了调用MSXML的封装;Apache Xalan项目支持XSLT处理;Apache Cocoon2.0,使用SAX接口,组成XSLT的处理管道。
Apache Xalan项目的一个例子文件UseXMLFilters.java UseXMLFilters.java。(节录,文件头部分省略)
public class UseXMLFilters
{
public static void main(String[] args)
throws TransformerException, TransformerConfigurationException,
SAXException, IOException
{
// Instantiate a TransformerFactory.
TransformerFactory tFactory = TransformerFactory.newInstance();
// Determine whether the TransformerFactory supports The use uf SAXSource
// and SAXResult
if (tFactory.getFeature(SAXSource.FEATURE) && tFactory.getFeature(SAXResult.FEATURE))
{
// Cast the TransformerFactory to SAXTransformerFactory.
SAXTransformerFactory saxTFactory = ((SAXTransformerFactory) tFactory);
// Create an XMLFilter for each stylesheet.
XMLFilter xmlFilter1 = saxTFactory.newXMLFilter(new StreamSource("foo1.xsl"));
XMLFilter xmlFilter2 = saxTFactory.newXMLFilter(new StreamSource("foo2.xsl"));
XMLFilter xmlFilter3 = saxTFactory.newXMLFilter(new StreamSource("foo3.xsl"));
// Create an XMLReader.
XMLReader reader = XMLReaderFactory.createXMLReader();
// xmlFilter1 uses the XMLReader as its reader.
xmlFilter1.setParent(reader);
// xmlFilter2 uses xmlFilter1 as its reader.
xmlFilter2.setParent(xmlFilter1);
// xmlFilter3 uses xmlFilter2 as its reader.
xmlFilter3.setParent(xmlFilter2);
// xmlFilter3 outputs SAX events to the serializer.
Serializer serializer = SerializerFactory.getSerializer
(OutputProperties.getDefaultMethodProperties("xml"));
serializer.setOutputStream(System.out);
xmlFilter3.setContentHandler(serializer.asContentHandler());
// Perform the series of transformations as follows:
// - transformer3 gets its parent (transformer2) as the XMLReader/XMLFilter
// and calls transformer2.parse(new InputSource("foo.xml")).
// - transformer2 gets its parent (transformer1) as the XMLReader/XMLFilter
// and calls transformer1.parse(new InputSource("foo.xml")).
// - transformer1 gets its parent (reader, a SAXParser) as the XMLReader
// and calls reader.parse(new InputSource("foo.xml")).
// - reader parses the XML document and sends the SAX parse events to transformer1,
// which performs transformation 1 and sends the output to transformer2.
// - transformer2 parses the transformation 1 output, performs transformation 2, and
// sends the output to transformer3.
// - transformer3 parses the transformation 2 output, performs transformation 3,
// and sends the output to the serializer.
xmlFilter3.parse(new InputSource("foo.xml"));
}
}
}
Apache Cocoon项目的一个配置文件例子sitemap.xmap Apache Cocoon项目的sitemap.xmap定义了XSLT处理管道。见下例中的<map:handle-errors>部分,错误信息经过两次XSLT处理," error2document.xsl" 和"apache.xsl"。
/sample/tutorial/sitemap.xmap (节录,无关部分省略)
…
<map:pipelines>
<map:pipeline>
<map:match pattern="*-dept.xml">
<map:act set="process">
<map:parameter name="descriptor" value="context://tutorial/docs/department-form.xml"/>
<map:generate type="serverpages" src="docs/confirm-dept.xsp"/>
<map:serialize type="xml"/>
</map:act>
<map:generate type="serverpages" src="docs/{1}-dept.xsp"/>
<map:serialize type="xml"/>
</map:match>
...
<map:handle-errors>
<map:transform src="stylesheets/system/error2document.xsl"/>
<map:transform src="stylesheets/apache.xsl"/>
<map:serialize status-code="500"/>
</map:handle-errors>
</map:pipeline>
...
</map:pipelines>
ASP.Net的Xml Web控件例子 下面的示例从.Net框架文当中摘录,说明如何使用 Xml 控件通过示例 XSL 转换文件来显示示例 XML 文件。示例 XML 文件名为 People.xml,示例 XSL 转换文件名为 Peopletable. xsl。可以看到,asp:Xml控间只能进行一步XSLT转换。
<html>
<body>
<h3>Xml Example</h3>
<form runat="server">
<asp:Xml id="xml1"
DocumentSource="people.xml"
TransformSource="peopletable.xsl"
runat="server" />
</form>
</body>
</html>
Web开发框架中的架构模式比较(四)
发布日期:2003-3-30 发 布 者:51jsp.net 页面输入验证 Validation ASP.Net提供验证功能的服务器控件: CompareValidator验证两个控件输入之间的比较,RangeValidator检查用户的输入是否在指定的上限和下限之间;RegularExpressionValidator 控件检查输入是否与某个正则表达式所定义的模式相匹配(社会保障号、电子邮件地址、电话号码、邮政编码等);RequiredFieldValidator 控件确保用户不会略过某个输入;CustomValidator 控件创建自定义服务器和客户端验证代码。稍后会举例说明。
Java web框架通常会把验证规则提出来,放在一个验证规则文件里。Apache Struts提供验证两种方式。一种是重载org.apache.struts.action.ActionForm类的validate方法,一种是定义Validator Plug-In文件,validator-rules.xml。Apache Cocoon也提供了类似的验证规则文件。稍后举例说明。
ASP.Net的例子 摘自.Net框架文档,其余部分省略,只保留了关于RegularExpressionValidator的部分。本例中,id为RegularExpressionValidator1的控件的ControlToValidate属性为TextBox1,所以,RegularExpressionValidator1负责验证TextBox1是否符合正则表达式"\d{5}"——5个数字。
<td> <asp:TextBox id="TextBox1" runat="server"/> </td> <td> <asp:RegularExpressionValidator id="RegularExpressionValidator1" ControlToValidate="TextBox1" ValidationExpression="\d{5}" Display="Static" EnableClientScript="false" ErrorMessage="Zip code must be 5 numeric digits" runat="server"/> </td>
Apache Struts的例子 下面的例子从Apache Struts的用户文档中摘录出来。Apache Struts提供的Validation机制非常强大,能够实现基于其它输入域的条件验证,即,如果另外一个或几个输入域都符合相应的情况,那么,验证当前域是否符合某种条件。
<form name="dependentlistForm">
<field
property="firstName" indexedListProperty="dependents"
depends="requiredif">
<arg0 key="dependentlistForm.firstName.label"/>
<var>
<var-name>field[0]</var-name>
<var-value>lastName</var-value>
</var>
<var>
<var-name>field-indexed[0]</var-name>
<var-value>true</var-value>
</var>
<var>
<var-name>field-test[0]</var-name>
<var-value>NOTNULL</var-value>
</var>
</field>
<field
property="dob"
indexedListProperty="dependents"
depends="requiredif,date">
<arg0 key="dependentlistForm.dob.label"/>
<var>
<var-name>field[0]</var-name>
<var-value>lastName</var-value>
</var>
<var>
<var-name>field-indexed[0]</var-name>
<var-value>true</var-value>
</var>
<var>
<var-name>field-test[0]</var-name>
<var-value>NOTNULL</var-value>
</var>
</field>
<field
property="coverageType"
indexedListProperty="dependents"
depends="requiredif">
<arg0 key="dependentlistForm.coverageType.label"/>
<var>
<var-name>field[0]</var-name>
<var-value>lastName</var-value>
</var>
<var>
<var-name>field-indexed[0]</var-name>
<var-value>true</var-value>
</var>
<var>
<var-name>field-test[0]</var-name>
<var-value>NOTNULL</var-value>
</var>
<var>
<var-name>field[1]</var-name>
<var-value>insureDependents</var-value>
</var>
<var>
<var-name>field-test[1]</var-name>
<var-value>EQUAL</var-value>
</var>
<var>
<var-name>field-value[1]</var-name>
<var-value>true</var-value>
</var>
<var>
<var-name>field-join</var-name>
<var-value>AND</var-value>
</var>
</field>
</form>
Apache Cocoon的例子 下面的例子是Apache Cocoon的教学程序中的文件。对id和name两个域进行验证。同时,这个文件定义了页面元素和数据库数据之间的绑定。下一节就要阐述这个问题。
<root>
<parameter name="id" type="long" nullable="no"/>
<parameter name="name" type="string" min-len="5" max-len="64"/>
<constraint-set name="update">
<validate name="name"/>
<validate name="id"/>
</constraint-set>
<constraint-set name="add">
<validate name="name"/>
</constraint-set>
<connection>personnel</connection>
<table name="department">
<keys>
<key param="id" dbcol="id" type="int" mode="manual"/>
</keys>
<values>
<value param="name" dbcol="name" type="string"/>
</values>
</table>
</root>
Database Driven Page 正如上一节最后一个例子(Apache Cocoon)所示,很多web开发框架提供页面元素和数据库字段的直接绑定。
.NET 框架包含三个便于显示大量数据的控件:Repeater 控件、DataList 控件和 DataGrid 控件。这三个控件都使用相似的数据绑定过程,绑定到DataSet、SqlDataReader或DataView。下面的代码示例从.Net框架文档摘录,显示如何将 SQL 数据库查询返回的 DataSet 绑定到 DataGrid 控件。
<%@ Import Namespace="System.Data" %> <%@ Import Namespace="System.Data.SqlClient" %> <HTML> <script language="C#" runat="server"> protected void Page_Load(Object Src, EventArgs E) { // Create a connection to the "pubs" SQL database located on the // local computer. SqlConnection myConnection = new SqlConnection("server=localhost;" + "database=pubs;Trusted_Connection=Yes"); // Connect to the SQL database using a SQL SELECT query to get all // the data from the "Authors" table. SqlDataAdapter myCommand = new SqlDataAdapter("SELECT " + " * FROM Authors", myConnection); // Create and fill a DataSet. DataSet ds = new DataSet(); myCommand.Fill(ds); // Bind MyDataGrid to the DataSet. MyDataGrid is the ID for the // DataGrid control in the HTML section. DataView source = new DataView(ds.Tables[0]); MyDataGrid.DataSource = source ; MyDataGrid.DataBind(); } </script> <body> <%-- Display the DataGrid information in the body of the page. --%> <h3><font face="Verdana">Simple SELECT to a DataGrid Control </font></h3> <%-- Display the data in a DataGrid. --%> <ASP:DataGrid id="MyDataGrid" runat="server" Width="700" BackColor="#ccccff" BorderColor="black" ShowFooter="false" CellPadding=3 CellSpacing="0" Font-Name="Verdana" Font-Size="8pt" HeaderStyle-BackColor="#aaaadd" EnableViewState="false" /> </body> </HTML> 多语言支持 多语言支持策略基本上都采取一种类似于查多本字典的模式。先举一个类比例子来说明,比如,我们有英英字典,英汉字典,英德字典,英法字典,对于一个英文单词,每本字典都有对应语言的单词,满足不同语言的用户的需要。我们把要查的英文单词称为key,所有的字典称为资源文件resource file,查出来的对应语言的单词,就是应该显示给用户的内容。、
上述模式简单而常见,不再列出例子代码,下面只进行简单的说明。
.Net框架通过一个重要的资源管理类System.Resources.ResourceManager,来管理在应用程序中使用的不同特定于区域性的资源。调用方可使用 GetObject 和 GetString 两种方法访问特定区域性的资源。这两个方法的参数都包括一个key,和一个本地语言信息。.Net的资源文件后缀是DLL。
Apache Struts项目的类org.apache.struts.util.MessageResources的getMessage方法提供了类似的功能。Apache Struts项目提供了一个扩展的HTML Tag —— Message,也起着多语言支持、本地化的作用。Struts的资源文件后缀是properties,格式按照java properties文件的格式。
Apache Cocoon项目提供了一类称为i18n的Transformer,用来实现多语言支持。常用的标记如<i18n:text>和<i18n:param>。Cocoon的多语言支持策略和前面所说的一样,应用方法也类似,但是实现方式却不一样——Cocoon采用XSLT实现多语言支持。Cocoon的资源文件后缀是xml,格式按照xml格式。看来,把xml贯彻始终者,非Cocoon莫属。
Web开发框架中的架构模式比较(五)
发布日期:2003-3-30 发 布 者:51jsp.net 用户身份确认Authentication 和授权Authorization 当web用户访问web服务器上的受到保护的资源时,通常要经过两个步骤。(从.Net框架文档摘录)
1.用户身份确认Authentication
确保用户不是假冒的。应用程序获取用户的凭据(各种形式的标识,如用户名和密码)并通过某些授权机构验证那些凭据。如果这些凭据有效,则提交这些凭据的实体被视为经过身份验证的标识。
2.授权Authorization
通过对已验证身份授予或拒绝特定权限来限制访问权限。
ASP.Net和java web框架的资源保护策略都遵循这样的模型:对应于被保护的资源,定义一组角色,用户,和允许的操作。操作在java web框架中称为http-method,在ASP.Net中称为Verb,都表示HTTP GET,HTTP POST等HTTP方法。
根据servlet2.4规范,java web框架的网页的login form应该按照下例书写。注意,form的action属性的值应该为j_security_check。
<form method=”POST” action=”j_security_check”>
<input type=”text” name=”j_username”>
<input type=”password” name=”j_password”>
</form>
ASP.Net的服务器端配置文件web.config例子。(节录) 下面的例子从.Net框架文档中摘录出来。
<authentication mode="forms">
<forms forms="401kApp"
loginurl="/login.aspx"
decryptionkey="1!#$$*13^">
<credentials passwordFormat=SHA1>
<user name="Kim" password="9611E4F94EC4972D5A537EA28C69F89AD28E5B36"/>
<user name="John" password="BA7157A99DFE9DD70A94D89844A4B4993B10168F"/>
</credentials>
</forms>
</authentication>
…
<authorization> <allow users="John" /> <deny users="*" /> </authorization> …
<authorization> <allow verb="GET" users="*" /> <allow verb="POST" users="Kim" /> <deny verb="POST" users="*" /> </authorization> …
Java web 框架的服务器端配置文件web.xml例子。 下例从servlet2.4规范中摘录。其中的< security-role >和< security-constraint >部分中定义了受保护资源对应的角色,用户,和允许的操作。
<?xml version="1.0" encoding="ISO-8859-1"?>
<web-app xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://
java.sun.com/xml/ns/j2ee/web-app_2_4.xsd" version=”2.4”>
<display-name>A Secure Application</display-name>
<servlet>
<servlet-name>catalog</servlet-name>
<servlet-class>com.mycorp.CatalogServlet
</servlet-class>
<init-param>
<param-name>catalog</param-name>
<param-value>Spring</param-value>
</init-param>
<security-role-ref>
<role-name>MGR</role-name>
<!-- role name used in code -->
<role-link>manager</role-link>
</security-role-ref>
</servlet>
<security-role>
<role-name>manager</role-name>
</security-role>
<servlet-mapping>
<servlet-name>catalog</servlet-name>
<url-pattern>/catalog/*</url-pattern>
</servlet-mapping>
<security-constraint>
<web-resource-collection>
<web-resource-name>SalesInfo
</web-resource-name>
<url-pattern>/salesinfo/*</url-pattern>
<http-method>GET</http-method>
<http-method>POST</http-method>
</web-resource-collection>
<auth-constraint>
<role-name>manager</role-name>
</auth-constraint>
<user-data-constraint>
<transport-guarantee>CONFIDENTIAL
</transport-guarantee>
</user-data-constraint>
</security-constraint>
</web-app>
SOAP Web Service .Net框架和Apache Axis项目都提供了Web Service的SOAP实现。采用的基本模式如下。
通过XML序列化实现SOAP XML数据到应用程序对象的绑定;XML序列化(和反序列化)发生在服务端和客户段;XML数据和应用程序对象Object的映射规则为,Object映射为一个XML元素,Object的“属性”(property)成员映射为该XML元素的子元素。
Java和C# 都支持Reflection机制,能够在运行时判断Object的类型。但有些细微的差别:Java对象的“属性”(property)并不是一种类型,而是一种符合getXXX,setXXX形式的约定;C#对象的“属性”(property)是在类内部声明的一种类型;还有,C#支持Attribute,比如,[SoapElement]、[XmlElement]、[WebMethod]、[SoapRpcMethod]等属性。所以,C#对象的XML序列化定义更加严格一些。
另外,两种语言的集合类也有差别,对于某些特殊的集合类,如hashtable,会有不兼容的情况,所以,最好发送数组类型,以保证不同语言开发的SOAP Web Service能够相互使用。
SOAP支持几种数组类型,其中有两种数组类型 —— 多维数组和复合数组,这里说明一下。多维数组是指如 3 * 4 之类的3行4列的整齐数组,C# 语言支持这种多维数组,java语言不支持这种多维数组;复合数组是指数组的数组,即数组的元素也可以是属组,C# 语言和java语言都支持这种复合数组。不过,复合数组也可以用来表示多维数组,比如复合数组的元素个数为3,元素类型为大小为4的数组,就可以用来表示3 * 4 之类的3行4列的整齐数组。
躲得过的怪物,躲不过的刺激
|