Web 服务实现中的概念分离
作者 Tieu Luu 09/06/2006
翻译 Judy01/29/2007
概念分离是面向服务体系结构的一项核心原则。 不幸的是,在实现 SOA 服务时,这项原则总是被忽略。 经常可以看到一个很长的类具有多重概念,例如安全、事务管理和登录等全部与业务逻辑混杂在一起。 使用 Spring 框架和 Aspect Oriented Programming (AOP) 准则,可以将概念分离灌输到服务实现中去。
在这篇文章中, 我将介绍如何使用 Apache Axis 和 Spring 开发 Web 服务,以及使用 Acegi Security 保证服务的安全 -- 从始至终都可以保持概念可以很好地分离。
动机与设计
本文使用的示例服务称作 FundsTransferService
,使用此服务银行可以将资金从一个帐户转移到另一个帐户。 服务的 WSDL、所有的源代码、配置文件和生成文件已在本文的资源部分给出。 我们有意选择一个简单的服务,目的是把重点放在文章的其他方面。 在此服务的实现过程中,将遇到三个概念:
- Web 服务引流,将其功能作为服务公开
- 业务逻辑,以执行转移资金
- 确保安全性,只有授权者可以执行资金转移
一个实际的系统还极有可能处理其他的概念,如事务管理、登录等。
服务实现的设计目标是,需要将特定的代码应用于特定的概念,而且概念与概念相互独立。 对于 Web 服务引流,我们使用 Axis 将其功能公开为一个服务。 跨帐户的资金转移这一业务逻辑,则将其封装在一组传统纯 Java 对象 (Plain Old Java Object,POJO) 中。 而安全性将由 Acegi Security 框架提供。 我们将使用 Spring 框架及其 AOP 功能将所有内容捆扎在一起,使实现此 Web 服务的代码间的依赖性降低。
实现的设计如图 1 所示。黄色是我们将要实现的对象。 蓝色由 Axis 提供,粉色由 Acegi 提供,绿色由 Spring 提供。 FundsTransferService
WSDL 中设计的服务的接口。 为简化此图,我们将所有 Axis 类视为组件,称为 Axis Engine。 BasicHandler
也是一个 Axis 类,但是由于它对设计的重要性我们还需要特殊对待(稍后详细讨论)。 FundsTransferServiceSoapBindingImpl
是 Axis 生成的类,也是我们需要加以实现以便提供服务的功能。 它将通过 Spring 间接为业务逻辑 POJO AccountMgrImpl
对象服务。(稍后也将详加讨论。) AccountMgrImpl
和 AccountMgr
接口包装在一起,因为这是一个很好的做法,还因为这允许 Spring 发挥它的神奇作用(还有另外一种方法是在不使用接口的情况下使用 Spring)。
图 1. 实现资金转移服务的设计
现在回到 BasicHandler
。 需要它的原因是它关系到我们已选择的提供安全保障的方式。 在此示例中,我们将处理两个层次上的安全性:Web 服务的安全性,和应用程序代码的安全性,例如,POJO。 对于概念分离的思想,我们已经提出了一个方案。 Axis 允许使用自定义的事务处理程序,以便截取提供其他如安全性等功能的请求和响应消息。 因此,我们将创建一个自定义的事务处理程序,称之为AcegiBridgeAuthenticationHandler
,用于负责处理 Web 服务安全。 它扩展自 Axis 的 BasicHandler
类,因此可以将其插入 Axis 处理程序的框架。 Acegi 将用于提供应用程序级别的安全,例如,提供对 POJO 的访问控制。
要使二者协同无缝地工作,我们需要将 Web 服务安全上下文过渡到 Acegi 安全上下文,因此将自定义的 Axis 处理程序类命名为 AcegiBridgeAuthenticationHandler
。 它不仅会处理 Web 服务安全的流程,还负责将从该流程中获取的安全上下文过渡到 Acegi 环境中,以便 Acegi 来决定授权,是否允许访问 POJO。 这是通过从 Web 服务请求消息中提取安全性设置完成的,Acegi 将验证请求,然后创建一个授权标识,即 UsernamePasswordAuthenticationToken
,因为在本示例中我们已经选择使用“用户名/密码”式的授权方式。 然后,将授权标识添加到 Acegi 的 SecurityContext
中,这样一来请求中的授权信息和权限在 Acegi 控制业务逻辑的 POJO 时就可供使用了。
现在开始解释如何使用 Spring 将所有内容捆扎在一起。 其妙处就在于图 1 中名为 AOP proxy 的那个绿色对象,它是由 Spring 生成的。 这个对象实现了 AccountMgr
接口,行为上相当于业务逻辑 POJO AccountMgrImpl
的代理。 这允许 Spring 插入 Acegi 的 AccountMgrImpl
来执行访问控制,以检查何时在 POJO 上发生方法调用。 当 FundsTransferServiceSoapBindingImpl
向 POJO 发出 Web 服务请求时,它实际上是向一个 AOP 代理的实例发出的而不是直接针对 AccountMgrImpl
。 因为 FundsTransferServiceSoapBindingImpl
扩展了 ServletEndpointSupport
,所以它可以访问 Spring 应用程序上下文来获取一个对 AOP 代理(已经使用合适的接口、拦截器和目标类 AccountMgrImpl
进行了配置)的引用。
图 2 的序列图中展示了当客户端调用 FundsTransferService
时将发生的流程。 Axis Engine 将负责接收请求消息,然后激活 AcegiBridgeAuthenticationHandler
。 AcegiBridgeAuthenticationHandler
验证授权信息,然后创建一个 UsernamePasswordAuthenticationToken
。 接下来,它将该标识写入 SecurityContext
以便 Acegi 将来使用。 AcegiBridgeAuthenticationHandler
成功返回后,Axis Engine 就会调用 FundsTransferServiceSoapBindingImpl
上的 transferFunds()
方法。 FundsTransferServiceSoapBindingImpl
将它委托给 AOP proxy,该代理是 FundsTransferServiceSoapBindingImpl
早在从 Spring Web 应用程序上下文进行初始化时就已经获取的。 AOP proxy
调用 Acegi MethodSecurityInterceptor
以便执行安全性检查。 MethodSecurityInterceptor
从 SecurityContext
处获取授权标识并检查是否被授权。 然后,使用授权标识中的信息,来查看客户端是否被允许调用 AccountMgrImpl
上的 transferFunds()
方法。 如果许可访问,则 MethodSecurityInterceptor
允许调用该方法进行 AccountMgrImpl
。 AccountMgrImpl
最终处理请求并返回结果,结果最终被传送到客户端程序。
图 2。服务实现的处理流程序列图
分享到:
相关推荐
<load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>dispatcher</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> <!-- ... --> </web-app> ``` 这将告诉...
Spring MVC 是一个强大的Java Web应用程序框架,用于构建高效、模块化的Web应用。在这个教程中,我们将探讨如何使用Spring MVC 3来创建一个简单的Web应用。首先,我们需要建立一个新的Web项目。 1. 创建Web项目: ...
<load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>dispatcher</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> ``` - **默认配置方式**:默认情况下,...
Spring MVC 提供了一个清晰的架构来分离应用程序中的业务逻辑、用户界面以及控制流程。 **关键组件包括:** 1. **后端控制器(Handler):** 处理用户请求并返回相应的模型数据和视图。 2. **映射处理器...
<load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>dispatcher</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> </web-app> ``` 5. **编写SpringMVC...
它提供了模型-视图-控制器(MVC)架构,使开发者能够将业务逻辑、数据处理和用户界面分离,从而实现更清晰、更可维护的代码结构。下面将详细讲解SpringMVC的搭建过程及其相关知识点。 1. **环境准备** 在开始...
<load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>springmvc</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> <filter> <filter-name>...
1. **创建项目**:在Eclipse中,选择"File" -> "New" -> "Dynamic Web Project",输入项目名称,例如"SpringMVCHelloWorld",并确保在"Target Runtime"中选择已安装的Apache Tomcat服务器。 2. **添加Spring MVC...
- `<%@ page language="java" import="java.util.*" pageEncoding="gbk"%>` 这行代码指定了页面的脚本语言为Java,并导入了`java.util.*`包,同时设置了页面编码为GBK。 - `<% String path=request.getContextPath()...
<load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>dispatcher</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> ``` 4. **创建 Spring 配置文件**: - ...
Struts1是一个经典的Java Web框架,它以Model-View-...Struts1通过提供强大的控制层和配置机制,帮助开发者有效地组织和管理Web应用的结构,实现了业务逻辑与展示逻辑的分离,提高了代码的可维护性和可复用性。
2. **分离**:实现真正的视图与代码分离,让视图层更加清晰、易于维护。 3. **灵活性**:开发框架应该提供足够的灵活性,允许开发者根据具体需求调整框架行为,而不是仅仅局限于特定的模式或方法。 4. **高性能*...
在MyEclipse中,你可以直接右键点击项目,选择“Run As” -> “Run on Server”,选择已配置的Tomcat服务器,来运行你的JSP应用。浏览器将会显示你刚刚创建的动态页面。 继续深入学习JSP,你需要掌握更多概念,如...
Struts2.1是Apache软件基金会的开源框架Struts的第二个主要版本,它是一个用于构建企业级Java web应用程序的MVC(模型-视图-控制器)框架。在本项目中,我们将探讨如何在MyEclipse6.5集成开发环境中创建一个基于...
12. **Struts框架理解**:Struts是MVC(Model-View-Controller)架构的Java Web框架,它分离了业务逻辑、视图和控制层,提高了代码的可维护性和可扩展性。它使用ActionForm处理用户请求,通过配置文件定义请求路径和...
综上所述,“Handson 教师用书”覆盖了Java Web开发的多个重要方面,包括基本概念、技术实现细节以及最佳实践。通过这些内容的学习,读者不仅可以获得扎实的理论基础,还能掌握实用的开发技能,非常适合初学者入门及...
<%@ page import="java.sql.*" %> Connection conn = DBConnection.getConnection(); Statement stmt = conn.createStatement(); ResultSet rs = stmt.executeQuery("SELECT * FROM products"); while (rs....
【描述】"this is a java application baed on servelts,jsp ." 描述了这是一个用Java语言开发的Web应用程序,它依赖于Servlets和JSP技术。Servlets是Java平台上的服务器端编程模型,主要用于扩展Web服务器的功能,...
在Java面试中,常常会考察应聘者对基础概念的理解以及实际开发经验。以下是一些常见的Java面试题目及其详细解答: 1. **继承、封装、多态**: - 继承是类与类之间的关系,允许一个类(子类)继承另一个类(父类)...