﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>BlogJava-Sung in Blog-文章分类-Thinking in Design</title><link>http://www.blogjava.net/qq13367612/category/3975.html</link><description>&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font class="subhead" size=3&gt;&lt;b&gt;一些技术文章 &amp; 一些生活杂碎&lt;/b&gt;&lt;/font&gt;</description><language>zh-cn</language><lastBuildDate>Wed, 28 Feb 2007 09:14:51 GMT</lastBuildDate><pubDate>Wed, 28 Feb 2007 09:14:51 GMT</pubDate><ttl>60</ttl><item><title>面向切面(AOP)与面向对象(OOP)</title><link>http://www.blogjava.net/qq13367612/articles/18131.html</link><dc:creator>Sung</dc:creator><author>Sung</author><pubDate>Fri, 04 Nov 2005 05:57:00 GMT</pubDate><guid>http://www.blogjava.net/qq13367612/articles/18131.html</guid><wfw:comment>http://www.blogjava.net/qq13367612/comments/18131.html</wfw:comment><comments>http://www.blogjava.net/qq13367612/articles/18131.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/qq13367612/comments/commentRss/18131.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/qq13367612/services/trackbacks/18131.html</trackback:ping><description><![CDATA[首先你要明确的一点，AOP和OOP是两种不同的认识事物的角度，并不是说有了AOP就不要用OOP。AOP所关注的是传统OOP不能优雅解决的问题。(程序员通常都是完美主义者，当解决某个问题不优雅的时候，那就意味着不完美。)下面将就一个简单的例子来说明他们到底如何的不同。 <BR><BR>作为一个使用OOP多年的人来说，当我听说AOP可以解决一些OOP一直都不能优雅地解决的问题时，我觉得应该去探个究竟了。对两种技术的比较最能给我们实际应用提供见解。这里我设计了一个例子:一个OOP应用，其中某些方面适合使用AOP。 <BR><BR>本文展示了一个简单的例子。一开始介绍了问题域，然后分别给出OOP与AOP的解决方案。后者使用了JDK5.0，JUnit，和AspectWerkz。最后说明如何编写代码。读完本文后，我希望你能知道AOP到底是什么，解决什么样的问题。(由于作者在后面AOP的例子中使用了Java5。0的批注(Annotation)，建议读者先有所了解) <BR><BR>问题域描述 <BR><BR>一个软件公司雇佣一个程序员，指定给他一个业务部门并要求他随时向经理报告。当团队成员完成他们的目标时，经理会给他们相应的奖金。公司所需要的方案必须能够增加一个新的雇员并给当前的员工增加奖金。为了方便，我们用CSV文件存储数据。 <BR><BR>
<CENTER><IMG src="http://tech.ccidnet.com/col/attachment/2005/10/515869.jpg"></CENTER><BR><BR>
<CENTER>图1 解决方案模型</CENTER><BR><BR>类Manager(经理)继承自类Employee，包含一个额外的属性，Managing Project。一个部门可能包含很多员工。多个部门构成了公司。暂不考虑公司这样的一个类，因为它在问题域之外。 <BR><BR>解决方案设计 <BR><BR>以下流程图描述了解决方案设计。 <BR><BR>
<CENTER><IMG src="http://tech.ccidnet.com/col/attachment/2005/10/515871.gif"></CENTER><BR><BR>
<CENTER>图2 对象之间的交互(增加一个新的员工，指派给他一个部门和经理)</CENTER><BR><BR>出于简单的考虑，本文只关注必需的细节。当然你也可以深入代码得到你想要的其他信息。 <BR><BR>[link]http://www.devx.com/assets/sourcecode/13172.zip[/link] <BR><BR>EmployeeServiceTestCase，一个JUnit测试用例，模拟一个最终用户，创建新员工记录，指派部门和经理。它获取所有可用的部门和经理数据并显示在图形界面上。 <BR><BR>为了实例化域对象BusinessUnit和Manager，获得的记录将传递给工厂类。之后，通过给EmployeeService传递一个引用来创建一个Employee对象。 <BR><BR>这个服务类使用EmployeeFactory创建对象，并把这个对象传给EmployeeRepository 来进行持久化操作。 <BR><BR>应用程序中需要面向哪些"切面" <BR><BR>到目前为止，对模型和设计的讨论还限于一个较抽象的层面。现在，我转向这个应用的其他方面 - 这对理解AOP的价值至关重要。 <BR><BR>操作所需的资源<BR><BR><BR><BR><BR><BR><BR><BR><BR><BR><BR><BR><BR><BR><BR><BR><BR><BR><BR><BR>
<CENTER><CCID_NOBR>
<TABLE cellSpacing=0 borderColorDark=#ffffff cellPadding=2 width=400 align=center borderColorLight=black border=1>
<TBODY>
<TR>
<TD class=code style="FONT-SIZE: 9pt" bgColor=#e6e6e6><PRE><CCID_CODE>public static Set findAllBusinessUnits() 
throws RepositoryException { 
Set businessUnits = new HashSet(); 
try { 
FileReader businessUnitFile = null; 
BufferedReader bufferedBusinessUnitFile = null; 
try { 
businessUnitFile = new FileReader(FILE_NAME); 
bufferedBusinessUnitFile = 
new BufferedReader(businessUnitFile); 
String businessUnitRecord; 
while((businessUnitRecord =
bufferedBusinessUnitFile.readLine()) != null)
{ 
BusinessUnit businessUnit = BusinessUnitFactory.
createBusinessUnit(businessUnitRecord); 
businessUnits。add(businessUnit); 
} 
} finally 
{ 
if(bufferedBusinessUnitFile != null) 
{ 
bufferedBusinessUnitFile。close(); 
} 
if(businessUnitFile != null)
{ 
businessUnitFile。close(); 
} 
} 
} catch(IOException ioe) 
{ 
String message = 
"IOError. Unable to find Business Unit records"; 
logger.log(SEVERE， message， ioe); 
throw new RepositoryException(message， ioe); 
} 

logger。log(INFO，
"Manager Records returned:" 
+ businessUnits.size()); 
return businessUnits; 
}</CCID_CODE></PRE></TD></TR></TBODY></TABLE></CCID_NOBR></CENTER><BR><BR>上面的代码通过FileReader和BUfferedReader来读取CSV文件中的业务数据。应用程序重复地从资源文件中取得数据然后在操作完成后释放。我们会发现:去掉程序的这两个"切面"将提高代码的可读性并达到一个更好的设计，因为去掉这些"多余"的东西，剩下的代码才是这个方法真正的精髓。 <BR><BR>这个方法的作用是读取业务单位数据。所以不应该也不需要去知道"如何获取和释放资源以及这个过程中出现的异常"这个"切面"。同样地，使用AOP处理异常也变得不同。(后面将详细介绍) <BR><BR>持久层 <BR><BR>传统的OOP使用仓库类(repository classes)来打理应用程序的持久层。即: <BR><BR>
<CENTER><CCID_NOBR>
<TABLE cellSpacing=0 borderColorDark=#ffffff cellPadding=2 width=400 align=center borderColorLight=black border=1>
<TBODY>
<TR>
<TD class=code style="FONT-SIZE: 9pt" bgColor=#e6e6e6><PRE><CCID_CODE>public class EmployeeRepository 
{ 

public static void createEmployee
(Employee employee) 
throws RepositoryException 
{ 
//使用print writer把数据放入csv文件 
} 

public static String 
findEmployeeRecordById(String id) 
throws RepositoryException 
{ 
//使用file reader来获得指定id的员工数据 
} 

public static Employee 
findEmployeeById(String id) 
throws RepositoryException 
{ 
//使用该方法获取员工数据，
Employee对象由工厂类创建 
} 

public static void 
updateEmployee(Employee employee) 
{ 
//更新员工数据 
} 
}</CCID_CODE></PRE></TD></TR></TBODY></TABLE></CCID_NOBR></CENTER><BR><BR>类EmployeeService 使用一个仓库类给应用中相关雇员提供服务，在一个企业应用中，从域模型(domain model)中去掉持久层代码是一种设计上的改进。模型设计者和程序员就可以关注各自的业务逻辑和持久层处理。后面你将会看到如何通过AOP来达到这样的效果。 <BR><BR>日志 <BR><BR>删除用于调试的日志代码将会极大地改进代码的可读性。考虑下面的代码片断: <BR><BR>
<CENTER><CCID_NOBR>
<TABLE cellSpacing=0 borderColorDark=#ffffff cellPadding=2 width=400 align=center borderColorLight=black border=1>
<TBODY>
<TR>
<TD class=code style="FONT-SIZE: 9pt" bgColor=#e6e6e6><PRE><CCID_CODE>public Employee 
createEmployee(String name， 
String contactNumber， 
BusinessUnit businessUnit， 
Manager manager) 
throws EmployeeServiceException 
{ 
String id = createNewEmployeeId(); 
Employee employee = 
EmployeeFactory。createEmployee
(id， name， contactNumber，
businessUnit， manager); 
try { 
EmployeeRepository.createEmployee(employee); 
} catch(RepositoryException re) 
{ 
String message = 
"Created employee successfully:" 
+ employee; 
logger。log(SEVERE， message); 
throw new EmployeeServiceException
(message， re); 
} 
logger。log(INFO， 
"Created employee successfully:"
+ employee); 
return employee; 
}</CCID_CODE></PRE></TD></TR></TBODY></TABLE></CCID_NOBR></CENTER><BR><BR>上面的代码里包含了一个致命错误和一个成功信息。输出日志这一"切面"同样可以移到业务模型外独立实现。 <BR><BR>异常处理 <BR><BR>异常处理的例子我这里不再赘述，但这节已经通过上面的代码讨论了潜在的问题。当你调用EmployeeRepository对象的createEmployee方法时，你可能会得到一个RepositoryException异常。 <BR><BR>传统的解决方法是，在这个类中处理。另一种方法是，当RepositoryException异常被抛出时createEmployee 方法返回null，catch块中的其他逻辑可以在类外处理这一错误。 <BR><BR>错误处理在不同的情况中也会不同。但是，通过AOP可以区分开每种情况。<BR><BR><BR><BR><BR><BR><BR><BR><BR><BR>
<CENTER><IMG src="http://tech.ccidnet.com/col/attachment/2005/10/515873.gif"></CENTER><BR><BR>
<CENTER>图3</CENTER><BR><BR>图3中描述了AOP方法的设计以及在一个更抽象的层次上类间的交互。你可以通过对比图1和图3来更好地理解AOP。程序的目的是通过BusinessUnit对象读取CSV文件中的记录然后填入类BusinessUnitService中的map。 <BR><BR>使用AOP来填充这个map有点类似后门(backdoor)方法 -- 控制被委派给BusinessUnit 来读取存储介质中的记录。 <BR><BR>AOP就是定义一些切入点(pointcut)和处理方法(advice)。一个"切入点"是源代码中一个执行点。前面的例子定义了一个"切入点"--类BusinessUnitService中的findBusinessUnits方法。一个"处理方法"顾名思义就是当执行到某个"切入点"时的一块代码。 <BR><BR>类BusinessUnitPersistentAspect包括advice方法findAllBusinessUnits，该方法从存储介质中载入数据，然后使用工厂类创建BusinessUnit对象。然后这个对象被加入map，map对象的引用通过BusinessUnitService对象获得。 <BR><BR>"切入点"和"处理方法"组成了所谓的"切面(Aspect)"为了读取存储介质中的数据，OOP方法通过一个DAO类来做。而AOP中，你只要定义一个"切入点"和相应的"处理方法"来读取数据。AOP框架会以advice的形式注入代码，既可以在执行期也可以在编译期。 <BR><BR>总而言之，当类BusinessUnitService 中的findAllBusinessUnits 方法被调用时，AOP框架会在"切入点"处注入处理方法，通过BusinessUnit 对象预先读取数据来填充map对象。这样，持久层方面的代码就可以移到业务代码之外了。 <BR><BR>新方法里的"切面" <BR><BR>本节讨论如何用AOP为应用程序的各个"切面"建模 <BR><BR>操作资源 <BR><BR>类BusinessUnitPersistenceAspect 的持久方法使用了一个buffered reader。你甚至可以定义"切面"的"切面"，但为了简单，这里只关注类的查找方法。 <BR><BR>
<CENTER><CCID_NOBR>
<TABLE cellSpacing=0 borderColorDark=#ffffff cellPadding=2 width=400 align=center borderColorLight=black border=1>
<TBODY>
<TR>
<TD class=code style="FONT-SIZE: 9pt" bgColor=#e6e6e6><PRE><CCID_CODE>@Aspect("perJVM") 
public class BufferedFileReaderAspect 
{ 

@Expression("execution
(* org.javatechnocrats.aop.withaop.
aspects.BusinessUnitPersistenceAspect.find*(..))") 
Pointcut businessUnitPersistenceAspect; 

// 其他"切入点"定义 

@Expression("businessUnitPersistenceAspect || 
employeePersistenceAspect || 
managerPersistenceAspect") 
Pointcut allPersistencePointcuts; 

private Map&lt;Class， String&gt; fileNames; 

public BufferedFileReaderAspect() 
{ 
System.out.println
("BufferedFileReaderAspect created"); 
fileNames = new HashMap&lt;Class， String&gt;(); 
fillFileNames(); 
} 

@Before("allPersistencePointcuts") 
public void assignReader
(JoinPoint joinPoint) 
throws Throwable 
{ 
System。out。println
("assignReader advice called"); 
Object callee = 
joinPoint.getCallee(); 
IBufferedFileReaderConsumable
bufReaderConsumable =
(IBufferedFileReaderConsumable)callee; 
Class persistenceClass = 
callee.getClass(); 
String fileName = 
fileNames.get(persistenceClass); 
FileReader fileReader = 
new FileReader(fileName); 
BufferedReader bufferedReader =
new BufferedReader(fileReader); 
bufReaderConsumable.
setBufferedReader(bufferedReader); 
} 

@AfterFinally("allPersistencePointcuts") 
public void releaseReader
(JoinPoint joinPoint) throws Throwable 
{ 
//释放buffered reader等资源 
} 
//其他方法 
}</CCID_CODE></PRE></TD></TR></TBODY></TABLE></CCID_NOBR></CENTER><BR><BR>上面的代码试图为每一个方法创建"切入点"--所有以find开头的方法。无论何时这些方法被调用，assignReader方法都会被提前执行。这里它获取被调用的类实例然后设置新建的buffered reader。 <BR><BR>同样地，在releaseReader 方法里，代码会预先关闭buffered reader集合。本节只解释@before和@ <BR><BR>AfterFinally 这两个"切入点"。(以J2SE 5。0的标记定义)。另外，你也可以在方面定义的xml文件中声明他们。你可以查看例程源代码中的aop。xml文件。 <BR><BR>下载 <BR><BR>持久化 <BR><BR>前面提到，OOP方法使用BusinessUnit来为应用的持久层填充Map。在下面的高亮代码中(@before一行，以及while循环代码)，当BusinessUnitService中的方法findAllBusinessUnits 被调用时"处理方法"findAllBusinessUnits 也将被调用。<BR><BR><BR><BR><BR><BR><BR><BR><BR><BR>
<CENTER><CCID_NOBR>
<TABLE cellSpacing=0 borderColorDark=#ffffff cellPadding=2 width=400 align=center borderColorLight=black border=1>
<TBODY>
<TR>
<TD class=code style="FONT-SIZE: 9pt" bgColor=#e6e6e6><PRE><CCID_CODE>@Aspect("perJVM") 
public class
BusinessUnitPersistenceAspect 
implements IBufferedFileReaderConsumable
{ 

private BufferedReader buffFileReader; 

@Before("execution
(Collection org.javatechnocrats.aop.withaop.
BusinessUnitService.findAllBusinessUnits())") 
public void findAllBusinessUnits
(JoinPoint joinPoint)
throws Throwable 
{ 
System.out.println
("findAllBusinessUnits advice called"); 
Map&lt;String， BusinessUnit&gt; businessUnits = 
((BusinessUnitService)joinPoint.
getThis()).getBusinessUnits(); 
String businessUnitRecord; 
while((businessUnitRecord =
buffFileReader。readLine()) != null) 
{ 
BusinessUnit businessUnit = BusinessUnitFactory.
createBusinessUnit(businessUnitRecord); 
businessUnits.put
(businessUnit.getId()， businessUnit); 
} 
} 

public void setBufferedReader
(BufferedReader buffFileReader) 
{ 
System.out.println
("BusinessUnitPersistenceAspect.
setBufferedReader called"); 
this.buffFileReader = buffFileReader; 
} 

public BufferedReader getBufferedReader() 
{ 
System.out.println
("BusinessUnitPersistenceAspect.
getBufferedReader called"); 
return this.buffFileReader; 
} 
}</CCID_CODE></PRE></TD></TR></TBODY></TABLE></CCID_NOBR></CENTER><BR><BR>"处理方法"从数据存储中读取记录，使用工厂类创建一个BusinessUnit实例。然后这个实例被加入到Map。该Map掌管程序的所有持久化"切面"。 <BR><BR>日志 <BR><BR>本文中的例子没有包含一个完整的日志AOP解决方案。但是，它为java。lang。Object类的toString方法定义了一个"切入点"来获取类的调试信息。因此，域中的类不需要实现toString方法。通常可能你可能需要为每一个类都要实现这个方法。 <BR><BR>
<CENTER><CCID_NOBR>
<TABLE cellSpacing=0 borderColorDark=#ffffff cellPadding=2 width=400 align=center borderColorLight=black border=1>
<TBODY>
<TR>
<TD class=code style="FONT-SIZE: 9pt" bgColor=#e6e6e6><PRE><CCID_CODE>@Aspect("perJVM") 
public class LoggingAspect 
{ 

@Around("execution(
String org.javatechnocrats.aop.
withaop..*.toString())") 
public Object toStringAdvice
(JoinPoint joinPoint)
throws Throwable 
{ 
System.out.println
("toStringAdvice called"); 
String toString = 
(String)joinPoint.proceed(); 
Object target = joinPoint.getThis(); 
Field fields[] = 
target.getClass().getDeclaredFields(); 
List members = 
new ArrayList(fields.length + 1); 
members.add(toString); 
for(Field field : fields) 
{ 
field.setAccessible(true); 
Object member = field.get(target); 
members.add(field.getName() 
+ "=" + member); 
} 
return members。toString(); 
}</CCID_CODE></PRE></TD></TR></TBODY></TABLE></CCID_NOBR></CENTER><BR><BR>你也可以用这个样例代码完成错误处理"切面"。 <BR><BR>深入源代码 <BR><BR>为了理解样例需求的OOP设计，请参看源代码并思考以下几个问题: 下载 <BR><BR>* 首先分析oldway包中EmployeeServiceTestCase 类中的代码 <BR><BR>*查看testEmployeeCredit 方法 <BR><BR>*搞懂业务类Employee和BusinessUnit <BR><BR>*学习 service，repository和factory概念。这些是业务驱动设计的主要概念。 <BR><BR>*更深入地理解oldway包中的service，repository和factory类 <BR><BR>而AOP地理解则应该是: <BR><BR>*分析newway包中EmployeeServiceTestCase 类 <BR><BR>*查看service，repository和factory类，基本和前一种差不多。只是你要让"处理方法"截获程序的执行流程。 <BR><BR>*研究aspect类学习"切入点"的定义 <BR><BR>要执行程序，你需要做的工作: <BR><BR>* 下载AspectWerkz 2。0 http://aspectwerkz。codehaus。org/ <BR><BR>*设置以下的环境变量: <BR><BR>
<CENTER><CCID_NOBR>
<TABLE cellSpacing=0 borderColorDark=#ffffff cellPadding=2 width=400 align=center borderColorLight=black border=1>
<TBODY>
<TR>
<TD class=code style="FONT-SIZE: 9pt" bgColor=#e6e6e6><PRE><CCID_CODE>set JAVA_HOME=c:\Program Files\Java\jdk1.5.0
set ASPECTWERKZ_HOME=C:\aw_2_0_2
set PATH=%PATH%;%ASPECTWERKZ_HOME%\bin
set CLASSPATH=
C:\aw_2_0_2\lib\aspectwerkz-2.0.RC2.jar;
C:\aw_2_0_2\lib\aspectwerkz-jdk5-2.0.RC2.jar;
classes;
C:\ junit\3.8.1\resources\lib\junit.jar</CCID_CODE></PRE></TD></TR></TBODY></TABLE></CCID_NOBR></CENTER><BR><BR>*解压缩源代码和其他文件 <BR><BR>*编译Java文件，但不要编译测试用例否则你调试时会遇到一个错误。 <BR><BR>*进行离线调试。假设你把文件解压缩到c:\aop，类文件解压到c:\aop\classes，在c:\aop目录下执行以下命令: <BR><BR>
<CENTER><CCID_NOBR>
<TABLE cellSpacing=0 borderColorDark=#ffffff cellPadding=2 width=400 align=center borderColorLight=black border=1>
<TBODY>
<TR>
<TD class=code style="FONT-SIZE: 9pt" bgColor=#e6e6e6><PRE><CCID_CODE>%ASPECTWERKZ_HOME%\bin\aspectwerkz 
-offline etc/aop。xml -cp classes classes</CCID_CODE></PRE></TD></TR></TBODY></TABLE></CCID_NOBR></CENTER><BR><BR>*AOP框架会修改类来注入必要的字节码 <BR><BR>*编译测试用例，使用JUnit运行它。 <BR><BR>后记 <BR><BR>当你完成了上面的这些工作，你应该有以下的领悟: <BR><BR>*程序中的交叉关联 <BR><BR>*关于AOP中深入源代码 <BR><BR>为了理解样例需求的OOP设计，请参看源代码并思考以下几个问题: <BR><BR>下载 <BR><BR>* 首先分析oldway包中EmployeeServiceTestCase 类中的代码 <BR><BR>*查看testEmployeeCredit 方法 <BR><BR>*搞懂业务类Employee和BusinessUnit <BR><BR>*学习 service，repository和factory概念。这些是业务驱动设计的主要概念。 <BR><BR>*更深入地理解oldway包中的service，repository和factory类 <BR><BR>而AOP地理解则应该是: <BR><BR>*分析newway包中EmployeeServiceTestCase 类 <BR><BR>*查看service，repository和factory类，基本和前一种差不多。只是你要让advice截取程序的流程。 <BR><BR>*研究aspect类学习point cut的定义 <BR><BR>要执行程序，你需要做的工作: <BR><BR>* 下载AspectWerkz 2.0 http://aspectwerkz。codehaus。org/ <BR><BR>*设置以下的环境变量: <BR><BR>
<CENTER><CCID_NOBR>
<TABLE cellSpacing=0 borderColorDark=#ffffff cellPadding=2 width=400 align=center borderColorLight=black border=1>
<TBODY>
<TR>
<TD class=code style="FONT-SIZE: 9pt" bgColor=#e6e6e6><PRE><CCID_CODE>set JAVA_HOME=c:\Program Files\Java\jdk1.5.0
set ASPECTWERKZ_HOME=C:\aw_2_0_2
set PATH=%PATH%;
%ASPECTWERKZ_HOME%\bin
set CLASSPATH=
C:\aw_2_0_2\lib\aspectwerkz-2.0.RC2.jar;
C:\aw_2_0_2\lib\aspectwerkz-jdk5-2.0.RC2.jar; 
classes;
C:\ junit\3.8.1\resources\lib\junit.jar</CCID_CODE></PRE></TD></TR></TBODY></TABLE></CCID_NOBR></CENTER><BR><BR>*解压缩源代码和其他文件 <BR><BR>*编译Java文件，但不要编译测试用例否则你调试时会遇到一个错误。 <BR><BR>*进行离线调试。假设你把文件解压缩到c:\aop ，类文件解压到c:\aop\classes，在c:\aop目录下执行以下命令: <BR><BR>
<CENTER><CCID_NOBR>
<TABLE cellSpacing=0 borderColorDark=#ffffff cellPadding=2 width=400 align=center borderColorLight=black border=1>
<TBODY>
<TR>
<TD class=code style="FONT-SIZE: 9pt" bgColor=#e6e6e6><PRE><CCID_CODE>%ASPECTWERKZ_HOME%\bin\aspectwerkz
-offline etc/aop。xml -cp classes classes</CCID_CODE></PRE></TD></TR></TBODY></TABLE></CCID_NOBR></CENTER><BR><BR>*AOP框架会修改类来注入必要的字节码 <BR><BR>*编译测试用例，使用JUnit运行它。 <BR><BR>后记 <BR><BR>当你完成了上面的这些工作，你应该有以下的领悟: <BR><BR>*程序中的交叉关联 <BR><BR>*关于AOP中"切面"的含义 <BR><BR>*如何用AOP来把程序业务层中的交叉关联分离出来，使用"切入点"和"处理方法" <BR><BR>*OOP和AOP时在程序控制流上的不同 <BR><BR>从本文你应该也得到一种看待实际开发的新视角。你应该有信心使用AOP来改进项目中的设计，建模，提高代码的重用性。至少，你可以开始使用AOP来处理日志，错误和持久化。 <BR><BR>个人觉得，AOP的学习曲线相对较陡，尤其在理解定义"切入点"的句法时。理想的情况是，使用OOP来设计业务模型，使用AOP把业务模型中的交叉关联移出，从而使代码简洁并提高可读性。 <BR><BR>AOP的一个缺点是会使调试变得困难，因为不同于OOP，程序流变的复杂了，交互是由编译期或执行期决定。我准备将来做一些自动化工具来解决这个问题。 <BR><img src ="http://www.blogjava.net/qq13367612/aggbug/18131.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/qq13367612/" target="_blank">Sung</a> 2005-11-04 13:57 <a href="http://www.blogjava.net/qq13367612/articles/18131.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>当前流行的J2EE WEB应用架构分析</title><link>http://www.blogjava.net/qq13367612/articles/16905.html</link><dc:creator>Sung</dc:creator><author>Sung</author><pubDate>Wed, 26 Oct 2005 09:52:00 GMT</pubDate><guid>http://www.blogjava.net/qq13367612/articles/16905.html</guid><wfw:comment>http://www.blogjava.net/qq13367612/comments/16905.html</wfw:comment><comments>http://www.blogjava.net/qq13367612/articles/16905.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/qq13367612/comments/commentRss/16905.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/qq13367612/services/trackbacks/16905.html</trackback:ping><description><![CDATA[<BLOCKQUOTE>J2EE体系包括java server pages(JSP) ,java SERVLET, enterprise bean，WEB service等技术。这些技术的出现给电子商务时代的WEB应用程序的开发提供了一个非常有竞争力的选择。怎样把这些技术组合起来形成一个适应项目需要的稳定架构是项目开发过程中一个非常重要的步骤。完成这个步骤可以形成一个主要里程碑基线。</BLOCKQUOTE>
<P><A name=1><SPAN class=atitle2>1. 架构概述</SPAN></A><BR></P>
<P>J2EE体系包括java server pages(JSP) ,java SERVLET, enterprise bean，WEB service等技术。这些技术的出现给电子商务时代的WEB应用程序的开发提供了一个非常有竞争力的选择。怎样把这些技术组合起来形成一个适应项目需要的稳定架构是项目开发过程中一个非常重要的步骤。完成这个步骤可以形成一个主要里程碑基线。形成这个基线有很多好处：</P>
<OL xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:h="http://www.w3.org/1999/xhtml" xmlns:dw="http://www.ibm.com/developerworks/">
<LI>各种因数初步确定 <BR>为了形成架构基线，架构设计师要对平台（体系）中的技术进行筛选，各种利弊的权衡。往往架构设计师在这个过程中要阅读大量的技术资料，听取项目组成员的建议，考虑领域专家的需求，考虑赞助商成本（包括开发成本和运行维护成本）限额。一旦架构设计经过评审，这些因数初步地就有了在整个项目过程中的对项目起多大作用的定位。 
<LI>定向技术培训 <BR>一旦架构师设计的架构得到了批准形成了基线，项目开发和运行所采用的技术基本确定下来了。众多的项目经理都会对预备项目组成员的技术功底感到担心；他们需要培训部门提供培训，但就架构师面对的技术海洋，项目经理根本就提不出明确的技术培训需求。怎不能够对体系中所有技术都进行培训吧！有了架构里程碑基线，项目经理能确定这个项目开发会采用什么技术，这是提出培训需求应该是最精确的。不过在实际项目开发中，技术培训可以在基线确定之前与架构设计并发进行。 
<LI>角色分工 <BR>有了一个好的架构蓝图，我们就能准确划分工作。如网页设计，JSP 标签处理类设计，SERVLET 设计，session bean设计，还有各种实现。这些任务在架构蓝图上都可以清晰地标出位置，使得项目组成员能很好地定位自己的任务。一个好的架构蓝图同时也能规范化任务，能很好地把任务划分为几类，在同一类中的任务的工作量和性质相同或相似。这样工作量估计起来有一个非常好的基础。 
<LI>运行维护 <BR>前面说过各个任务在架构图上都有比较好的定位。任何人能借助它很快地熟悉整个项目的运行情况，错误出现时能比较快速地定位错误点。另外，有了清晰的架构图，项目版本管理也有很好的版本树躯干。 
<LI>扩展性 <BR>架构犹如一颗参天大树的躯干，只要躯干根系牢，树干粗，长一些旁支，加一些树叶轻而易举无疑。同样，有一个稳定的经得起考验的架构，增加一两个业务组件是非常快速和容易的。 </LI></OL>
<P>大家都知道这些好处，一心想形成一个这样的J2EE应用程序架构（就像在windows平台中的MFC）。在这个路程中经历了两个大的阶段：</P>
<P><A name=N10066><SPAN class=atitle3>1.1. 模型1</SPAN></A><BR></P>
<P>模型1其实不是一个什么稳定架构，甚至谈不上形成了架构。模型1的基础是JSP文件。它从HTTP的请求中提取参数，调用相应的业务逻辑，处理HTTP会话，最后生成HTTP文档。一系列这样的JSP文件形成一个完整的模型1应用，当然可能会有其他辅助类或文件。早期的ASP 和 PHP 技术就属于这个情况。</P>
<P>总的看来，这个模型的好处是简单，但是它把业务逻辑和表现混在一块，对大应用来说，这个缺点是令人容忍不了的。</P>
<P><A name=N10074><SPAN class=atitle3>1.2. 模型2</SPAN></A><BR>在经过一番实践，并广泛借鉴和总结经验教训之后，J2EE应用程序终于迎来了MVC（模型-视图-控制）模式。MVC模式并不是J2EE行业人士标新立异的，所以前面我谈到广发借鉴。MVC的核心就是做到三层甚至多层的松散耦合。这对基于组件的，所覆盖的技术不断膨胀的J2EE体系来说真是福音和救星。</P>
<P>它在浏览器（本文对客户代理都称浏览器）和JSP或SERVLET之间插入一个控制组件。这个控制组件集中了处理浏览器发过来的HTTP请求的分发逻辑，也就是说，它会根据HTTP请求的URL,输入参数，和目前应用的内部状态，把请求分发给相应的WEB 层的JSP 或SERVLET。另外它也负责选择下一个视图（在J2EE中，JSP,SERVLET会生成回给浏览器的html从而形成视图）。集中的控制组件也有利于安全验证，日志纪录，有时也封装请求数据给下面的WEB tier层。这一套逻辑的实现形成了一个像MFC的应用框架，位置如图：</P>
<P><A name=N10082><B></B></A><BR><IMG height=319 alt="" src="http://www-128.ibm.com/developerworks/cn/java/l-j2eeArch/1.gif" width=340 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:h="http://www.w3.org/1999/xhtml" xmlns:dw="http://www.ibm.com/developerworks/"> </P>
<P><A name=N1008E><SPAN class=atitle3>1.3. 多层应用</SPAN></A><BR>下图为J2EE体系中典型的多层应用模型。</P>
<UL xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:h="http://www.w3.org/1999/xhtml" xmlns:dw="http://www.ibm.com/developerworks/">
<LI>Client tier客户层 <BR>一般为浏览器或其他应用。客户层普遍地支持HTTP协议，也称客户代理。 
<LI>WEB tier WEB应用层 <BR>在J2EE中，这一层由WEB 容器运行，它包括JSP, SERVLET等WEB部件。 
<LI>EJB tier 企业组件层 <BR>企业组件层由EJB容器运行，支持EJB, JMS, JTA 等服务和技术。 
<LI>EIS tier 企业信息系统层 <BR>企业信息系统包含企业内传统信息系统如财务，CRM等，特点是有数据库系统的支持。 </LI></UL>
<P><A name=N100B0><B></B></A><BR><IMG height=261 alt="" src="http://www-128.ibm.com/developerworks/cn/java/l-j2eeArch/2.gif" width=600 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:h="http://www.w3.org/1999/xhtml" xmlns:dw="http://www.ibm.com/developerworks/"> </P>
<P>应用框架目前主要集中在WEB层，旨在规范这一层软件的开发。其实企业组件层也可以实现这个模型，但目前主要以设计模式的形式存在。而且有些框架可以扩充，有了企业组件层组件的参与，框架会显得更紧凑，更自然，效率会更高。</P>
<P><A name=2><SPAN class=atitle2>2. 候选方案</SPAN></A><BR></P>
<P>目前，实现模型2的框架也在不断的涌现，下面列出比较有名的框架。</P>
<P><A name=N100CA><SPAN class=atitle3>2.1. Apache Struts</SPAN></A><BR>Struts是一个免费的开源的WEB层的应用框架，apache软件基金致力于struts的开发。Struts具是高可配置的性，和有一个不断增长的特性列表。一个前端控制组件，一系列动作类，动作映射，处理XML的实用工具类，服务器端java bean 的自动填充，支持验证的WEB 表单，国际化支持，生成HTML，实现表现逻辑和模版组成了struts的灵魂。</P>
<P><B xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:h="http://www.w3.org/1999/xhtml" xmlns:dw="http://www.ibm.com/developerworks/">2.1.1. Struts和MVC</B> </P>
<P>模型2的目的和MVC的目的是一样的，所以模型2基本可以和MVC等同起来。下图体现了Struts的运作机理：</P>
<P><A name=N100DE><B></B></A><BR><IMG height=413 alt="" src="http://www-128.ibm.com/developerworks/cn/java/l-j2eeArch/3.gif" width=550 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:h="http://www.w3.org/1999/xhtml" xmlns:dw="http://www.ibm.com/developerworks/"> </P>
<P>2.1.1.1. 控制</P>
<P>如图所示，它的主要部件是一个通用的控制组件。这个控制组件提供了处理所有发送到Struts 的HTTP请求的入口点。它截取和分发这些请求到相应的动作类（这些动作类都是Action类的子类）。另外控制组件也负责用相应的请求参数填充 From bean,并传给动作类。动作类实现核心商业逻辑，它可以通过访问java bean 或调用EJB。最后动作类把控制权传给后续的JSP 文件，后者生成视图。所有这些控制逻辑利用一个叫struts-config.xml文件来配置。</P>
<P>2.1.1.2. 模型</P>
<P>模型以一个或几个java bean的形式存在。这些bean分为三种：</P>
<UL xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:h="http://www.w3.org/1999/xhtml" xmlns:dw="http://www.ibm.com/developerworks/">
<LI>Form beans(表单Beans) <BR>它保存了HTTP post请求传来的数据，在Struts里，所有的Form beans都是 ActionFrom 类的子类。 
<LI>业务逻辑beans <BR>专门用来处理业务逻辑。 
<LI>系统状态beans <BR>它保存了跨越多个HTTP 请求的单个客户的会话信息，还有系统状态。 </LI></UL>
<P>2.1.1.3. 视图</P>
<P>控制组件续传HTTP请求给实现了视图的JSP文件。JSP能访问beans 并生成结果文档反馈到客户。Struts提供JSP 标签库： Html，Bean，Logic，Template等来达到这个目的，并有利于分开表现逻辑和程序逻辑。</P>
<P><B xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:h="http://www.w3.org/1999/xhtml" xmlns:dw="http://www.ibm.com/developerworks/">2.1.2. Struts的细节分析</B> </P>
<P>2.1.2.1. 视图-控制-模型</P>
<P>用户发出一个*.do的HTTP请求，控制组件接收到这个请求后，查找针对这个请求的动作映射，再检查是否曾创建过相应的动作对象（action实例），如果没有则调用actionmapping生成一个动作对象，控制组件会保存这个动作对象供以后使用。接着调用actionmapping的方法得到actionForm对象。之后把actionForm作为参数传给动作对象的perform方法，这个方法结束之后会返回给控制组件一个 actionforward对象。控制组件接着从这个对象中获取下一个视图的路径和重定向属性。如果为重定向则调用HTTPSERVLETREPONSE的方法来显示下一个视图，否则相继调用requestdispatcher, SERVLETcontext的方法续传HTTP请求到下一个视图。</P>
<P>当动作对象运行perform方法时，可能出现错误信息。动作对象可以保存这些错误信息到一个error对象中，接着调用自身的saveerrors方法把这个错误保存到request对象的属性中。接着动作对象调用actionmapping对象的getInput方法从动作映射中获取input参数，也就是产生输入的视图，并以这个input为参数生成一个actionforward对象返回。这个input参数的JSP中一般有HTTP:errors定制标签读取这些错误信息并显示在页面上。</P>
<P>下面是一个logon.JSP 的代码实例：</P>
<TABLE cellSpacing=0 cellPadding=5 width="100%" bgColor=#cccccc border=1>
<TBODY>
<TR>
<TD><PRE><CODE>
&lt;%@ page language="java" %&gt;
&lt;%@ taglib uri="/WEB-INF/struts-bean.tld" prefix="bean" %&gt;
&lt;%@ taglib uri="/WEB-INF/struts-html.tld" prefix="html" %&gt;

&lt;html:html locale="true"&gt;
&lt;head&gt;
&lt;title&gt;&lt;bean:message key="logon.title"/&gt;&lt;/title&gt;
&lt;html:base/&gt;
&lt;/head&gt;
&lt;body bgcolor="white"&gt;

&lt;html:errors/&gt;   &lt;!--  如果出现错误会显示在这里  --&gt;

&lt;html:form action="/logon" focus="username"&gt;
&lt;table border="0" width="100%"&gt;

  &lt;tr&gt;
    &lt;th align="right"&gt;
      &lt;bean:message key="prompt.username"/&gt;
    &lt;/th&gt;
    &lt;td align="left"&gt;
      &lt;html:text property="username" size="16" maxlength="16"/&gt;
    &lt;/td&gt;
  &lt;/tr&gt;

  &lt;tr&gt;
    &lt;th align="right"&gt;
      &lt;bean:message key="prompt.password"/&gt;
    &lt;/th&gt;
    &lt;td align="left"&gt;
      &lt;html:password property="password" size="16" maxlength="16"
                    redisplay="false"/&gt;
    &lt;/td&gt;
  &lt;/tr&gt;

  &lt;tr&gt;
    &lt;td align="right"&gt;
      &lt;html:submit property="submit" value="Submit"/&gt;
    &lt;/td&gt;
    &lt;td align="left"&gt;
      &lt;html:reset/&gt;
    &lt;/td&gt;
  &lt;/tr&gt;

&lt;/table&gt;
</CODE></PRE></TD></TR></TBODY></TABLE>
<P><A name=N10126><B></B></A><BR><IMG height=312 alt="" src="http://www-128.ibm.com/developerworks/cn/java/l-j2eeArch/a.gif" width=697 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:h="http://www.w3.org/1999/xhtml" xmlns:dw="http://www.ibm.com/developerworks/"> </P>
<P>2.1.2.2. 模型到视图</P>
<P>模型到视图指视图在显示之前装载系统数据到视图的过程。系统数据一般为模型内java bean的信息。示意图表现了由控制组件forward过来的有html:form定制标签的JSP 的处理逻辑。</P>
<P>html:form定制标签处理对象从application scope（通过查询SERVLETCONTEXT对象的属性来实现）获取先前由控制组件actionSERVLET放在那里的动作映射等对象，由html:form 的action属性查得actionform名字、类型和范围等信息，在相应的范围内查找actionform，如果有则利用它的信息填充html form表单[实际填充动作在嵌套的html:text等定制标签的处理对象中]。否则在相应范围内创建一个actionform 对象。</P>
<P><B xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:h="http://www.w3.org/1999/xhtml" xmlns:dw="http://www.ibm.com/developerworks/">2.1.3. 优缺点</B> </P>
<P>优点：</P>
<UL xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:h="http://www.w3.org/1999/xhtml" xmlns:dw="http://www.ibm.com/developerworks/">
<LI>一些开发商开始采用并推广这个框架 
<LI>作为开源项目，有很多先进的实现思想 
<LI>对大型的应用支持的较好 
<LI>有集中的网页导航定义 </LI></UL>
<P>缺点：</P>
<UL xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:h="http://www.w3.org/1999/xhtml" xmlns:dw="http://www.ibm.com/developerworks/">
<LI>不是业届标准 
<LI>对开发工具的支持不够 
<LI>复杂的taglib，需要比较长的时间来掌握 
<LI>html form 和 actionform的搭配比较封闭，但这也是它的精华所在。 </LI></UL>
<P>修改建议把actionform属性的设置器和访问器修改成读取或生成xml文档的方法，然后 html form和actionform之间用xml文档进行数据交换，使之松散耦合，适应数据结构易变化的应用。</P>
<P><A name=N1016A><B></B></A><BR><IMG height=696 alt="" src="http://www-128.ibm.com/developerworks/cn/java/l-j2eeArch/4.gif" width=774 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:h="http://www.w3.org/1999/xhtml" xmlns:dw="http://www.ibm.com/developerworks/"> </P>
<P><A name=N10176><SPAN class=atitle3>2.2. JATO</SPAN></A><BR>JATO应用程序框架是iPlanet 应用程序框架的旧名。它是一个成熟的、强大的，基于J2EE标准的面向于开发WEB应用程序的应用框架。结合了显示字段、应用程序事件、组件层次和以页面为中心的开发方法、以及MVC和服务到工作者service-to-workers的设计模式等概念。JATO可适用于中、大、超大规模的WEB应用。但是它也不是一个企业层的应用框架，也就是说它不会直接提供创建EJB, WEB services等企业层组件的方法，但用它可以构造出访问企业层组件的客户应用。</P>
<P>这个框架功能主要有三部分组成：</P>
<UL xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:h="http://www.w3.org/1999/xhtml" xmlns:dw="http://www.ibm.com/developerworks/">
<LI>iPlanet应用框架核心； 
<LI>iPlanet应用框架组件； 
<LI>iPlanet应用框架扩展。 </LI></UL>
<P>应用框架核心定义了基本接口、对象协议、简单组件，以及iPlanet应用框架程序的最小核心。包括视图简单组件、模型简单组件、请求分发组件和可重用命令对象。iPlanet应用框架组件利用框架核心定义的基本接口、协议和组件向开发者提供高层的重用组件，这些组件既有与特定视觉效果无关的水平组件，同时也有适应特定实用环境、提高可用性而特意提供的垂直型组件。框架扩展实现了用框架相容的方法访问非J2EE环境的方法。通常情况下，扩展被框架应用程序用来无缝访问J2EE容器特定功能。JATO平台栈图很清楚地表达了这个情况。</P>
<P>JATO最大的威力在：对于快速开发用户，你能利用框架组件和扩展提高生产率，对于要求更大灵活性的用户，你能实现框架核心提供的接口来保持应用的框架兼容性。</P>
<P><A name=N10196><B></B></A><BR><IMG height=227 alt="" src="http://www-128.ibm.com/developerworks/cn/java/l-j2eeArch/5.gif" width=300 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:h="http://www.w3.org/1999/xhtml" xmlns:dw="http://www.ibm.com/developerworks/"> </P>
<P><A name=N101A4><B></B></A><BR><IMG height=502 alt="" src="http://www-128.ibm.com/developerworks/cn/java/l-j2eeArch/6.gif" width=550 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:h="http://www.w3.org/1999/xhtml" xmlns:dw="http://www.ibm.com/developerworks/"> </P>
<P>此图表示实现一个JATO应用程序，可以简单地实现控制组件module1Servlet，视图组件ListCustomersViewBean和模型组件CustomersModuleImpl，以及一个给客户代理显示界面的ListCustomers.jsp文件。并清楚地表明这些组件与JATO框架组件的继承关系。</P>
<P><A name=N101B5><B></B></A><BR><IMG height=609 alt="" src="http://www-128.ibm.com/developerworks/cn/java/l-j2eeArch/7.gif" width=580 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:h="http://www.w3.org/1999/xhtml" xmlns:dw="http://www.ibm.com/developerworks/"> </P>
<P>JATO标签库提供了VIEW对象与JSP文件的接口。库中标签处理程序负责实现VIEW对象和JSP产生地客户端文档的信息同步和交换。这个图清楚地表达了这种对应关系</P>
<P><B xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:h="http://www.w3.org/1999/xhtml" xmlns:dw="http://www.ibm.com/developerworks/">2.2.1. MVC分析</B> </P>
<P><A name=N101CC><B></B></A><BR><IMG height=459 alt="" src="http://www-128.ibm.com/developerworks/cn/java/l-j2eeArch/8.gif" width=600 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:h="http://www.w3.org/1999/xhtml" xmlns:dw="http://www.ibm.com/developerworks/"> </P>
<P>前端控制组件接收用户发来的任何请求，这个可在WEB.xml中指定请求分发组件负责视图管理和导航，和前端控制组件封装在ApplicationSERVLETBase一起实现。应用程序开发者需要为每一个子系统（人力资源，财务，CRM等）实现一个此类的继承。</P>
<P>请求分发组件分发请求给工作者，工作者实现了command接口。应用开发者可以实现这个接口。JATO提供了一个缺省实现：DefaultRequestHandingCommand，这个实现会把请求传给视图组件的特定事件。</P>
<P>组合视图是指视图组件在显示给用户时的层次关系：根视图是一个ViewBean类的对象字段是一个DisplayField类的对象，容器视图是一个ContainerView类的对象。视图组件类的层次关系如下图：</P>
<P><A name=N101E3><B></B></A><BR><IMG height=273 alt="" src="http://www-128.ibm.com/developerworks/cn/java/l-j2eeArch/9.gif" width=550 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:h="http://www.w3.org/1999/xhtml" xmlns:dw="http://www.ibm.com/developerworks/"> </P>
<P><B xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:h="http://www.w3.org/1999/xhtml" xmlns:dw="http://www.ibm.com/developerworks/">2.2.2. 优缺点分析</B> </P>
<P>优点：</P>
<UL xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:h="http://www.w3.org/1999/xhtml" xmlns:dw="http://www.ibm.com/developerworks/">
<LI>这种框架的适应范围大，即提供了底层接口，也有立即可用的组件 
<LI>具有与客户端RAD开发工具相似的开发概念如页为中心（等同于VB的FORM），事件处理等. 
<LI>对大型的应用支持较好 </LI></UL>
<P>缺点：</P>
<UL xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:h="http://www.w3.org/1999/xhtml" xmlns:dw="http://www.ibm.com/developerworks/">
<LI>不是业届标准 
<LI>目前还没有开发工具的支持（然JATO已经为工具支持做好了准备） 
<LI>没有定义网页导航，开发者在视图中自己指定具体的导航URL </LI></UL>
<P>修改建议 <BR xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:h="http://www.w3.org/1999/xhtml" xmlns:dw="http://www.ibm.com/developerworks/">把众多的VIEW/MODEL对应修改成xml文档传递数据，加上集中的网页导航定义 </P>
<P><A name=N10218><SPAN class=atitle3>2.3. JSF(JavaServer Faces)</SPAN></A><BR>JSF是一个包括SUN在内的专家组正在定义的开发WEB应用用户界面的框架，JSF 技术包括：</P>
<UL xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:h="http://www.w3.org/1999/xhtml" xmlns:dw="http://www.ibm.com/developerworks/">
<LI>一组API，它实现UI了组件，管理组件的状态，处理事件，输入校验，定义页面导航，支持国际化和访问； 
<LI>一个JSP定制标签库实现与JSP的接口。 </LI></UL>
<P>JSF非常简单，是一个定义良好的编程模型。利用这个技术，开发者通过在页面内组合可重用的UI组件，在把这些组件和应用的数据源相连，路由客户产生的事件到服务器端的事件处理器进行编程。JSP处理了所有幕后的复杂工作，使得开发者把关注重点放在应用代码上。</P>
<P><B xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:h="http://www.w3.org/1999/xhtml" xmlns:dw="http://www.ibm.com/developerworks/">2.3.1. STRUTS、JATO和JSF比较</B> </P>
<P>它们之间有部分重叠，但重点不一样。</P>
<UL xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:h="http://www.w3.org/1999/xhtml" xmlns:dw="http://www.ibm.com/developerworks/">
<LI>STRUTS和JATO都提供了一个MVC式的应用模型，而JSF只在用户界面上提供编程接口。这意味着前两者涉及的范围比后者广。JSF可以成为前两者在UI开发的部分。 
<LI>JSF的规范的发布版将在 2002年底发布，实现可能要比这个时间晚些。另外将会有工具支持这个框架的应用开发。 </LI></UL>
<P><A name=N1023F><SPAN class=atitle3>2.4. WAF</SPAN></A><BR>WAF是WEB APPLICATION FRAMWORK的简称，是SUN蓝皮书例子程序中提出的应用框架。它实现了 MVC和其他良好的设计模式。</P>
<P><B xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:h="http://www.w3.org/1999/xhtml" xmlns:dw="http://www.ibm.com/developerworks/">2.4.1. 细节分析</B> </P>
<P><A name=N10250><B></B></A><BR><IMG height=363 alt="" src="http://www-128.ibm.com/developerworks/cn/java/l-j2eeArch/10.gif" width=600 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:h="http://www.w3.org/1999/xhtml" xmlns:dw="http://www.ibm.com/developerworks/"> </P><A href="http://www-128.ibm.com/developerworks/cn/java/l-j2eeArch/10_10.gif" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:h="http://www.w3.org/1999/xhtml" xmlns:dw="http://www.ibm.com/developerworks/">点击这里看大图</A> 
<P><B xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:h="http://www.w3.org/1999/xhtml" xmlns:dw="http://www.ibm.com/developerworks/">2.4.2. 视图-控制-模型</B> </P>
<P>如图所示，开发人员编写的两个xml配置文件定义了WAF的运作参数。Screendefinition.xml定义了一系列的屏幕(screen)。Mapping.xml则定义了某个动作之后应该显示的屏幕，但没有指定屏幕到哪里拿数据。</P>
<P>用户发出一个HTTP请求（*.screen），由TemplateSERVLET屏幕前端控制组件接收，它提取请求信息，设置request对象CurrentScreen属性，再把请求发到模版JSP。模版JSP收到请求后，JSP中的Template标签察看这个当前屏幕，并从屏幕定义文件（Screendefinition.xml）中获取这个屏幕的具体参数，再生成html返回给客户。</P>
<P>假设返回给客户的html中包括了html表单，用户在输入一定数据之后提交，发出一个HTTP请求（*.do）。这个请求被MainSERVLET接收，它提取请求信息，察看动作映射文件（mapping.xml），设置处理这个请求的动作对象(HTTPAction对象)，交给requestprosessor对象处理。Requestprosessor对象调用动作对象完成任务，如果需要进一步处理，requestprosessor对象会调用WEBclientcontroler对象的事件处理机制。MainSERVLET在处理完请求之后，从屏幕流管理对象那里得到下一个屏幕，并把请求传给这个屏幕的JSP文件。</P>
<P>值得一提的是WEBclientcontroler事件处理机制最终把HTTP请求的数据传到了EJBAction对象那里处理。这样HTTPAction对象和EJBAction对象形成了两级处理机制，前一级与request对象紧密相关，把数据封装起来形成一个Event对象，再传给了EJBAction对象，后者与Request对象无关。这个方式可以形成一个session级别的数据处理机制。下图显示了这个方法。HTTPAction1对象处理一个请求，并把数据放到一个状态SessionBean内，HTTPAction2也如此，当HTTPAction3接收到HTTP请求之后，把控制传给EJBAction, 后者获取状态SessionBean数据，处理请求，成功后清控状态SessionBean的内容。这个机制非常适应多个输入页面才能满足一个业务的输入数据的情况（比如购物车）。</P>
<P><A name=N10274><B></B></A><BR><IMG height=228 alt="" src="http://www-128.ibm.com/developerworks/cn/java/l-j2eeArch/11.gif" width=400 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:h="http://www.w3.org/1999/xhtml" xmlns:dw="http://www.ibm.com/developerworks/"> </P>
<P><B xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:h="http://www.w3.org/1999/xhtml" xmlns:dw="http://www.ibm.com/developerworks/">2.4.3. 优缺点分析</B> </P>
<P>优点</P>
<UL xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:h="http://www.w3.org/1999/xhtml" xmlns:dw="http://www.ibm.com/developerworks/">
<LI>屏幕导航定义明确 
<LI>为框架的扩展提供了一个空间 </LI></UL>
<P>缺点</P>
<UL xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:h="http://www.w3.org/1999/xhtml" xmlns:dw="http://www.ibm.com/developerworks/">
<LI>源码比较乱，稳定性和可靠性没人验证。 
<LI>只是一个框架躯干，没有正式的model层，视图的概念不强 
<LI>没有模型到视图的定义 </LI></UL>
<P>修改意见 <BR xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:h="http://www.w3.org/1999/xhtml" xmlns:dw="http://www.ibm.com/developerworks/">只有一个框架躯干，正为实现自己的应用框架提供了灵活性。没有僵化的视图概念，提供了在网页输入到模型的扩充接口，比如插入XML数据交换。 </P><img src ="http://www.blogjava.net/qq13367612/aggbug/16905.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/qq13367612/" target="_blank">Sung</a> 2005-10-26 17:52 <a href="http://www.blogjava.net/qq13367612/articles/16905.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>MVC减少编程复杂性 </title><link>http://www.blogjava.net/qq13367612/articles/16890.html</link><dc:creator>Sung</dc:creator><author>Sung</author><pubDate>Wed, 26 Oct 2005 08:14:00 GMT</pubDate><guid>http://www.blogjava.net/qq13367612/articles/16890.html</guid><wfw:comment>http://www.blogjava.net/qq13367612/comments/16890.html</wfw:comment><comments>http://www.blogjava.net/qq13367612/articles/16890.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/qq13367612/comments/commentRss/16890.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/qq13367612/services/trackbacks/16890.html</trackback:ping><description><![CDATA[随着面向对象的语言（如Java）的迅速发展和普及，越来越多的编程人员开始在应用开发中使用这些语言。然而原有的开发语言（即面向操作的开发语言如C＋＋等）在短时间内还不可能退出历史舞台，因此现在就出现了面向对象的语言和传统的面向操作的语言共存的局面。在设计应用中同时使用两类不同的语言（混合语言设计）比过去只使用一类语言会带来许多新的问题，其中复杂性就是混合语言设计中最经常遇到的问题。下面我们探讨混合语言设计中可能导致复杂性增加的地方，以及如何减少以至消除这些复杂性。<BR><BR>复杂性<BR>　　复杂性是应用开发过程中最令人头疼的一个问题。每当在一个应用中增加一个功能时，它的复杂性通常呈几何级的增长。这种复杂性往往导致程序的开发无法再继续下去。这也是现在为什么许多应用只有Beta版本而没有正式版的原因。<BR><BR>　　专家将应用开发过程产生的复杂性分为两类，即非本质的（accidental）和本质的（essential）。本质的复杂性是对于解决目标问题所必然产生的复杂性，非本质的复杂性是由于选择了不适当的开发工具和设计工具而产生的复杂性。对于一个功能确定的程序来讲，本质的复杂性是确定的，而非本质的复杂性则是没有限制的。因此，一个应用的开发要想较顺利地取得成功，就需要尽可能地减少非本质的复杂性。<BR><BR>OOD的特点<BR>　　面向对象的设计（OOD）将一个程序分解成根据具体的对象而设计的一系列元素。这些具体对象的行为和数据以一种叫做“类（class）”的编程单元进行打包。应用程序创建一个或多个这些类的例示，也称为“对象（object）”。类的行为是通过创建对象之间的关系组合在一起的。<BR><BR>　　OOD允许开发者用两种主要的方法来控制复杂性的增加。第一，OOD定义严格的出口语义，这允许开发者隐藏实现的细节，并且明确说明什么方法是其它的对象可以访问的。这个信息隐藏使得可以对大部分的代码进行修改而不影响其它的对象。<BR><BR>　　第二，OOD将对象之间的关系分为四类：继承、包容、使用和协调。适当地使用这些关系可以大大减少应用开发过程中本质的和非本质的复杂性。如，继承是产生面向对象设计中可再使用的主要因素。这个再使用性是通过代码共享和多态性获得的。这种再使用可以大大减少应用的本质的复杂性。包容允许一个类的用户在使用包容器时忽略被包容的类（class）。这个简化使设计者能够大大减少应用的非本质的复杂性。<BR><BR>可视化接口在OOD方面的不足<BR>　　许多程序都需要可视化接口，这些接口由对话框、选单、工具条等组成。这些可视化接口的增加会引进OOD设计的不足，使得一个好的面向对象的设计走向反面。可视化接口有三个属性可能会给应用开发带来麻烦。<BR><BR>　　第一，可视化接口提高了传统的面向操作的拓扑结构。用户产生接口事件，如开关按键和列表框选择等，受到程序的一个模块的驱动并且用来对静态的数据进行操作。在设计中将这面向操作的拓扑结构同一个面向对象的设计混合在一起将导致对象之间的大量的杂合。<BR><BR>　　第二，用户接口通常对于同样的信息经常会需要许多不同的显示。如，一个客户选择列表框可以包含一个客户的名字和电话号码以及许多其它客户的名字。<BR><BR>　　当用户选择某个特定的客户后，他／她的名字和电话号码及其它全部相关的信息都会详细地显示出来。<BR><BR>　　除此之外，一个简单的程序可能具有不同的用户接口。如一个银行账户系统有一个接口用于出纳员来访问账户平衡、存款和取款，而监督者的接口则包含另外的信息并加上账号管理的功能。这些不同的接口很容易导致类的扩展。<BR><BR>　　最后，可视化接口在整个设计阶段还会进行较大的改变。这些改变包括完全重新安排用户与系统的交互操作等。可视化接口的这些改变即使在最好的设计中也会增加应用开发的复杂性。<BR><BR>MVC弥补可视化接口/OOD的不足<BR>　　模型／界面／控制器（Model／View／Controller，MVC）编程技术允许一个开发者将一个可视化接口连接到一个面向对象的设计中，而同时还可以避免我们上面讨论的几个问题。MVC最初是为Smalltalk语言而设计的。MVC通过创建下面三个层将面向对象的设计与可视化接口分开：<BR><BR>　　模型（Model）：模型包含完成任务所需要的所有的行为和数据。模型一般由许多类组成并且使用面向对象的技术来创建满足五个设计目标的程序。<BR><BR>　　界面（View）：一个界面就是一个程序的可视化元素，如对话框、选单、工具条等。界面显示从模型中提供的数据，它并不控制数据或提供除显示外的其它行为。一个单一的程序或模型一般有两种界面行为。<BR><BR>　　控制器（Controller）：控制器将模型映射到界面中。控制器处理用户的输入，每个界面有一个控制器。它是一个接收用户输入、创建或修改适当的模型对象并且将修改在界面中体现出来的状态机。控制器在需要时还负责创建其它的界面和控制器。<BR><BR>　　控制器一直决定哪些界面和模型组件应该在某个给定的时刻是活动的，它一直负责接收和处理用户的输入，来自用户输入的任何变化都被从控制器送到模型。<BR><BR>　　界面从模型内的对象中显示数据。这些对象的改变可以通过也可以不通过用户的交互操作来完成。如：在一个Web浏览器中负责接收页面的对象收集和装配栈中的信息，必须有某种方式来让这些对象通知界面数据已经被改变了。在模型变化时有两种方法来对界面进行更新。<BR><BR>　　在第一种方法中，界面可以告诉模型它正在监视哪些对象。当这些对象中有任何一个发生变化时，一个信息就被发送给界面。界面接收这些信息并且相应地进行更新。为了避免我们上面讨论的不足，模型必须能够不用修改就支持许多种不同的界面显示。<BR><BR>　　第二个方法并不直接将界面连接到模型中，它的控制器负责在模型变化时更新界面。控制器通过对模型对象或观察器方法进行监测来检测模型中的变化。这个方法不用了解界面的模型知识，因此界面就变成是可以跨应用使用的。<BR><BR>使用MVC的优点<BR>　　MVC通过以下三种方式消除与用户接口和面向对象的设计有关的绝大部分困难：<BR><BR>　　第一，控制器通过一个状态机跟踪和处理面向操作的用户事件。这允许控制器在必要时创建和破坏来自模型的对象，并且将面向操作的拓扑结构与面向对象的设计隔离开来。这个隔离有助于防止面向对象的设计走向反面。<BR><BR>　　第二，MVC将用户接口与面向对象的模型分开。这允许同样的模型不用修改就可使用许多不同的界面显示方式。除此之外，如果模型更新由控制器完成，那么界面就可以跨应用再使用。<BR><BR>　　最后，MVC允许应用的用户接口进行大的变化而不影响模型。每个用户接口的变化将只需要对控制器进行修改，但是既然控制器包含很少的实际行为，它是很容易修改的。<BR><BR>　　面向对象的设计人员在将一个可视化接口添加到一个面向对象的设计中时必须非常小心，因为可视化接口的面向操作的拓扑结构可以大大增加设计的复杂性。<BR><BR>　　MVC设计允许一个开发者将一个好的面向对象的设计与用户接口隔离开来，允许在同样的模型中容易地使用多个接口，并且允许在实现阶段对接口作大的修改而不需要对相应的模型进行修改。<img src ="http://www.blogjava.net/qq13367612/aggbug/16890.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/qq13367612/" target="_blank">Sung</a> 2005-10-26 16:14 <a href="http://www.blogjava.net/qq13367612/articles/16890.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>在Ruby on Rails/Naked Objects精神指引下的域驱动开发框架</title><link>http://www.blogjava.net/qq13367612/articles/16547.html</link><dc:creator>Sung</dc:creator><author>Sung</author><pubDate>Mon, 24 Oct 2005 03:15:00 GMT</pubDate><guid>http://www.blogjava.net/qq13367612/articles/16547.html</guid><wfw:comment>http://www.blogjava.net/qq13367612/comments/16547.html</wfw:comment><comments>http://www.blogjava.net/qq13367612/articles/16547.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/qq13367612/comments/commentRss/16547.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/qq13367612/services/trackbacks/16547.html</trackback:ping><description><![CDATA[Ruby on Rails已经受到越来越多的重视，更多文章开始关注，<A href="http://www.onlamp.com/pub/a/onlamp/2005/01/20/rails.html" target=_blank>Rolling with Ruby on Rails</A>一文比较详细，也有国人做了翻译，<A href="http://www.koalant.com/rubyonrails.pdf%20" target=_blank>按这里</A>。这里我们不过多讨论ROR(Ruby on Rails)，而是探讨如何以一个正确的方式快速开发J2EE。
<P><STRONG>现在的问题</STRONG></P>
<P>　　现在我们J2EE开发碰到了什么问题呢？ 让我们想象一下使用Spring和Hibernate开发一个J2EE WEB应用是什么样的：我们需要增加一个新的域对象类型为Person，下面主要的开发步骤：</P>
<OL>
<LI>创建<CODE>Person</CODE>类. 
<LI>创建<CODE>PersonDAO</CODE>类. 
<LI>创建<CODE>Person数据表</CODE>. 
<LI>定义<CODE>PersonDAO在</CODE>Spring的application context XML文件. 
<LI>创建<CODE>Person</CODE> page页面和action类. 
<LI>增加<CODE>Person页面到</CODE>web框架(如struts)XML配置文件中. 
<LI>创建<CODE>personList</CODE>页面来显示<CODE>Person实例</CODE>. 
<LI>创建<CODE>personEdit</CODE>页面来编辑<CODE>Person</CODE>实例. </LI></OL>
<P>　　你会确实感慨：真是需要很多步骤啊。</P>
<P><STRONG>如何解决？</STRONG></P>
<P>　　关键问题是我们开发时不能重复一些步骤，因此必须尽量减少步骤，如果只减少步骤到:</P>
<OL>
<LI>创建<CODE>Person</CODE>类? </LI></OL>
<P>　　是否只需要第一个步骤就可以？在第一步时，我们花费更多时间精力进行域建模，确定域模型的属性行为等。其他步骤我们会发现下面的规律：</P>
<UL>
<LI>对于每个实体，我们需要完成应用的基本功能，如 create, retrieve, update, and delete (CRUD). 
<LI>我们需要每个实体持久化到数据库. 
<LI>我们需要数据库为每个实体创建数据表。 
<LI>我们需要安排实体之间的关系。 </LI></UL>
<P>　　当然，在复杂应用中，不会只是这些功能，但是如果我们将这些功能通过框架实现，将大大提高我们的开发效率。</P>
<P><STRONG>域驱动开发</STRONG></P>
<P>　　域驱动开发(domain driven development framework )，简称DDD是一种最新的OO设计概念，它是由ROR和<A href="http://www.nakedobjects.org/" target=_blank>Naked Object</A>组织提出的。</P>
<P>　　所谓naked Object是指一个复杂的域对象，这个Object是一个POJO，但是不是一个傻傻的完全是属性的POJO，而是封装了业务逻辑的POJO，注意这里是最大的区别，一般业务逻辑我们是通过另外的Service类来实现，然后在Service中封装的transaction script(Martin Fowler却称为贫血模型) ， naked Object则是合并起来的（有的类似回归传统了,符合Martin Fowler审美观了），但是，这种纯OO是和SOA()思想矛盾的(Service-Oriented vs. Object-Oriented )，可见<A id=viewpost.ascx_TitleUrl href="http://dotavery.com/blog/archive/2004/01/04/215.aspx" target=_blank>Adventures in SOA</A>(puts the business logic in service-like methods instead of on the object, service method -&gt; business method --&gt; persistence method) )</P>
<P>　　个人感觉整个软件好像一直在玩0或1的游戏，不过也许最复杂的体系就是来自最简单的抉择，如股票/汇市等投资领域也如此。</P>
<P>　　naked Object提出现在J2EE开发和裸体对象DDD开发下的图：</P>
<P><IMG height=374 src="http://www.jdon.com/artichect/images/nakedarchitecture-diagram.gif" width=600></P>
<P>　　通过这张图我们可以看到，以前方式造成J2EE开发层次之间调用混乱，修改和拓展非常不方便，而在右边的DDD开发方式下，<STRONG>界面(边界)对象就是域对象就是持久化的实体BO</STRONG>，没有多余的Contorller或Action了。原来Domain层被服务层Service layer遮挡，在右图中，则Domain层直接暴露给前台了，所以Domain没有东西被遮盖，裸露了，称为Naked(裸露) Objects.</P>
<P><STRONG>现在怎么办？</STRONG></P>
<P>　　ROR提倡的DDD方式引起了众多J2EE开发者的兴趣，在各大Java媒体正在引起广泛的讨论，但是ROR不是Java的，那么有无基于Java的DDD开发框架呢？</P>
<P>　　目前有不少DDD开发框架正在诞生中，<A href="http://www.jdon.com/jdonframework/index.htm" target=_blank>Jdon框架</A>正是在ROR这种精神指引下的一款快速开源开发框架，Jdon框架1.2.2版本虽然不是一个完全意义上的Naked Object，基于Service-Oriented 架构,但是已经初步具备上图右边开发流程，具体可参考<A href="http://www.jdon.com/jdonframework/doc/JdonFramework010.htm" target=_blank>Jdon Sample的开发流程</A></P>
<P>　　使用Jdon框架开发J2EE应用系统，最重要的一个前提是：设计好你的域对象，然后在将域对象复制到表现层，变成表现层的ActionForm/ModelForm；将域对象直接在持久层使用Hibernate/iBatis等持久化到数据库；如果使用EJB的实体Bean持久化技术，将无需实现建立数据表；应用系统部署时，J2EE容器将直接根据实体建立数据表，也可节省前面步骤中两个步骤。</P>
<P>　　当然，目前Jdon框架是采取分离手法，遵循桥模式，将抽象和行为分离，每个域对象对应一个操作它的服务类或DAO类，服务类主要用来封装业务逻辑层，然后将业务Service作为一个业务组件暴露给表现层的Controller/Action类，而Controller/Action则无需代码，只要通过如下配置即可完成：</P>
<P><FONT face=arial,sans-serif color=#000000 size=-1>&lt;model key="username" <B>class</B>=</FONT><FONT color=#00bb00>"com.jdon.framework.samples.jpetstore.domain.Account"</FONT><FONT color=black>&gt;<BR>　　&lt;actionForm name=</FONT><FONT color=#00bb00>"accountForm"</FONT><FONT color=black>/&gt; </FONT><FONT color=#0000aa>//指定边界类</FONT><FONT color=black><BR>　　&lt;handler&gt;<BR>　　　　&lt;service ref=</FONT><FONT color=#00bb00>"accountService"</FONT><FONT color=black>&gt; </FONT><FONT color=#0000aa>//指定某个业务接口</FONT><FONT color=black><BR>　　　　　　&lt;getMethod name=</FONT><FONT color=#00bb00>"getAccount"</FONT><FONT color=black>/&gt;<BR>　　　　　　&lt;createMethod name=</FONT><FONT color=#00bb00>"insertAccount"</FONT><FONT color=black>/&gt; </FONT><FONT color=#0000aa>//业务接口的新增方法</FONT><FONT color=black><BR>　　　　　　&lt;updateMethod name=</FONT><FONT color=#00bb00>"updateAccount"</FONT><FONT color=black>/&gt; </FONT><FONT color=#0000aa>//业务接口的修改方法</FONT><FONT color=black><BR>　　　　　　&lt;deleteMethod name=</FONT><FONT color=#00bb00>"deleteAccount"</FONT><FONT color=black>/&gt;<BR>　　　　&lt;/service&gt;<BR>　　　　&lt;/handler&gt;<BR>&lt;/model&gt;</FONT></P>
<P>　　通过上述配置，净化了上图中应用控制层(Application or Controller layer)和Domain Layer之间对应关系，变得有条理而且明晰。</P>
<P>　　随着Naked Object 被越来越多人认识和应用成熟，Jdon框架也将转向支持另外一个纯OO流派Naked Object， 就象它同时支持POJO派和EJB派一样。 </P>
<P>　　在Jdon框架以后版本中，会很方便支持Naked Object，只要将上面配置文件指向Service去除，CRUD方法由Model自己实现，如下：</P>
<P><FONT face=arial,sans-serif color=#000000 size=-1>&lt;model key="username" <B>class</B>=</FONT><FONT color=#00bb00>"com.jdon.framework.samples.jpetstore.domain.Account"</FONT><FONT color=black>&gt;<BR>　　&lt;actionForm name=</FONT><FONT color=#00bb00>"accountForm"</FONT><FONT color=black>/&gt; </FONT><FONT color=#0000aa>//指定边界类</FONT><FONT color=black><BR>　　&lt;handler&gt;<BR>　　　&lt;!--　&lt;service ref=</FONT><FONT color=#00bb00>"accountService"</FONT><FONT color=black>&gt; </FONT><FONT color=#0000aa>//指定某个业务接口</FONT><FONT color=black> 无需业务层，去除--&gt; <BR>　　　　　　&lt;getMethod name=</FONT><FONT color=#00bb00>"getAccount"</FONT><FONT color=black>/&gt;<BR>　　　　　　&lt;createMethod name=</FONT><FONT color=#00bb00>"insertAccount"</FONT><FONT color=black>/&gt; </FONT><FONT color=#0000aa>//业务接口的新增方法</FONT><FONT color=black><BR>　　　　　　&lt;updateMethod name=</FONT><FONT color=#00bb00>"updateAccount"</FONT><FONT color=black>/&gt; </FONT><FONT color=#0000aa>//业务接口的修改方法</FONT><FONT color=black><BR>　　　　　　&lt;deleteMethod name=</FONT><FONT color=#00bb00>"deleteAccount"</FONT><FONT color=black>/&gt;<BR>　　 &lt;!--　　&lt;/service&gt; --&gt; <BR>　　&lt;/handler&gt;<BR>&lt;/model&gt;</FONT></P><img src ="http://www.blogjava.net/qq13367612/aggbug/16547.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/qq13367612/" target="_blank">Sung</a> 2005-10-24 11:15 <a href="http://www.blogjava.net/qq13367612/articles/16547.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Java设计模式之综述篇</title><link>http://www.blogjava.net/qq13367612/articles/16092.html</link><dc:creator>Sung</dc:creator><author>Sung</author><pubDate>Thu, 20 Oct 2005 03:03:00 GMT</pubDate><guid>http://www.blogjava.net/qq13367612/articles/16092.html</guid><wfw:comment>http://www.blogjava.net/qq13367612/comments/16092.html</wfw:comment><comments>http://www.blogjava.net/qq13367612/articles/16092.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/qq13367612/comments/commentRss/16092.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/qq13367612/services/trackbacks/16092.html</trackback:ping><description><![CDATA[<P>自从J2EE出现以来，就大大简化了在Java下的企业级开发。但是随着J2EE越来越普遍地被应用到各个领域中，开发者们渐渐意识到需要一种方法来标准化应用程序的开发过程，他们采用的方法是标准化应用程序的结构层。在结构层通常封装了一些独立于业务逻辑的复杂技术，以便在业务逻辑和底层的架构之间建立起弱连接。在个专题中将会介绍一些设计模式，通过利用这些设计模式，开发人员可以达到标准化和简化应用程序开发过程的目的。 </P>
<P><BR>应用程序结构和J2EE</P>
<P><BR>J2EE是一个很成功的技术，它为一些基本的任务提供了一致的标准，例如数据库连接、分布式应用程序等。但是使用J2EE并不能保证开发人员开发出成功的应用程序。有些人认为J2EE本身就是一种框架技术，但是这种认识是不正确的，我们应该意识到J2EE并没有提供一个能够帮助开发人员开发出高质量应用程序的框架，因此很多有经验的开发人员通过利用设计模式来弥补这一缺项。 </P>
<P><BR>设计模式</P>
<P><BR>在开发人员的圈子中，大家通过相互交流在开发过程中所遇到的问题以及解决方法来丰富整个圈子的经验。而设计模式就是在这样的情况下产生的。一个设计模式必然是针对某个特定的问题的，这个问题的解决方案以及这样解决问题产生的后果。在解决利用J2EE进行程序开发中出现的问题的过程中，人们把设计模式分为两类，一种是通用开发模式，一种是为了解决特定的J2EE问题的模式。下面让我们来看一看每一种类型的开发模式都包含了哪些内容。 </P>
<P>J2EE设计模式 </P>
<P>J2EE设计模式在过去几年中随着Java开发人员经验的不断成长而发展。这些设计模式是针对使用各种J2EE技术时可能出现的问题提出的，它们能够帮助开发人员构造出应用程序框架的要求。例如，Front Controller（前端控件）模式将servlet代码的开发转化为在图形用户界面下的开发。但是需要记住J2EE设计模型解决了那些在J2EE项目中最可能出现的问题。如果你在J2EE遇到的问题很特殊，很有可能没有相应的设计模型来解决它。 </P>
<P>软件开发设计模式 </P>
<P>软件开发设计模式又被分为两种，一种是通用的面向对象设计模式。例如工厂（Factory）模式是一种面向对象的设计模式，它将对象的创建封装起来，使对象能够重用，这样就可以减少程序占用的系统资源。而另一种是基于Java的设计模式，这些设计模式要么是和Java的语言特性结合得很紧，要么是面向对象技术在Java中的深化。不要以为软件设计模式相对独立于J2EE就认为它们不重要，通常它们比J2EE设计模式更重要。这是因为： </P>
<P>1）J2EE设计模式是近几年才出现的，并且在不断变化，而软件开发设计模式经过了长时间的考验，比前者更加成熟和完善； </P>
<P>2）有些J2EE设计模式是建立在某些软件开发设计模式之上的； </P>
<P>3）软件开发模式为J2EE设计模式提供了坚实的基础。它的应用将影响到整个结构的稳定性和可扩充性。 </P>
<P>在实际应用中，设计模式并不是一段具体的代码。设计模式通常是在设计说明书中描述。将设计模式应用到系统中的真正挑战在于如何在系统中应用模式中的思想。这些思想必须被应用到恰当的环境中。 </P>
<P>根据设计模式的所解决的问题，又可以分为以下几个类型： </P>
<P>· 创建类型：创建类型的模式都是用于创建类的实例。但是和通过new来创建实例不同，这些模式提供了更加灵活的方式，是程序能够根据特定的情况创建特定的类。 </P>
<P>· 结构类型：结构类型的模式帮助开发人员将简单对象组合在一起以后的更加复杂的结构。 </P>
<P>· 行为类型：行为类型的模式帮助开发人员控制类之间的通讯。 </P>
<P>创建类型的模式 </P>
<P>所有创建类型的模式都和如何有效地创建类的实例相关。在Java中，如果开发人员要生成一个类的实例，最简单的方法是使用new关键字： </P>
<P>MyFoo = new Foo();  // 生成一个Foo的实例<BR> </P>
<P><BR>这种方法只能够在程序中生成固定的类。但是在很多情况下，程序需要根据不同的情况生成不同的类的实例，这就需要将实例的生成过程抽象到一个特殊的创建类中，由该类在运行时决定生成哪种类的实例。这样使得程序有更好的灵活性和通用性。 </P>
<P>创建类型的模式包括： </P>
<P>· 工厂模式（Factory Pattern）：根据工厂模式实现的类可以根据提供的数据生成一组类中某一个类的实例，而这一组类有一个公共的抽象父类。 </P>
<P>· 抽象工厂模式（Abstract Factory Pattern）：抽象工厂模式也可以根据提供的数据生成一组类中某一个类的实例，而这一组类有一个公共的抽象父类。只不过它定义的是一个接口。 </P>
<P>· 构造者模式（Builder Pattern）：构造者模式将一个复杂对象的构造过程和它的表现层分离开来，这样类就可以根据不同情况展现出不同的表现方式。 </P>
<P>· 原型模式（Prototype Pattern）：原型模式通过对类的实例进行拷贝来创建新的实例。 </P>
<P>· 单一模式（Singleton Pattern）：根据单一模式实现的类只允许有一个是类，并且提供了一个全局指针来引用该实例。 </P>
<P>结构类型的模式 </P>
<P>结构类型的模式将类和对象组合起来，以构成更加复杂的结构。它又被划分为类模式和对象模式。类模式和对象模式之间的区别在于类模式通过继承关系来提供有效的接口；而类模式通过对象合成或将对象包含在其它对象中的方式构成更加复杂的结构。 </P>
<P>结构类型的模式包括了以下模式： </P>
<P>· 适配器模式（Adapter Pattern）：适配器模式可以将一个类的接口和另一个类的接口匹配起来。 </P>
<P>· 桥梁模式（Bridge Pattern）：桥梁模式对客户端程序提供一个固定的接口，但是允许开发人员变化实际的实现类。这样开发人员就可以将接口是具体的实现类分离开来。 </P>
<P>· 复合模式（Composite Pattern）：复合模式可以将多个对象进行复合，其中的每个对象可以是简单对象，也可以是复合对象。 </P>
<P>· 代理模式（Proxy Pattern）：代理模式利用一个简单的对象替代一个复杂的对象，当复杂对象在需要的时候才会被加载到系统中，这样可以节约系统资源，提高系统的响应速度。在网络环境中这种模式很有用处。 </P>
<P>· 修饰模式（Decorator Pattern）：通过修饰模式，开发人员可以在运行时将特定的功能绑定在对象上。 </P>
<P>· 轻量模式（Flyweight Pattern）：轻量模式通过将对象中的一部分数据保存在对象外，在调用对象中的方法时再将这些数据传回对象。这样做可以减少大量比较简单的对象占用的空间。 </P>
<P>· 正面模式（Fa?ade Pattern）：正面模式将复杂的类层次结构组织起来，通过一个简单的接口来获得层次结构中的数据。 </P>
<P>行为类型的模式 </P>
<P>行为类型的模式主要是那些处理对象之间通讯的模式，该类型的包括以下模式： </P>
<P>· 观测者模式（Observer Pattern）：观测者模式可以在发生变化时将变化通知多个类。 </P>
<P>· 中介模式（Mediator Pattern）：中介模式可以通过一个中间类来控制若干个类之间的通讯，并且这些类相互之间不需要了解对方的信息。 </P>
<P>· 回忆模式（Memento Pattern）：回忆模式可以在不破坏对象封装性的前提下保存和恢复对象的内部状态。 </P>
<P>· 职责链模式（Chain of Responsibility）：职责链模式将请求传递给一组对象，只有特定的对象才会处理该请求。这样就进一步削弱类之间的联系。 </P>
<P>· 命令模式（Command Pattern）：命令模式将请求传递给特定的对象，这样客户端即使在不知道服务器端如何处理请求的情况下也可以发送请求。 </P>
<P>· 模板模式（Template Pattern）：模板模式提供了对算法的抽象定义。 </P>
<P>· 策略模式（Strategy Pattern）: 策略模式定义了一组算法，将每个算法都封装起来，并且使它们之间可以互换。策略模式使这些算法在客户端调用它们的时候能够互不影响地变化。 </P>
<P>· 访问者模式（Visitor Pattern）：访问者模式通过一个访问类来访问其他类中的数据。 </P>
<P>· 状态模式（State Pattern）：状态模式将一个类实例的变量保存在独立的内存空间中。 </P>
<P>· 迭代模式（Iterator Pattern）：迭代模式在不知道数据的内部表现形式的前提下，通过标准的接口来遍历数据集合中的数据。 <BR></P><img src ="http://www.blogjava.net/qq13367612/aggbug/16092.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/qq13367612/" target="_blank">Sung</a> 2005-10-20 11:03 <a href="http://www.blogjava.net/qq13367612/articles/16092.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Web services設計模式--企業觀點</title><link>http://www.blogjava.net/qq13367612/articles/16019.html</link><dc:creator>Sung</dc:creator><author>Sung</author><pubDate>Sat, 15 Oct 2005 08:56:00 GMT</pubDate><guid>http://www.blogjava.net/qq13367612/articles/16019.html</guid><wfw:comment>http://www.blogjava.net/qq13367612/comments/16019.html</wfw:comment><comments>http://www.blogjava.net/qq13367612/articles/16019.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/qq13367612/comments/commentRss/16019.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/qq13367612/services/trackbacks/16019.html</trackback:ping><description><![CDATA[<P class=MsoNormal style="TEXT-JUSTIFY: inter-ideograph; LAYOUT-GRID-MODE: char; TEXT-ALIGN: justify"><B><SPAN style="FONT-SIZE: 20pt; FONT-FAMILY: 標楷體">三部曲<SPAN lang=EN-US>:Web services之規劃策略</SPAN></SPAN></B></P>
<P class=MsoNormal style="TEXT-JUSTIFY: inter-ideograph; LAYOUT-GRID-MODE: char; TEXT-INDENT: 26.9pt; TEXT-ALIGN: justify"><B><SPAN lang=EN-US style="FONT-SIZE: 14pt; FONT-FAMILY: 標楷體"></SPAN></B> </P>
<P class=MsoNormal style="LAYOUT-GRID-MODE: char; TEXT-INDENT: 26.9pt; TEXT-ALIGN: right" align=right><B><SPAN style="FONT-SIZE: 14pt; FONT-FAMILY: 標楷體">李清培</SPAN></B></P>
<P class=MsoNormal style="LAYOUT-GRID-MODE: char; WORD-BREAK: break-all; TEXT-ALIGN: right" align=right><B><SPAN style="FONT-SIZE: 14pt; FONT-FAMILY: 標楷體">弈飛資訊首席顧問<SPAN lang=EN-US> /台灣微軟特約資深</SPAN></SPAN></B><B><SPAN style="FONT-SIZE: 14pt; FONT-FAMILY: 標楷體">講師</SPAN></B></P>
<P class=MsoNormal style="TEXT-JUSTIFY: inter-ideograph; LAYOUT-GRID-MODE: char; TEXT-INDENT: 26.9pt; TEXT-ALIGN: justify"><B><SPAN lang=EN-US style="FONT-SIZE: 14pt; FONT-FAMILY: 標楷體"></SPAN></B> </P>
<P class=MsoNormal style="TEXT-JUSTIFY: inter-ideograph; LAYOUT-GRID-MODE: char; TEXT-INDENT: 26.9pt; TEXT-ALIGN: justify"><B><SPAN style="FONT-SIZE: 14pt; FONT-FAMILY: 標楷體">在上一篇文章中，我們談到了</SPAN></B><B><SPAN style="FONT-SIZE: 14pt; FONT-FAMILY: 標楷體">以<SPAN lang=EN-US>Web services作為存取介面的服務導向應用程式架構</SPAN></SPAN></B><B><SPAN style="FONT-SIZE: 14pt; FONT-FAMILY: 標楷體">，以及其與企業應用程式之間的關聯；其中最重要的關鍵點在於如何利用“服務導向的應用程式架構”滿足企業應用程式強烈的<SPAN lang=FR> </SPAN>“彈性”與“整合” 之需求<SPAN lang=FR> </SPAN>。這個月，我們將進一步的談談，如何將<SPAN lang=FR>Web services</SPAN>應用在真實的企業環境，以及其規劃策略。</SPAN></B></P>
<P class=MsoNormal style="TEXT-JUSTIFY: inter-ideograph; LAYOUT-GRID-MODE: char; TEXT-ALIGN: justify"><B><SPAN lang=FR style="FONT-SIZE: 20pt; FONT-FAMILY: 標楷體">Web services</SPAN></B><B><SPAN style="FONT-SIZE: 20pt; FONT-FAMILY: 標楷體">企業運用設計模式</SPAN></B></P>
<P class=MsoNormal style="TEXT-JUSTIFY: inter-ideograph; LAYOUT-GRID-MODE: char; TEXT-INDENT: 26.9pt; TEXT-ALIGN: justify"><B><SPAN style="FONT-SIZE: 14pt; FONT-FAMILY: 標楷體">在談到如何將<SPAN lang=FR>Web services</SPAN></SPAN></B><B><SPAN style="FONT-SIZE: 14pt; FONT-FAMILY: 標楷體">導入到企業的系統架構中之前</SPAN></B><B><SPAN style="FONT-SIZE: 14pt; FONT-FAMILY: 標楷體">，還要再強調一次，雖然在以下的各種應用模式中，使用的是<SPAN lang=FR>Internet</SPAN>的技術，但<SPAN lang=FR>Internet</SPAN></SPAN></B><B><SPAN style="FONT-SIZE: 14pt; FONT-FAMILY: 標楷體">只是</SPAN></B><B><SPAN lang=FR style="FONT-SIZE: 14pt; FONT-FAMILY: 標楷體">Web services</SPAN></B><B><SPAN style="FONT-SIZE: 14pt; FONT-FAMILY: 標楷體">的手段</SPAN></B><B><SPAN style="FONT-SIZE: 14pt; FONT-FAMILY: 標楷體">，</SPAN></B><B><SPAN style="FONT-SIZE: 14pt; FONT-FAMILY: 標楷體">而非</SPAN></B><B><SPAN lang=FR style="FONT-SIZE: 14pt; FONT-FAMILY: 標楷體">Web services</SPAN></B><B><SPAN style="FONT-SIZE: 14pt; FONT-FAMILY: 標楷體">的目的。<SPAN lang=EN-US>Web services不是只為了Internet而設計，重點在於他是一種使用標準技術的分散式應用程式。</SPAN></SPAN></B></P>
<P class=MsoNormal style="TEXT-JUSTIFY: inter-ideograph; LAYOUT-GRID-MODE: char; TEXT-INDENT: 26.9pt; TEXT-ALIGN: justify"><B><SPAN style="FONT-SIZE: 14pt; FONT-FAMILY: 標楷體">分散式應用程式讓企業在建置資訊系統時不論在採購上或建置上都更為彈性，企業可依需要不斷的擴充系統，而不需在初期即一次購足；企業也可以將系統以功能模組的方式分階段建置或升級；企業也可以依實際需求，將資料庫或資訊系統分布在不同的地方，再以網路加以連結。分散式應用程式有助於將商業邏輯集中管理，並取得較佳的安全機制，另外在伺服器與資料庫資源的充分利用以及多樣化的用戶端的設計模式，更是分散式應用程式所帶來的好處。</SPAN></B></P>
<P class=MsoNormal style="TEXT-JUSTIFY: inter-ideograph; LAYOUT-GRID-MODE: char; TEXT-INDENT: 26.9pt; TEXT-ALIGN: justify"><B><SPAN style="FONT-SIZE: 14pt; FONT-FAMILY: 標楷體">然而隨著市場全球化以及網路經濟的成形，雖然給了分散式應用程式一個絕佳的揮灑空間。卻也因此突顯了一個嚴重的問題，也就是在上一篇文章中所提到異質平台的問題。理論上，分散式應用程式只要設計得當，便可以將分散在各地的系統與資料整合成一個抽象的大系統，但由於各家系統廠商所使用的技術不同，以及新舊系統技術與設計概念不同，所導致的不相容問題，使得分散式運算的優點大打折扣。因此在發展新一代分散式應用程式時，就企業觀點而言首先必須解決的，是企業內系統整合的問題，包括資料的整合與應用程式的整合，如何讓異質平台或新舊系統間的資料能互通，以及新開發的應用程式能繼續使用舊系統或異質平台的應用程式，以保留就有投資的價值。再來則是跨企業間的程式互通，包括<SPAN lang=EN-US>B2B的電子商務，以及供應鏈的整合。最後則是各應用程式的流程整合。而Web services則是符合這些需求的重要技術。</SPAN></SPAN></B></P>
<P class=MsoNormal style="TEXT-JUSTIFY: inter-ideograph; LAYOUT-GRID-MODE: char; TEXT-INDENT: 26.9pt; TEXT-ALIGN: justify"><B><SPAN style="FONT-SIZE: 14pt; FONT-FAMILY: 標楷體">除了解決企業全球化與網路化的整合需求以外，延伸自<SPAN lang=EN-US>Web services的特殊技術，也為企業帶來了另一種商業價值，這種價值來至於Web services的商品化，也就是在上一篇題到的軟體服務。這種直接出售Web services的軟體服務，包括功能性的隨選服務 (Services-on-Demand)，以及組成應用程式的軟體積木等。</SPAN></SPAN></B></P>
<P class=MsoNormal style="TEXT-JUSTIFY: inter-ideograph; LAYOUT-GRID-MODE: char; TEXT-INDENT: 26.9pt; TEXT-ALIGN: justify"><B><SPAN style="FONT-SIZE: 14pt; FONT-FAMILY: 標楷體">接下來我們就一一的介紹如何將<SPAN lang=EN-US>Web services導入到企業的真實環境，以及其規劃策略與所帶來的好處。</SPAN></SPAN></B></P>
<P class=MsoNormal style="TEXT-JUSTIFY: inter-ideograph; LAYOUT-GRID-MODE: char; TEXT-ALIGN: justify"><B><SPAN style="FONT-SIZE: 20pt; FONT-FAMILY: 標楷體">企業應用程式的整合</SPAN></B></P>
<P class=MsoNormal style="TEXT-JUSTIFY: inter-ideograph; LAYOUT-GRID-MODE: char; TEXT-INDENT: 26.9pt; TEXT-ALIGN: justify"><B><SPAN style="FONT-SIZE: 14pt; FONT-FAMILY: 標楷體">對於許多企業而言，使用<SPAN lang=EN-US> Web services 的第一個實作通常會是內部應用程式的整合。利用 Web services 延伸或擴充原有應用程式的功能，或將不同系統，以 Web services 加以連結或整合。</SPAN></SPAN></B></P>
<P class=MsoNormal style="LAYOUT-GRID-MODE: char; TEXT-ALIGN: center" align=center><B><SPAN lang=EN-US style="FONT-SIZE: 14pt; FONT-FAMILY: 標楷體"><IMG height=217 src="http://move-to.net/Comm/Document/9_image001.jpg" width=360></SPAN></B></P>
<P class=MsoNormal style="TEXT-JUSTIFY: inter-ideograph; LAYOUT-GRID-MODE: char; TEXT-INDENT: 26.9pt; TEXT-ALIGN: justify"><B><SPAN style="FONT-SIZE: 14pt; FONT-FAMILY: 標楷體">企業應用程式整合工作如果加以細分，包括應用程式的整合、資料整合、與流程整合。關於流程整合在後面再來談。應用程式與資料的整合需求對許多企業來講是很重要的議題。當企業合併或併購時，原本不同企業的資訊系統需要整合成一個完整的資訊系統；開發新的系統必須與舊的系統整合；企業因需求與設計考量，將原本集中式大型主機系統改為分散式應用程式系統時也需要整合，尤其當系統或資料庫是分散在各地時，必須透過<SPAN lang=EN-US>Internet整合加以整合；再來則是企業再進行軟體採購或委外服務時，為了符合最佳的經濟效率或協力廠商使用技術的限制，常無法取得與原有系統相同技術或平台之解決方案，這時候也需要整合。</SPAN></SPAN></B></P>
<P class=MsoNormal style="TEXT-JUSTIFY: inter-ideograph; LAYOUT-GRID-MODE: char; TEXT-INDENT: 26.9pt; TEXT-ALIGN: justify"><B><SPAN style="FONT-SIZE: 14pt; FONT-FAMILY: 標楷體">企業應用程式整合的市場仍相當龐大，而每個專案動則花費數百甚至數千萬的預算。目前市場上整合的解決方案很多，但大多是一對一的整合，典型的像連結<SPAN lang=EN-US>MSMQ與MQSeries的FalconMQ。 Web services 則提供另一種全然不同的方法，利用實作標準介面的方式，進行多點的整合。只要將現有的傳統系統可以包裝成Web Service ，便可與企業內的其他系統整合使用。利用這種技術，將複雜的舊系統包裝在標準的XML之後，以Web services的標準溝通介面，取代原有一對一的整合方式，同時在規劃時，還可以依需要，僅選擇一部分或全部的功能作為整合的介面。</SPAN></SPAN></B></P>
<P class=MsoNormal style="TEXT-JUSTIFY: inter-ideograph; LAYOUT-GRID-MODE: char; TEXT-ALIGN: justify"><B><SPAN style="FONT-SIZE: 20pt; FONT-FAMILY: 標楷體">供應鏈的建立與開發</SPAN></B></P>
<P class=MsoNormal style="TEXT-JUSTIFY: inter-ideograph; LAYOUT-GRID-MODE: char; TEXT-INDENT: 26.9pt; TEXT-ALIGN: justify"><B><SPAN style="FONT-SIZE: 14pt; FONT-FAMILY: 標楷體">另一個驅動<SPAN lang=EN-US> Web services 發展的主要力量則為 B2B 的商業模式。有人甚至斷言供應鏈整合將會是最具威力的 Web services 應用程式。主要是因為供應鏈影響的範圍廣，而 Web services 提供供應鏈應用程式所需之 XML 及相關之產業標準。在一份由InfoWorld (<A href="http://www.infoworld.com/" target=_blank>http://www.InfoWorld.com</A>) 針對CTO所作的調查統計，70%的CTO認為Web services 對企業最有影響的是在B2B電子商務上。B2B應用程式可以像信用卡驗證這樣簡單或者像產業的供應鏈這樣複雜的程式。建置B2B應用程式的挑戰結合B2B背後的廣大市場潛力是驅使Web Service快速改進的原動力。</SPAN></SPAN></B></P>
<P class=MsoNormal style="LAYOUT-GRID-MODE: char; TEXT-ALIGN: center" align=center><B><SPAN lang=EN-US style="FONT-SIZE: 14pt; FONT-FAMILY: 標楷體"><IMG height=240 src="http://move-to.net/Comm/Document/9_image002.jpg" width=372 border=0></SPAN></B></P>
<P class=MsoNormal style="TEXT-JUSTIFY: inter-ideograph; LAYOUT-GRID-MODE: char; TEXT-INDENT: 26.9pt; TEXT-ALIGN: justify"><B><SPAN style="FONT-SIZE: 14pt; FONT-FAMILY: 標楷體">台灣的<SPAN lang=EN-US>B2B計畫，最重要的應該是由經濟部技術處主導的A、B、C、D、E計畫。其中A計畫，讓HP、Compaq、IBM將採購資訊下放到台灣來；B計畫則把華碩、仁寶、英業達等15家台灣廠商的資訊與美國採購商搭上線，讓台灣的製造業在世界PC市場上，保住一年180億美元的市場。A、B計畫的核心，是以「大廠為中心廠，帶動下游供應商加入」的垂直聯結方式，藉由Internet將市場變動的資訊，即時回饋到計畫中的產業，讓廠商可以針對變動來調整庫存。</SPAN></SPAN></B></P>
<P class=MsoNormal style="TEXT-JUSTIFY: inter-ideograph; LAYOUT-GRID-MODE: char; TEXT-INDENT: 26.9pt; TEXT-ALIGN: justify"><B><SPAN style="FONT-SIZE: 14pt; FONT-FAMILY: 標楷體">另一個不同於<SPAN lang=EN-US>A、B計畫的，則是由下游零組件大廠明基與資策會合作的「星動計畫」，在這個計畫中，Internet所連結的是一種水平溝通的電子交易平台（Hub），以「水平」的產業平台，取代「垂直」的供應鏈體系。星動計畫是以資策會開發的viaHub作為公共平台，讓參與廠商、供應商之間可以跨越不同的系統平台作RosettaNet的資料存取。</SPAN></SPAN></B></P>
<P class=MsoNormal style="TEXT-JUSTIFY: inter-ideograph; LAYOUT-GRID-MODE: char; TEXT-INDENT: 26.9pt; TEXT-ALIGN: justify"><B><SPAN style="FONT-SIZE: 14pt; FONT-FAMILY: 標楷體">除了製造業以外，傳統各產業之間其實都存著一套共通的電子交換格式<SPAN lang=EN-US>EDI以進行B2B的資料交換，不同於Web services的是，這些交換格式都並須建立產業間特殊的交換平台與資料格式或規範，而Web services不需要特定平台，Internet本身就是一個很好的平台，只需依XML的規範，定義各產業的Schema，即可在共通的標準上進行交易，利用Web services建置的好處在於他的建置成本低，參與的廠商利用Web services的標準規範建置溝通介面，只需按照各產業所訂的標準定義描述資料的名詞及內容格式即可，例如一筆訂單資料應包含哪幾個項目，訂單是用Orders還是PO來表示等。另外一個好處在於這樣的規範還可以是跨產業的，B2B不是只有供應鏈而已，還必須考慮金流、物流等，這些都會應用到跨產業的溝通方式。因此，以Web services作為B2B溝通介面的規劃策略，具有相當大的彈性與經濟效益，也因此有些權威人士認為供應鏈整合將會是一個殺手級的Web Service 應用程式。</SPAN></SPAN></B></P>
<P class=MsoNormal style="TEXT-JUSTIFY: inter-ideograph; LAYOUT-GRID-MODE: char; TEXT-ALIGN: justify"><B><SPAN style="FONT-SIZE: 20pt; FONT-FAMILY: 標楷體">現有與未來應用程式的擴充</SPAN></B></P>
<P class=MsoNormal style="TEXT-JUSTIFY: inter-ideograph; LAYOUT-GRID-MODE: char; TEXT-INDENT: 26.9pt; TEXT-ALIGN: justify"><B><SPAN style="FONT-SIZE: 14pt; FONT-FAMILY: 標楷體">由於目前個人所能取得的數位週邊設備相當豐富，除傳統<SPAN lang=EN-US>PC與筆記型電腦以外，PDA、手機、簡訊等，使得用戶端程式的客製化顯得非常重要，其中尤以手機最為嚴重，由於消費性產品的市場化，各家在樣式上求新求變，使程式開發工作更為困難。Web services 繼承自分散式應用程式商業邏輯集中的優點，可以快速開發多樣化的用戶端程式。只要將商業邏輯以Web services呈現，再針對不同用戶端撰寫資料展示的方式就可以了。目前市場上的用戶端程式開發工具，大多數都支援Web services的存取，其中Visual Studio .NET更可以在單一的畫面裡面，完成所有應用程式的開發。</SPAN></SPAN></B></P>
<P class=MsoNormal style="TEXT-JUSTIFY: inter-ideograph; LAYOUT-GRID-MODE: char; TEXT-INDENT: 26.9pt; TEXT-ALIGN: justify"><B><SPAN style="FONT-SIZE: 14pt; FONT-FAMILY: 標楷體">然而對大部分的企業而言，許多的商業邏輯都已寫完，而且行之多年，不可能為了開發一隻手機的程式，而將整個程式重寫。前面提到，<SPAN lang=EN-US>Web Service提供一組吸引人的技術，就是將現有的傳統系統包裝成Web Service ，以提供其他應用程式使用。藉由這種方式，不只可以享有Web services所帶來的便利，更可因此延伸原有應用程式的生命週期。</SPAN></SPAN></B></P>
<P class=MsoNormal style="TEXT-JUSTIFY: inter-ideograph; LAYOUT-GRID-MODE: char; TEXT-INDENT: 26.9pt; TEXT-ALIGN: justify"><B><SPAN style="FONT-SIZE: 14pt; FONT-FAMILY: 標楷體">在這裡舉一個典型的例子，在擔任<SPAN lang=EN-US>.NET開發技術的講師與顧問的兩年多時間裡，</SPAN></SPAN></B></P>
<P class=MsoNormal style="TEXT-JUSTIFY: inter-ideograph; LAYOUT-GRID-MODE: char; TEXT-INDENT: 26.9pt; TEXT-ALIGN: justify"><B><SPAN lang=EN-US style="FONT-SIZE: 14pt; FONT-FAMILY: 標楷體"> 最常碰到的問題是有關ASP.NET網頁設計的問題。由於ASP.NET提供像VB開發視窗程式一樣拖曳的視覺化開發環境，使得很多人就習慣性的將兩者拿來比，但事實上這兩者還是有差異的。網頁的程式，由於透過Internet在伺服器上執行完畢後，再將結果傳回用戶端展示層，因此有其先天上的限制。</SPAN></B></P>
<P class=MsoNormal style="LAYOUT-GRID-MODE: char; TEXT-ALIGN: center" align=center><B><SPAN lang=EN-US style="FONT-SIZE: 14pt; FONT-FAMILY: 標楷體"><IMG height=334 src="http://move-to.net/Comm/Document/9_image003.jpg" width=408 border=0></SPAN></B></P>
<P class=MsoNormal style="TEXT-JUSTIFY: inter-ideograph; LAYOUT-GRID-MODE: char; TEXT-INDENT: 26.9pt; TEXT-ALIGN: justify"><B><SPAN style="FONT-SIZE: 14pt; FONT-FAMILY: 標楷體">很多人會希望能符合老闆以及市場形象的需求，使用<SPAN lang=EN-US>Web based的架構，(在一些特殊的個案中，企業選擇Web based的原因是因為老闆認為這樣才跟得上時代)但用希望像視窗程式一樣的使用者操作介面，其實透過Web services就可以解決這樣的問題。</SPAN></SPAN></B></P>
<P class=MsoNormal style="LAYOUT-GRID-MODE: char; TEXT-ALIGN: center" align=center><B><SPAN lang=EN-US style="FONT-SIZE: 14pt; FONT-FAMILY: 標楷體"><IMG height=295 src="http://move-to.net/Comm/Document/9_image004.jpg" width=468 border=0></SPAN></B></P>
<P class=MsoNormal style="TEXT-JUSTIFY: inter-ideograph; LAYOUT-GRID-MODE: char; TEXT-INDENT: 26.9pt; TEXT-ALIGN: justify"><B><SPAN style="FONT-SIZE: 14pt; FONT-FAMILY: 標楷體">另外一種則應用程式擴充的例子，則是將應用程式系統分為核心程式與服務程式，將必要的程式邏輯部分也在核心程式，在以<SPAN lang=EN-US>Web services的方式依功能分類，撰寫各個服務程式。可以將核心程式當作是主機板與CPU等重要元件，而各個服務程式則有如週邊設備一樣,可依需要隨時擴增。</SPAN></SPAN></B></P>
<P class=MsoNormal style="LAYOUT-GRID-MODE: char; TEXT-ALIGN: center" align=center><B><SPAN lang=EN-US style="FONT-SIZE: 14pt; FONT-FAMILY: 標楷體"><IMG height=301 src="http://move-to.net/Comm/Document/9_image005.jpg" width=420 border=0></SPAN></B></P>
<P class=MsoNormal style="TEXT-JUSTIFY: inter-ideograph; LAYOUT-GRID-MODE: char; TEXT-INDENT: 26.9pt; TEXT-ALIGN: justify"><B><SPAN lang=EN-US style="FONT-SIZE: 14pt; FONT-FAMILY: 標楷體"></SPAN></B> </P>
<P class=MsoNormal style="TEXT-JUSTIFY: inter-ideograph; LAYOUT-GRID-MODE: char; TEXT-ALIGN: justify"><B><SPAN style="FONT-SIZE: 20pt; FONT-FAMILY: 標楷體">降低系統建置的時間與成本</SPAN></B></P>
<P class=MsoNormal style="TEXT-JUSTIFY: inter-ideograph; LAYOUT-GRID-MODE: char; TEXT-INDENT: 26.9pt; TEXT-ALIGN: justify"><B><SPAN style="FONT-SIZE: 14pt; FONT-FAMILY: 標楷體">除了解決應用系統整合與溝通上的問題外</SPAN></B><B><SPAN style="FONT-SIZE: 14pt; FONT-FAMILY: 標楷體">，</SPAN></B><B><SPAN style="FONT-SIZE: 14pt; FONT-FAMILY: 標楷體">對於新系統的開發</SPAN></B><B><SPAN style="FONT-SIZE: 14pt; FONT-FAMILY: 標楷體">，<SPAN lang=FR>Web services</SPAN></SPAN></B><B><SPAN style="FONT-SIZE: 14pt; FONT-FAMILY: 標楷體">也可以降低開發的時間與成本</SPAN></B><B><SPAN style="FONT-SIZE: 14pt; FONT-FAMILY: 標楷體">，這一類的設計模式大概可分為幾種狀況。</SPAN></B></P>
<P class=MsoNormal style="TEXT-JUSTIFY: inter-ideograph; LAYOUT-GRID-MODE: char; TEXT-INDENT: 26.9pt; TEXT-ALIGN: justify"><B><SPAN style="FONT-SIZE: 14pt; FONT-FAMILY: 標楷體">第一種稱為軟體積木的開發方式，</SPAN></B><B><SPAN style="FONT-SIZE: 14pt; FONT-FAMILY: 標楷體">企業直接利用</SPAN></B><B><SPAN lang=FR style="FONT-SIZE: 14pt; FONT-FAMILY: 標楷體">Internet</SPAN></B><B><SPAN style="FONT-SIZE: 14pt; FONT-FAMILY: 標楷體">上的</SPAN></B><B><SPAN lang=FR style="FONT-SIZE: 14pt; FONT-FAMILY: 標楷體">Web services</SPAN></B><B><SPAN style="FONT-SIZE: 14pt; FONT-FAMILY: 標楷體">，以軟體積木的方式，加快系統開發的速度，尤其對於一些輔助性的功能，或一些共通的商業智慧。在上一篇文章中，我們也舉了<SPAN lang=FR>Google</SPAN>的例子，</SPAN></B><B><SPAN style="FONT-SIZE: 14pt; FONT-FAMILY: 標楷體">您可以直接使用</SPAN></B><B><SPAN lang=FR style="FONT-SIZE: 14pt; FONT-FAMILY: 標楷體"> Google </SPAN></B><B><SPAN style="FONT-SIZE: 14pt; FONT-FAMILY: 標楷體">所提供的</SPAN></B><B><SPAN lang=FR style="FONT-SIZE: 14pt; FONT-FAMILY: 標楷體"> Web services</SPAN></B><B><SPAN style="FONT-SIZE: 14pt; FONT-FAMILY: 標楷體">，</SPAN></B><B><SPAN style="FONT-SIZE: 14pt; FONT-FAMILY: 標楷體">就可在應用程式中加入此一功能。除此以外，由微軟所提供的<SPAN lang=EN-US>.NET My Service也提供了非常多的軟體積木可供使用，其中最為熟悉的應屬Passport驗證機制。</SPAN></SPAN></B></P>
<P class=MsoNormal style="TEXT-JUSTIFY: inter-ideograph; LAYOUT-GRID-MODE: char; TEXT-INDENT: 26.9pt; TEXT-ALIGN: justify"><B><SPAN style="FONT-SIZE: 14pt; FONT-FAMILY: 標楷體">另外對於新市場的開發，企業往往必須重新熟悉這一個市場的商業邏輯或專門的技術，而透過<SPAN lang=EN-US>Web services的服務即可快速的修正系統的功能，以加快新市場的開拓。例如企業在進行全球貿易時，除了基本的商務應用程式外，可能還會建立連接貨運倉儲部門與國際貨運公司間的B2B運輸系統。這樣的系統通常是以緊密結合的方式所建立，也就是企業的資料庫裡，必須知道貨運公司的價格、航班、週期、速度等。當企業的業務拓展到新的國家時，如果原有的貨運公司無法到達時，這時候只有兩種選擇，第一是放棄市場，第二是重新洽談另一家貨運公司，重新改寫程式。但如果反過來，這些B2B的關係是建立在Web services的連結上，只要透過UDDI找到所需的服務，便可輕易的進入新市場。</SPAN></SPAN></B></P>
<P class=MsoNormal style="TEXT-JUSTIFY: inter-ideograph; LAYOUT-GRID-MODE: char; TEXT-INDENT: 26.9pt; TEXT-ALIGN: justify"><B><SPAN style="FONT-SIZE: 14pt; FONT-FAMILY: 標楷體">再來則是企業在提供全球技術服務時，也可以利用<SPAN lang=EN-US>Web services來達到技術支援的目的。例如目前主要汽車大廠的服務點都以全球部署作為其市場競爭的利器。而針對高階人士設計的筆記型電腦，為因應國際商務的需求，也都強調全球保固的服務。然而這也衍生一個問題，由於服務點遍佈全球，各地的技術水平並不一致，如何達到相同的服務品質，則是一個很大的考驗。</SPAN></SPAN></B></P>
<P class=MsoNormal style="TEXT-JUSTIFY: inter-ideograph; LAYOUT-GRID-MODE: char; TEXT-INDENT: 26.9pt; TEXT-ALIGN: justify"><B><SPAN style="FONT-SIZE: 14pt; FONT-FAMILY: 標楷體">以汽車廠為例，假設今天擁有一部數百萬的進口名車，在台灣要找到維護場並不難，但今天如果在某些落後國家，狀況可能不一樣了，即使原廠所設的服務點，也會應當地的技術人力，而有所不同。幸運的是，目前大多進口名車都採取電腦診斷的方式以進行故障排除，因此只要能提供詳細的檢修步驟，讓維修人員按照步驟完成檢修工作。</SPAN></B></P>
<P class=MsoNormal style="TEXT-JUSTIFY: inter-ideograph; LAYOUT-GRID-MODE: char; TEXT-INDENT: 26.9pt; TEXT-ALIGN: justify"><B><SPAN style="FONT-SIZE: 14pt; FONT-FAMILY: 標楷體">然而這樣還不能完全解決問題。由於修護系統的高度機密與價值，不大可能在所有的地方都建置一套這樣的系統，這時又是<SPAN lang=EN-US>Web services發揮其強大功能的時候了。這些汽車大廠可依各服務點的規模及技術能力等，建置一般功能的維修檢測系統，以應付一般性的檢修工作，對於重大的或具機密性的技術，則至於原廠或各地區之核心廠。當各小型檢修場無法判讀汽車電腦晶片內的數據時，再透過Web services連接原廠或各地區之核心廠取得相關檢修步驟。如此不但保有技術的機密性外，又可符合全球服務的需求，更重要的是，當擴點需求產生時，可加快建置的時間，而當重要的技術問題產生時，只需更新原廠或各地區之核心廠的資料庫，即可將資料傳送至全球的檢測系統。</SPAN></SPAN></B></P>
<P class=MsoNormal style="TEXT-JUSTIFY: inter-ideograph; LAYOUT-GRID-MODE: char; TEXT-ALIGN: justify"><B><SPAN style="FONT-SIZE: 20pt; FONT-FAMILY: 標楷體">軟體租用新模式</SPAN></B></P>
<P class=MsoNormal style="TEXT-JUSTIFY: inter-ideograph; LAYOUT-GRID-MODE: char; TEXT-INDENT: 26.9pt; TEXT-ALIGN: justify"><B><SPAN style="FONT-SIZE: 14pt; FONT-FAMILY: 標楷體">以上所舉的例子都是以使用者的角度區看，在上一篇文章中提到服務導向應用成架構實提到，參與這個架構的還包括服務提供者與服務登錄與代理兩個角色。前面也提到<SPAN lang=EN-US>Web services本身也可以當作一項產品來販賣。出售服務的架構其實到處都有，只不過型式不同罷了，目前網際網路裡面，線上刷卡代收服務是最典型的例子。</SPAN></SPAN></B></P>
<P class=MsoNormal style="TEXT-JUSTIFY: inter-ideograph; LAYOUT-GRID-MODE: char; TEXT-INDENT: 26.9pt; TEXT-ALIGN: justify"><B><SPAN style="FONT-SIZE: 14pt; FONT-FAMILY: 標楷體">將<SPAN lang=EN-US> Web services 當作交易的標地，可能影響到資訊系統的設計、部署與採購模式。企業可經由外部所提供之軟體服務，取得執行商業行為所需之應用程式功能，而不需全然由內部來開發。透過這種方式，程式開發者不須再使用傳統建立單一、集中式伺服器應用程式的方法，即可快速地建立或延伸現有應用程式的規模。企業因此可節省系統開發所需之時間，加快市場開發速度。</SPAN></SPAN></B></P>
<P class=MsoNormal style="TEXT-JUSTIFY: inter-ideograph; LAYOUT-GRID-MODE: char; TEXT-INDENT: 26.9pt; TEXT-ALIGN: justify"><B><SPAN style="FONT-SIZE: 14pt; FONT-FAMILY: 標楷體">對服務的提供者而言，大概可以有幾種模式，第一種可能在軟體銷售<SPAN lang=EN-US>/採購的方式改為租用或隨選服務的模式；這裡提到的租用與隨選服務事實上是有差異的。ISV可以將核心程式及部分的模組直接安裝於客戶端，以租用的方式實施，而為了避免租期與租金的爭議，可保留一小部分的啟動機制至於ISV的伺服器上。在租約期間，客戶透過Web services機制，聯結至ISV啟動其應用程式；租約到期，ISV僅須關閉此一機制即可。至於隨選服務，則針對一些工具服務，或延伸的功能，讓客戶依需要連結使用。</SPAN></SPAN></B></P>
<P class=MsoNormal style="TEXT-JUSTIFY: inter-ideograph; LAYOUT-GRID-MODE: char; TEXT-INDENT: 26.9pt; TEXT-ALIGN: justify"><B><SPAN style="FONT-SIZE: 14pt; FONT-FAMILY: 標楷體">企業也可以利用<SPAN lang=EN-US> Web services 將原有企業的智慧財產或成功經驗，重新包裝出售，以開拓全新的軟體服務市場。對ISV或VAR、OEM等廠商，更是提升商品附加價值的方式。</SPAN></SPAN></B></P>
<P class=MsoNormal style="TEXT-JUSTIFY: inter-ideograph; LAYOUT-GRID-MODE: char; TEXT-INDENT: 26.9pt; TEXT-ALIGN: justify"><B><SPAN style="FONT-SIZE: 14pt; FONT-FAMILY: 標楷體">對於一些電子資訊提供者，也可以改變提供的格式，目前大部分都是透過電子郵件或網頁瀏覽方式，未來也可以利用<SPAN lang=EN-US>Web services提供相同的資訊，讓用戶端可以直接加以利用，將Web services當作資料來源，直接提供應用程式存取。例如在設計網頁時，若希望能取得氣象、股票、球賽、產經最新消息，只要將所需之資訊版面空下，利用網頁上的控制項直接連結個資料來源之Web services，即可取得最新的資訊。而服務的提供者則可依訂戶的需求收取不同之費用。</SPAN></SPAN></B></P>
<P class=MsoNormal style="TEXT-JUSTIFY: inter-ideograph; LAYOUT-GRID-MODE: char; TEXT-ALIGN: justify"><B><SPAN style="FONT-SIZE: 20pt; FONT-FAMILY: 標楷體">企業流程管理</SPAN></B></P>
<P class=MsoNormal style="TEXT-JUSTIFY: inter-ideograph; LAYOUT-GRID-MODE: char; TEXT-INDENT: 26.9pt; TEXT-ALIGN: justify"><B><SPAN style="FONT-SIZE: 14pt; FONT-FAMILY: 標楷體">最後則來談談流程整合的部分，之所以會留到最後在來講，主要上避免在談到流程整合時，只侷限在企業內得整合。利用<SPAN lang=EN-US> Web services 加上流程管理軟體，可以讓企業內部或與外部合作夥伴間建立起天衣無縫的作業流程，更可依需要不斷的加入應用程式模組，而不影響到其他的應用程式，這些模組可以自行開發，也可以直接使用ISV所提供資訊服務。如此不但能提升企業組織的效率並降低企業經營的成本。<SPAN style="COLOR: black">或許您要問，目前已有很多的流程管理軟體與跨平台整合軟體，位什麼還要有Web services，這是因為這些軟體都是為個別系統間整合所設計，即使主要大廠所提供的流程管理軟體，</SPAN>包括Microsoft、IBM、BEA等<SPAN style="COLOR: black">，也須為不同的Adapter付出不同的軟體授權費，若採用Web services則不須為不同的系統就要採購另一套整合或流程軟體。</SPAN></SPAN></SPAN></B></P>
<P class=MsoNormal style="LAYOUT-GRID-MODE: char; TEXT-ALIGN: center" align=center><B><SPAN lang=EN-US style="FONT-SIZE: 14pt; COLOR: black; FONT-FAMILY: 標楷體"><IMG height=358 src="http://move-to.net/Comm/Document/9_image006.jpg" width=553 border=0></SPAN></B></P>
<P class=MsoNormal style="TEXT-JUSTIFY: inter-ideograph; LAYOUT-GRID-MODE: char; TEXT-INDENT: 26.9pt; TEXT-ALIGN: justify"><B><SPAN lang=EN-US style="FONT-SIZE: 14pt; COLOR: black; FONT-FAMILY: 標楷體"></SPAN></B> </P>
<P class=MsoNormal style="TEXT-JUSTIFY: inter-ideograph; LAYOUT-GRID-MODE: char; TEXT-ALIGN: justify"><B><SPAN style="FONT-SIZE: 20pt; FONT-FAMILY: 標楷體">導入時機</SPAN></B></P>
<P class=MsoNormal style="TEXT-JUSTIFY: inter-ideograph; LAYOUT-GRID-MODE: char; TEXT-INDENT: 26.9pt; TEXT-ALIGN: justify"><B><SPAN style="FONT-SIZE: 14pt; FONT-FAMILY: 標楷體">看完了以上的文章，或許會懷疑，這樣的技術成熟了嗎？我需不需要導入？要如何導入？而且在前兩年，資訊界還傳著一個很奇怪的說法，雖然各主要大廠及<SPAN lang=FR>WS-I</SPAN>組織以提供相當完整的規範與技術，但還是有些所謂權威人士會說<SPAN lang=FR>Web services</SPAN>是個不成熟的技術，還不能導到企業中使用。雖然對於全面性的將<SPAN lang=FR>Web services</SPAN>應用到全球的網路經濟還有些技術與規範要克服的，但也有不少廠商與政府或非政府機構以成功的導入<SPAN lang=FR>Web services</SPAN>。若要等一套技術完全成熟在一次導入，那時候可能又已經推出另外一套更新的技術，或許我們把他當作是一種市場競爭的手段罷了，對於技術跟不上速度的廠商，通常會以這種方式以減緩對手搶攻市場的速度。</SPAN></B></P>
<P class=MsoNormal style="TEXT-JUSTIFY: inter-ideograph; LAYOUT-GRID-MODE: char; TEXT-INDENT: 26.9pt; TEXT-ALIGN: justify"><B><SPAN style="FONT-SIZE: 14pt; FONT-FAMILY: 標楷體">下回我們再來分析哪些技術是可以導入的，哪些是還有限制的，哪些是目前不可行的，以及導入的步驟。</SPAN></B></P><img src ="http://www.blogjava.net/qq13367612/aggbug/16019.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/qq13367612/" target="_blank">Sung</a> 2005-10-15 16:56 <a href="http://www.blogjava.net/qq13367612/articles/16019.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>通过Java Swing看透MVC设计模式</title><link>http://www.blogjava.net/qq13367612/articles/15981.html</link><dc:creator>Sung</dc:creator><author>Sung</author><pubDate>Sat, 15 Oct 2005 08:55:00 GMT</pubDate><guid>http://www.blogjava.net/qq13367612/articles/15981.html</guid><wfw:comment>http://www.blogjava.net/qq13367612/comments/15981.html</wfw:comment><comments>http://www.blogjava.net/qq13367612/articles/15981.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/qq13367612/comments/commentRss/15981.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/qq13367612/services/trackbacks/15981.html</trackback:ping><description><![CDATA[一个好的用户界面(GUI)的设计通常可以在现实世界找到相应的表现。例如，如果在您的面前摆放着一个类似于电脑键盘按键的一个简单的按钮，然而就是这么简单的一个按钮，我们就可以看出一个GUI设计的规则，它由两个主要的部分构成，一部分使得它具有了按钮应该具有的动作特性，例如可以被按下。另外一部分则负责它的表现，例如这个按钮是代表了A还是B。 <BR>　　看清楚这两点你就发现了一个很强大的设计方法，这种方法鼓励重用reuse，而不是重新设计redesign。你发现按钮都有相同的机理，你只要在按钮的顶上喷上不同的字母便能制造出“不同”的按钮，而不用为了每个按钮而重新设计一份图纸。这大大减轻了设计工作的时间和难度。<BR>　　如果您把上述设计思想应用到软件开发领域，那么取得相似的效果一点都不让人惊奇。一个在软件开发领域应用的非常广泛的技术Model/View/Controller(MVC)便是这种思想的一个实现。<BR>　　这当然很不错，但是或许您又开始疑惑这和java基础类JFC(Java Foundation Class)中的用户界面设计部分(Swing)又有什么关系呢？好的，我来告诉你。<BR>　　尽管MVC设计模式通常是用来设计整个用户界面(GUI)的，JFC的设计者们却独创性的把这种设计模式用来设计Swing中的单个的组件(Component)，例如表格Jtable,树Jtree,组合下拉列表框JcomboBox等等等等。这些组件都有一个Model,一个View，一个Controller，而且，这些model,view,controller可以独立的改变，就是当组件正在被使用的时候也是如此。这种特性使得开发GUI界面的工具包显得非常的灵活。<BR>　　MVC设计模式把一个软件组件区分为三个不同的部分，model,view,controller。<BR><IMG src="http://www.javaresearch.org/members/{xymiser}/images/ "><BR>　　Model是代表组件状态和低级行为的部分，它管理着自己的状态并且处理所有对状态的操作，model自己本身并不知道使用自己的view和controller是谁，系统维护着它和view之间的关系，当model发生了改变系统还负责通知相应的view。<BR>　　View代表了管理model所含有的数据的一个视觉上的呈现。一个Model可以有一个以上的View,但是Swing中却很少有这样的情况。<BR>　　Controller管理着model和用户之间的交互的控制。它提供了一些方法去处理当model的状态发生了变化时的情况。<BR>　　使用键盘上的按钮的例子来说明一下：Model就是按钮的整个机械装置，View/Controller就是按钮的表面部分。<BR>　　下面的图解释了如何把一个JFC开发的用户界面分为model,view,controller，注意，view/Controller被合并到了一起，这是MVC设计模式通常的用法，它们提供了组件的用户界面(UI)。<BR> <BR>　　用Button的例子详细说明<BR>　　为了更好的理解MVC设计模式和Swing用户界面组件之间的关系，让我们更加深入的进行分析。我将采用最常见的组件button来说明。<BR>　　我们从model来开始。<BR>　　Model<BR>　　一个按钮的model所应该具备的行为由一个接口ButtonModel来完成。一个按钮model实例封装了其内部的状态，并且定义了按钮的行为。它的所有方法可以分为四类：<BR>　　1、查询内部状态<BR>　　2、操作内部状态<BR>　　3、添加和删除事件监听器<BR>　　4、发生事件<BR>　　其他的用户界面组件有它们各自的与组件相关的Model，但是所有的组件Model都提供这四类方法。<BR>　　View & Controller<BR>　　上面的图中讲述一个按钮的view/controller由一个接口ButtonUI完成。如果一个类实现了这个接口，那么它将会负责创建一个用户界面，处理用户的操作。它的所有方法可以被分为三大类：<BR>　　1、绘制Paint<BR>　　2、返回几何类型的信息<BR>　　3、处理AWT事件<BR>　　其他用户界面组件有他们自己的组件相关的View/Controller，但是他们都提供上述三类方法。<BR>　　程序员通常并不会直接和model以及view/controller打交道，他们通常隐藏于那些继承自java.awt.Component的组件里面了，这些组件就像胶水一样把MVC三者合三为一。也正是由于这些继承的组件对象，一个程序员可以很方便的混合使用Swing组件和AWT组件，然后，我们知道，Swing组件有很多都是直接继承自相应的AWT组件，它能提供比AWT组件更加方便易用的功能，所以通常情况下，我们没有必要混合使用两者。<BR>　　一个实例<BR>　　现在我们已经明白了Java类与MVC各个部分的对应关系，我们可以更加深入一点去分析问题了。下面我们将要讲述一个小型的使用MVC模式开发的例子。因为JFC十分的复杂，我只能把我的例子局限于一个用户界面组件里面（如果你猜是一个按钮的例子，那么你对了！）<BR>　　让我们来看看这个例子的所有部分吧。<BR>　　Button类<BR>　　最显而易见的开始的地方就是代表了按钮组件本省的代码，因为这个类是大部分程序员会接触的。<BR>　　就像我前面提到的，按钮用户界面组件类实际上就是model和view/controller的之间的黏合剂。每个按钮组件都和一个model以及一个controller关联，model定义了按钮的行为，而view/controller定义了按钮的表现。而应用程序可以在任何事件改变这些关联。让我们看看得以实现此功能的代码。<BR>public void setModel(ButtonModel buttonmodel)<BR>{<BR>　if (this.buttonmodel != null)<BR>　{<BR>　　this.buttonmodel.removeChangeListener(buttonchangelistener);<BR>　　this.buttonmodel.removeActionListener(buttonactionlistener);<BR><BR>　　buttonchangelistener = null;<BR>　　buttonactionlistener = null;<BR>　}<BR><BR>　this.buttonmodel = buttonmodel;<BR><BR>　if (this.buttonmodel != null)<BR>　{<BR>　　buttonchangelistener = new ButtonChangeListener();<BR>　　buttonactionlistener = new ButtonActionListener();<BR><BR>　　this.buttonmodel.addChangeListener(buttonchangelistener);<BR>　　this.buttonmodel.addActionListener(buttonactionlistener);<BR>　}<BR><BR>　updateButton();<BR>}<BR><BR>public void setUI(ButtonUI buttonui)<BR>{<BR>　if (this.buttonui != null)<BR>　{<BR>　　this.buttonui.uninstallUI(this);<BR>　}<BR><BR>　this.buttonui = buttonui;<BR><BR>　if (this.buttonui != null)<BR>　{<BR>　　this.buttonui.installUI(this);<BR>　}<BR><BR>　updateButton();<BR>}<BR><BR>public void updateButton()<BR>{<BR>　invalidate();<BR>} <BR>　　在进入下一节之前，你应该多花一些时间来仔细阅读一下Button类的源代码。<BR>　　ButtonModel类<BR>　　ButtonModel维护着三种类型的状态信息：是否被按下（pressed），是否“武装上了”（armed），是否被选择（selected）。它们都是boolean类型的值。<BR>　　一个按钮被按下（pressed）是指当鼠标在按钮上面的时候，按下鼠标但是还没有松开鼠标按钮的状态，及时用户此时把鼠标拖拽到按钮的外面也没有改变这种状态。<BR>　　一个按钮是否“武装了”（armed）是指按钮被按下，并且鼠标还在按钮的上面。<BR>　　一些按钮还可能被选择（selected），这种状态通过重复的点击按钮取得true或者false的值。<BR>　　下面的代码是状态pressed的一个缺省的实现。状态armed以及selected实现的代码与之类似。ButtonModel类应该被继承，这样可以覆盖缺省的状态定义，实现有个性的按钮。<BR>private boolean boolPressed = false;<BR><BR>public boolean isPressed()<BR>{<BR>　return boolPressed;<BR>}<BR><BR>public void setPressed(boolean boolPressed)<BR>{<BR>　this.boolPressed = boolPressed;<BR>　fireChangeEvent(new ChangeEvent(button));<BR>} <BR>　　按钮的模型button model还负责通知其他对象（事件监听器）它们所感兴趣的事件。从下面的代买中我们可以看出当按钮的转台发生改变的时候就会发出一个ChangeEvent。下面就是代码：<BR>private Vector vectorChangeListeners = new Vector();<BR><BR>public void addChangeListener(ChangeListener changelistener)<BR>{<BR>　vectorChangeListeners.addElement(changelistener);<BR>}<BR><BR>public void removeChangeListener(ChangeListener changelistener)<BR>{<BR>　vectorChangeListeners.removeElement(changelistener);<BR>}<BR><BR>protected void fireChangeEvent(ChangeEvent changeevent)<BR>{<BR>　Enumeration enumeration = vectorChangeListeners.elements();<BR>　while (enumeration.hasMoreElements())<BR>　{<BR>　　ChangeListener changelistener =(ChangeListener)enumeration.nextElement();<BR>　　changelistener.stateChanged(changeevent);<BR>　}<BR>}<BR>　　在进入下一节之前，你应该多花一些时间来仔细阅读一下ButtonModel类的源代码。 <BR>　　ButtonUI类<BR>　　按钮的view/controller是负责构建表示层的。缺省情况下它仅仅是用背景色画一个矩形而已，他们的子类继承了他们并且覆盖了绘制的方法，使得按钮可以有许多不同的表现，例如MOTIF，Windows 95，Java样式等等。<BR>public void update(Button button, Graphics graphics)<BR>{<BR>}<BR><BR>public void paint(Button button, Graphics graphics)<BR>{<BR>　Dimension dimension = button.getSize();<BR>　Color color = button.getBackground();<BR>　graphics.setColor(color);<BR>　graphics.fillRect(0, 0, dimension.width, dimension.height); <BR>}<BR>　　ButtonUI类并不自己处理AWT事件，他们会使用一个定制的事件监听器把低级的AWT事件翻译为高级的Button模型期望的语义事件。下面就是安装/卸载事件监听器的代码。<BR>private static ButtonUIListener buttonuilistener = null;<BR><BR>public void installUI(Button button)<BR>{<BR>　button.addMouseListener(buttonuilistener);<BR>　button.addMouseMotionListener(buttonuilistener);<BR>　button.addChangeListener(buttonuilistener);<BR>}<BR><BR>public void uninstallUI(Button button)<BR>{<BR>　button.removeMouseListener(buttonuilistener);<BR>　button.removeMouseMotionListener(buttonuilistener);<BR>　button.removeChangeListener(buttonuilistener);<BR>}<BR>　　View/Controller实际上就是一些方法。他们不维护任何自己的状态信息。因此，许多按钮的实例可以共享一个ButtonUI实例。ButtonUI是通过在方面的参数列表里面加上按钮的引用来区分各个不同的按钮。<BR>　　同样，希望你能多花一些时间来看看ButtonUI类，然后咱们进入下一节。<BR>　　ButtonUIListener类<BR>　　ButtonUIListener类可以帮助Button类去转变鼠标或者键盘的输入为对按钮模型的操作。这个监听器类实现了：MouseListener,MouseMotionListener,ChangeListener接口，并且处理一下事件：<BR>public void mouseDragged(MouseEvent mouseevent)<BR>{<BR>　Button button = (Button)mouseevent.getSource();<BR>　ButtonModel buttonmodel = button.getModel();<BR><BR>　if (buttonmodel.isPressed())<BR>　{<BR>　　if (button.getUI().contains(button, mouseevent.getPoint()))<BR>　　{<BR>　　　buttonmodel.setArmed(true);<BR>　　}<BR>　　else<BR>　　{<BR>　　　buttonmodel.setArmed(false);<BR>　　}<BR>　}<BR>}<BR><BR>public void mousePressed(MouseEvent mouseevent)<BR>{<BR>　Button button = (Button)mouseevent.getSource();<BR>　ButtonModel buttonmodel = button.getModel();<BR>　buttonmodel.setPressed(true);<BR>　buttonmodel.setArmed(true);<BR>}<BR><BR>public void mouseReleased(MouseEvent mouseevent)<BR>{<BR>　Button button = (Button)mouseevent.getSource();<BR>　ButtonModel buttonmodel = button.getModel();<BR>　buttonmodel.setPressed(false);<BR>　buttonmodel.setArmed(false);<BR>}<BR><BR>public void stateChanged(ChangeEvent changeevent)<BR>{<BR>　Button button = (Button)changeevent.getSource();<BR>　button.repaint();<BR>}<BR>　　总结<BR>　　我希望你能按照上面讲述的方法去做。如果不能，那么所有的努力都将白费。这个例子以及Swing用户界面组件的好处在于你不用去花时间去弄明白他们底层是如何设计实现的就可以很方便的使用他们了。他们都提供了缺省的model以及view/controller，然后，当你自己做组件的时候，你会发现上面的思想的强大之处。<BR><img src ="http://www.blogjava.net/qq13367612/aggbug/15981.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/qq13367612/" target="_blank">Sung</a> 2005-10-15 16:55 <a href="http://www.blogjava.net/qq13367612/articles/15981.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Beyond MVC: A New Look at the Servlet Infrastructure</title><link>http://www.blogjava.net/qq13367612/articles/16246.html</link><dc:creator>Sung</dc:creator><author>Sung</author><pubDate>Fri, 09 Sep 2005 06:57:00 GMT</pubDate><guid>http://www.blogjava.net/qq13367612/articles/16246.html</guid><wfw:comment>http://www.blogjava.net/qq13367612/comments/16246.html</wfw:comment><comments>http://www.blogjava.net/qq13367612/articles/16246.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/qq13367612/comments/commentRss/16246.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/qq13367612/services/trackbacks/16246.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: This article is the first of two that examine in depth the origins of the Model-View-Controller (MVC) design pattern and its misapplication to servlet framework architectures. The purpose of this firs...&nbsp;&nbsp;<a href='http://www.blogjava.net/qq13367612/articles/16246.html'>阅读全文</a><img src ="http://www.blogjava.net/qq13367612/aggbug/16246.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/qq13367612/" target="_blank">Sung</a> 2005-09-09 14:57 <a href="http://www.blogjava.net/qq13367612/articles/16246.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>