Web服务与Axis框架深度解析
1. Axis框架概述
Axis是Apache的SOAP 2版本的继任者。原SOAP 2包的开发者意识到其存在一些无法修复的缺陷,于是重新开发了Axis。Axis具有以下组件:
- 一个简单的独立服务器(主要用于测试)
- 可插入如Tomcat等Servlet引擎的服务器
- 对WSDL(Web Services Description Language)的广泛支持
- 能从WSDL生成Java类的发射器工具
- 一些示例程序
- 用于监控TCP/IP数据包的工具
1.1 Axis的架构
Axis的总体架构中,请求者可以是通过Axis支持的任何协议发出请求的客户端,通常使用HTTP协议。请求者可以是桌面应用程序、其他Web应用程序或其他Web服务。Axis引擎在客户端和Web服务方法之间起到促进作用,管理与Web服务标准之间的转换。
Axis允许开发者定义一系列与请求或响应相关联的处理程序。这些处理程序类似于过滤器Servlet,每个处理程序执行特定任务并将请求转发给下一个处理程序。处理程序组成一个链,这是Web服务请求或响应所经过的一组特定处理程序。以下是其架构的mermaid流程图:
graph LR
A[请求者] --> B[Axis引擎]
B --> C[Web服务]
B --> D[请求处理程序链]
B --> E[响应处理程序链]
B --> F[枢轴点处理程序]
D --> F
F --> E
处理程序链在Axis引擎使用的配置文档(默认名为server.config)中定义。该文件是一个XML文档,定义了Axis的行为配置参数。
1.2 Axis工具
Axis附带了一些工具,方便在Java中开发Web服务。
1.2.1 简单Web服务创建
要创建简单的Web服务,可以开发一个包含Axis的Web应用程序,并在Web应用程序的根目录下提供一个具有
.jws
扩展名的公共可访问文件。需要注意的是,
.jws
不是标准扩展名,Axis和WebLogic都使用它来定义简单Web服务,但它们并不兼容。以下是一个简单的Java源文件示例,Axis会将其转换为Web服务:
public class Simple {
public String sayHello(String name) {
return "Hello, " + name;
}
}
当有人通过HTTP调用这个简单服务时,Axis会自动构建必要的基础设施,使其作为Web服务可访问。就像JSP一样,Axis会为Web服务生成Java源文件,编译它,并自动将请求重定向到该文件。如果通过浏览器访问这个文件(执行GET请求而不是调用方法的POST请求),会看到相应的消息。
此外,Axis还能为任何Web服务(不仅仅是使用
.jws
文件创建的服务)自动生成WSDL文件。要访问上述简单Web服务的WSDL,只需在URI末尾添加
?WSDL
即可。
1.2.2 WSDL2Java工具
要调用现有的Web服务,需要生成Java接口和辅助类。Axis包含一个名为WSDL2Java的工具,它可以读取WSDL文件并生成调用Web服务所需的所有Java类。以从上述简单Web服务生成的WSDL文件为例,运行WSDL2Java会生成四个Java源文件,如下表所示:
| Java源文件 | 描述 |
| — | — |
| Simple.java | 描述通过此Web服务可用方法的可远程接口 |
| SimpleService.java | 定义返回实现Simple接口的类实例的方法的Java接口 |
| SimpleServiceLocator.java | 用于定位、绑定和返回实现SimpleService.java的类的实用类,调用该类可绑定到Web服务 |
| SimpleSoapBindingStub.java | 实现从客户端实际调用Web服务细节的类 |
以下是生成的
Simple.java
接口代码:
/**
* Simple.java
*
* This file was auto-generated from WSDL
* by the Apache Axis WSDL2Java emitter.
*/
package localhost;
public interface Simple extends java.rmi.Remote {
public java.lang.String sayHello(java.lang.String name)
throws java.rmi.RemoteException;
}
1.2.3 Java2WSDL工具
Axis还包含Java2WSDL实用工具,它可以根据Java接口生成将其作为Web服务实现所需的WSDL。使用此工具比让Axis框架自动生成WSDL更为复杂,通常在需要自定义WSDL或Web服务的部署选项时使用。
2. 调用Web服务
使用Axis调用Web服务相对简单,最难的部分是找到想要调用的Web服务。许多网站会发布Web服务列表,例如www.xmethods.com。调用Web服务只需要知道其WSDL,Axis会生成其他所需的一切。
2.1 调用示例
假设应用程序需要查找莎士比亚戏剧的台词并获取有关戏剧的信息,有一个Web服务可以完成此任务(可在xmethods网站找到),其WSDL为www.xmlme.com/WSShakespeare.asmx?WSDL。调用步骤如下:
1. 对该WSDL文件运行WSDL2Java工具,生成四个文件。
2. 实现需要调用Web服务的类,示例代码如下:
package com.nealford.art.ws.clientcall;
import java.rmi.RemoteException;
import javax.xml.rpc.ServiceException;
import com.xmlme.ShakespeareLocator;
import com.xmlme.ShakespeareSoap;
public class ShakespeareQuotes {
public ShakespeareQuotes() {
ShakespeareSoap bard = null;
try {
bard = new ShakespeareLocator().
getShakespeareSoap();
} catch (ServiceException ex) {
ex.printStackTrace();
}
String speech = "To be, or not to be";
System.out.println("The quote:'" + speech + "'");
try {
System.out.println(bard.getSpeech(speech));
} catch (RemoteException ex1) {
}
}
public static void main(String[] args) {
new ShakespeareQuotes();
}
}
ServiceLocator会返回一个实现ShakespeareSoap接口的类的实例。该接口定义了唯一的方法
getSpeech()
。获得接口引用后,就可以像处理本地对象一样处理该对象。调用
bard.getSpeech()
会执行Web服务并返回匹配的说话者、戏剧和台词。
Web服务作为一种分布式执行协议的一个优点是,消费者无需关心实现Web服务方法的语言或平台。例如,莎士比亚台词服务恰好使用Microsoft .NET Framework实现,但消费者无需知道具体使用的语言。
3. eMotherEarth Web服务集成
在eMotherEarth应用程序中添加Web服务调用,需要进行一些配置更改。
3.1 配置更改
3.1.1 web.xml更改
添加Web服务的第一步是将Axis JAR文件添加到现有项目中。Axis JAR文件包含一个Servlet,当嵌入更大的Web应用程序时,它充当Axis引擎。为了启用这个Servlet,需要在web.xml配置文件中添加引用,并使用前缀映射的URL映射将任何标识为“service”的请求发送到AxisServlet。示例配置如下:
<servlet>
<servlet-name>AxisServlet</servlet-name>
<display-name>Apache-Axis Servlet</display-name>
<servlet-class>
org.apache.axis.transport.http.AxisServlet
</servlet-class>
</servlet>
<!-- items omitted here -->
<servlet-mapping>
<servlet-name>AxisServlet</servlet-name>
<url-pattern>/services/*</url-pattern>
</servlet-mapping>
3.1.2 数据库连接
原应用程序中,欢迎Servlet在用户首次访问时创建数据库连接池。但现在应用程序可能会被编程式调用,不能再假设用户会首先访问应用程序。为了解决这个问题,必须确保应用程序启动时就建立数据库连接池。
一种解决方案是创建一个具有单例对象和Servlet特性的类。以下是
ConnectionPoolProxy
类的实现:
package com.nealford.art.emotherearth.util;
import javax.servlet.GenericServlet;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
public class ConnectionPoolProxy extends GenericServlet {
static private ConnectionPoolProxy cpp;
public void init() throws ServletException {
cpp = this;
}
public void service(ServletRequest req, ServletResponse res)
throws javax.servlet.ServletException,
java.io.IOException {
//-- intentionally left blank
}
public static ConnectionPoolProxy getInstance() {
return cpp;
}
public DBPool getDbPool() {
return (DBPool) getServletContext().getAttribute("dbPool");
}
}
该类扩展自GenericServlet,以便Servlet引擎可以自动创建它。它借用了单例的概念,持有对自身的私有静态引用。在
init()
方法中,将对象引用存储在静态变量中。
service()
方法是必需的但为空。
getInstance()
方法返回Servlet引擎持有的对象的内部引用,
getDbPool()
方法可以访问Servlet上下文集合中的数据库连接池。
3.1.3 server-config.wsdd配置
由于不使用
.jws
文件实现Web服务,需要通过名为server-config.wsdd的XML文档配置Axis来发布服务。该文档位于WEB - INF目录中,定义了Axis的所有处理程序。以下是为Web服务方法添加的配置示例:
<!-- service registration for Order Status -->
<service name="OrderStatus" provider="java:RPC">
<parameter name="className"
value="com.nealford.art.emotherearth.ws.OrderInfo"/>
<parameter name="allowedMethods"
value="getWsDescription, getOrderStatus, getShippingStatus"/>
</service>
此配置创建了一个名为
OrderStatus
的Web服务,使用RPC语义进行调用。实现该Web服务的类是
OrderInfo
,它公开了三个方法:
getWsDescription()
、
getOrderStatus()
和
getShippingStatus()
。
3.2 订单服务方法添加
原应用程序以典型的Model 2方式处理订单,订单边界类返回订单实体对象的实例。对于Web服务,只需要获取特定订单的状态,不需要整个订单对象。因此,在订单边界类中添加了几个无状态方法,而实体类无需更改。以下是添加的方法:
private String getStatusFor(String sql, int orderKey) throws
SQLException {
Connection c = null;
PreparedStatement ps = null;
ResultSet rs = null;
String result = "Error: Order not found";
try {
c = dbPool.getConnection();
ps = c.prepareStatement(sql);
ps.setInt(1, orderKey);
rs = ps.executeQuery();
if (rs.next())
result = rs.getString(1);
} finally {
ps.close();
dbPool.release(c);
}
return result;
}
public String getShippingStatus(int orderKey)
throws SQLException {
return getStatusFor(SQL_GET_SHIPPING_STATUS, orderKey);
}
public String getOrderStatus(int orderKey) throws SQLException {
return getStatusFor(SQL_GET_ORDER_STATUS, orderKey);
}
getOrderStatus
和
getShippingStatus
方法调用
getStatusFor
方法,传入相应的SQL语句和订单键,以获取订单状态或运输状态。
通过以上步骤,可以在eMotherEarth应用程序中成功集成Web服务,实现订单状态和运输状态的查询功能。这种集成方式充分利用了Axis框架的优势,使得应用程序能够更好地与其他系统进行交互。
4. 深入理解Axis处理程序链
4.1 处理程序链的作用与结构
Axis的处理程序链是其架构中的重要组成部分,它允许开发者对Web服务请求和响应进行灵活的处理。处理程序链由一系列处理程序组成,每个处理程序执行特定的任务,并将处理结果传递给下一个处理程序。这种结构类似于过滤器Servlet,使得开发者可以在请求和响应的不同阶段插入自定义逻辑。
处理程序链的配置在
server.config
文件中定义,该文件是一个XML文档,包含了Axis的各种配置参数。以下是处理程序链的mermaid流程图:
graph LR
A[请求] --> B[请求处理程序1]
B --> C[请求处理程序2]
C --> D[枢轴点处理程序]
D --> E[响应处理程序2]
E --> F[响应处理程序1]
F --> G[响应]
4.2 处理程序的类型与示例
处理程序可以是安全组件、日志记录系统、数据转换等。例如,安全组件可以对请求进行身份验证和授权,日志记录系统可以记录请求和响应的详细信息,数据转换处理程序可以对数据进行格式转换。
其中,枢轴点处理程序是每个Web服务都有的特殊处理程序,它负责实际调用Web服务方法,并将请求转换为响应。以下是一个简单的处理程序示例,用于记录请求和响应的日志:
import org.apache.axis.AxisFault;
import org.apache.axis.MessageContext;
import org.apache.axis.handlers.BasicHandler;
public class LoggingHandler extends BasicHandler {
public void invoke(MessageContext msgContext) throws AxisFault {
System.out.println("Request received: " + msgContext.getRequestMessage());
// 调用下一个处理程序
super.invoke(msgContext);
System.out.println("Response sent: " + msgContext.getResponseMessage());
}
}
4.3 处理程序链的配置与使用
要将处理程序添加到处理程序链中,需要在
server.config
文件中进行配置。以下是一个简单的配置示例:
<handler name="LoggingHandler" type="java:com.example.LoggingHandler"/>
<chain name="MyChain">
<handler ref="LoggingHandler"/>
<!-- 其他处理程序 -->
</chain>
<service name="MyService" provider="java:RPC">
<parameter name="className" value="com.example.MyServiceClass"/>
<requestFlow>
<chain ref="MyChain"/>
</requestFlow>
<responseFlow>
<chain ref="MyChain"/>
</responseFlow>
</service>
通过以上配置,
LoggingHandler
将被添加到
MyService
的请求和响应处理程序链中,实现日志记录功能。
5. Axis工具的高级应用
5.1 WSDL2Java的高级用法
WSDL2Java工具不仅可以生成基本的Java接口和辅助类,还支持一些高级选项。例如,可以通过命令行参数指定生成类的包名、输出目录等。以下是一些常用的命令行参数:
| 参数 | 描述 |
|---|---|
-p
| 指定生成类的包名 |
-o
| 指定输出目录 |
-s
| 生成存根类 |
-u
| 生成服务定位器类 |
例如,以下命令将生成包名为
com.example
的Java类,并将输出文件保存到
output
目录中:
java -cp axis.jar org.apache.axis.wsdl.WSDL2Java -p com.example -o output http://example.com/service.wsdl
5.2 Java2WSDL的自定义配置
Java2WSDL工具可以根据Java接口生成WSDL文件,并且支持自定义配置。例如,可以通过命令行参数指定WSDL的命名空间、服务名称等。以下是一个自定义配置的示例:
java -cp axis.jar org.apache.axis.wsdl.Java2WSDL -p com.example -n http://example.com/ns -s MyService com.example.MyInterface
通过以上命令,将生成一个命名空间为
http://example.com/ns
,服务名称为
MyService
的WSDL文件。
5.3 工具的组合使用
在实际开发中,可以将WSDL2Java和Java2WSDL工具组合使用,实现Web服务的开发和调用。例如,先使用Java2WSDL生成WSDL文件,然后使用WSDL2Java根据该WSDL文件生成Java类,最后调用Web服务。以下是一个简单的开发流程:
- 定义Java接口
package com.example;
public interface MyInterface {
public String sayHello(String name);
}
- 使用Java2WSDL生成WSDL文件
java -cp axis.jar org.apache.axis.wsdl.Java2WSDL -p com.example -n http://example.com/ns -s MyService com.example.MyInterface
- 使用WSDL2Java生成Java类
java -cp axis.jar org.apache.axis.wsdl.WSDL2Java -p com.example -o output http://example.com/MyService.wsdl
- 调用Web服务
import com.example.MyInterface;
import com.example.MyServiceLocator;
public class Client {
public static void main(String[] args) {
try {
MyServiceLocator locator = new MyServiceLocator();
MyInterface service = locator.getMyInterface();
String result = service.sayHello("World");
System.out.println(result);
} catch (Exception e) {
e.printStackTrace();
}
}
}
6. Web服务的性能优化与安全考虑
6.1 性能优化
在使用Axis开发Web服务时,性能优化是一个重要的考虑因素。以下是一些性能优化的建议:
- 减少数据传输量 :尽量减少请求和响应的数据量,可以通过压缩数据、只传输必要的数据等方式实现。
- 使用连接池 :使用数据库连接池和网络连接池,减少连接的创建和销毁开销。
- 优化处理程序链 :避免在处理程序链中添加不必要的处理程序,减少处理时间。
6.2 安全考虑
Web服务的安全性也是至关重要的。以下是一些安全考虑的建议:
- 身份验证和授权 :对请求进行身份验证和授权,确保只有合法的用户可以访问Web服务。
- 数据加密 :对敏感数据进行加密传输,防止数据泄露。
- 防止攻击 :采取措施防止常见的攻击,如SQL注入、跨站脚本攻击等。
通过以上性能优化和安全考虑,可以提高Web服务的稳定性和可靠性,为用户提供更好的服务体验。
综上所述,Axis框架为开发和调用Web服务提供了强大的支持。通过深入理解Axis的架构、工具和配置,以及进行性能优化和安全考虑,可以开发出高效、安全的Web服务应用程序。
超级会员免费看
1410

被折叠的 条评论
为什么被折叠?



