Apache axis1.4调用webservice 客户端获取请求报文和响应报文

本文介绍如何使用Axis1.4库在Java中调用Webservice并获取请求与响应的SOAP报文。通过具体示例,演示了设置Webservice地址、调用服务及获取报文的方法。

获取请求报文和响应报文

axis1.4使用wsdl生成代码客户端后,使用Call的方式调用webservice服务时,若需要获取请求报文和响应报文,可使用如下方式获取:

		MessageContext msgCxt = api._getCall().getMessageContext();
		//请求报文
		String requestStr = msgCxt.getRequestMessage().getSOAPPartAsString();
		//响应报文
		String responseStr = msgCxt.getResponseMessage().getSOAPPartAsString();
		//若获取到响应报文为空,可尝试如下方式获取:
		//api._getCall().getResponseMessage().getSOAPPartAsString();

示例

以调用qq检查在线状态的公开webservice为例:

	public static void main(String[] args) throws ServiceException, RemoteException {
		
		String endPoint = "http://www.webxml.com.cn/webservices/qqOnlineWebService.asmx";
		
		QqOnlineWebServiceLocator service = new QqOnlineWebServiceLocator();
		service.setqqOnlineWebServiceSoapEndpointAddress(endPoint);
		
		QqOnlineWebServiceSoapStub api = (QqOnlineWebServiceSoapStub) service.getqqOnlineWebServiceSoap();
		
		String response = api.qqCheckOnline("1149376120");
		
		MessageContext msgCxt = api._getCall().getMessageContext();
		//请求报文
		String requestStr = msgCxt.getRequestMessage().getSOAPPartAsString();
		//响应报文
		String responseStr = msgCxt.getResponseMessage().getSOAPPartAsString();
		
		System.out.println("请求报文:");
		System.out.println(requestStr);
		System.out.println("++++++++++++++++++++++");
		System.out.println("响应报文:");
		System.out.println(responseStr);
		
	}

输出结果:
在这里插入图片描述

需要的jar包:
axis.jar
commons-discovery-0.2.jar
commons-io-2.4.jar
commons-logging.jar
jaxrpc.jar
saaj.jar
wsdl4j.jar
下载地址:
https://download.youkuaiyun.com/download/wangbailin2009/10906719

<think> 我们讨论的是传统方式(非Spring框架)调用WebService时如何打印请求报文日志。传统方式通常指的是使用JAX-WS的Dispatch API、SOAPHandler或者直接获取传输层的消息。以下是几种可行的方法: ### 方法1: 使用SOAPHandler拦截请求报文 通过实现`SOAPHandler<SOAPMessageContext>`接口,可以拦截SOAP请求响应消息,并打印日志。 **步骤:** 1. 创建自定义的SOAPHandler 2. 将Handler注册到服务端口 **示例代码:** ```java import javax.xml.ws.handler.Handler; import javax.xml.ws.handler.HandlerResolver; import javax.xml.ws.handler.MessageContext; import javax.xml.ws.handler.PortInfo; import javax.xml.ws.handler.soap.SOAPHandler; import javax.xml.ws.handler.soap.SOAPMessageContext; import javax.xml.soap.SOAPMessage; import java.util.Set; import java.util.Collections; import java.io.ByteArrayOutputStream; public class LoggingHandler implements SOAPHandler<SOAPMessageContext> { @Override public boolean handleMessage(SOAPMessageContext context) { // 判断是请求还是响应 Boolean outbound = (Boolean) context.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY); // 只处理请求(出站消息) if (outbound) { SOAPMessage message = context.getMessage(); try { ByteArrayOutputStream out = new ByteArrayOutputStream(); message.writeTo(out); String xml = out.toString("UTF-8"); System.out.println("请求报文: \n" + xml); } catch (Exception e) { e.printStackTrace(); } } return true; // 继续处理链 } @Override public boolean handleFault(SOAPMessageContext context) { return true; } @Override public void close(MessageContext context) { } @Override public Set<QName> getHeaders() { return Collections.emptySet(); } } // 注册Handler到服务端口 Service service = Service.create(new URL("http://example.com/service?wsdl"), new QName("...")); service.setHandlerResolver(new HandlerResolver() { @Override public List<Handler> getHandlerChain(PortInfo portInfo) { return Collections.singletonList(new LoggingHandler()); } }); DataWebservice port = service.getPort(DataWebservice.class); ``` ### 方法2: 使用Dispatch API直接操作SOAP消息 如果你使用Dispatch API(`javax.xml.ws.Dispatch`)发送请求,可以直接获取到SOAP消息对象并打印。 **示例代码:** ```java import javax.xml.ws.Dispatch; import javax.xml.ws.Service; import javax.xml.soap.SOAPMessage; import javax.xml.transform.Source; import javax.xml.transform.stream.StreamResult; import java.io.StringWriter; Service service = Service.create(new URL("http://example.com/service?wsdl"), new QName("...")); Dispatch<SOAPMessage> dispatch = service.createDispatch(new QName("..."), SOAPMessage.class, Service.Mode.MESSAGE); // 创建SOAP请求消息(此处省略详细构造过程) SOAPMessage request = ...; // 打印请求报文 ByteArrayOutputStream out = new ByteArrayOutputStream(); request.writeTo(out); System.out.println("请求报文: \n" + out.toString("UTF-8")); // 发送请求 SOAPMessage response = dispatch.invoke(request); ``` ### 方法3: 启用CXF或Axis2的日志拦截器(如果使用这些框架) 如果你的传统方式是基于CXF或Axis2,它们提供了日志拦截器: - **CXF**: 使用`LoggingInInterceptor``LoggingOutInterceptor` - **Axis2**: 在`axis2.xml`中配置日志模块 但注意,题目要求传统方式(可能指JAX-WS原生方式),所以这里不展开。 ### 注意事项 1. **日志内容**: 打印的SOAP报文可能包含敏感信息,生产环境需谨慎。 2. **性能**: 频繁的日志输出可能影响性能,建议在调试时开启。 3. **编码**: 确保转换字节流时使用正确的字符集(如UTF-8)。 ### 总结 最通用的方法是使用`SOAPHandler`,它不依赖于特定框架,符合JAX-WS标准。通过拦截出站(请求)消息,即可打印完整的SOAP请求报文。 §§相关问题§§ 1. 如何在WebService调用打印响应报文日志? 2. 使用SOAPHandler时如何区分请求响应? 3. 传统WebService调用有哪些常用方法? </think> ### 传统方式调用WebService打印请求报文日志的方法 在传统Java WebService调用中(非Spring框架),打印SOAP请求报文日志主要有以下三种方法: #### 方法1:使用SOAPHandler拦截器(推荐) 通过实现`SOAPHandler`接口拦截请求消息并输出日志: ```java import javax.xml.ws.handler.soap.SOAPHandler; import javax.xml.ws.handler.soap.SOAPMessageContext; import javax.xml.soap.SOAPMessage; import java.io.ByteArrayOutputStream; import java.util.Set; public class LoggingHandler implements SOAPHandler<SOAPMessageContext> { @Override public boolean handleMessage(SOAPMessageContext context) { // 判断是否为出站请求 Boolean outbound = (Boolean) context.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY); if (outbound) { try { SOAPMessage msg = context.getMessage(); ByteArrayOutputStream out = new ByteArrayOutputStream(); msg.writeTo(out); // 将SOAP消息写入输出流 String xml = new String(out.toByteArray(), "UTF-8"); System.out.println("SOAP请求报文:\n" + xml); // 打印日志 } catch (Exception e) { e.printStackTrace(); } } return true; } // 其他必须实现的方法(简化版) @Override public Set<QName> getHeaders() { return null; } @Override public boolean handleFault(SOAPMessageContext context) { return true; } @Override public void close(MessageContext context) {} } ``` **注册Handler到服务端口**: ```java Service service = Service.create(wsdlURL, serviceName); service.setHandlerResolver(portInfo -> Collections.singletonList(new LoggingHandler())); DataWebservice port = service.getPort(DataWebservice.class); // 获取带日志拦截的端口 ``` #### 方法2:通过MessageContext获取报文 在服务实现类中直接获取原始SOAP消息: ```java @WebService public class MyWebServiceImpl { @Resource private WebServiceContext context; public String myMethod(String param) { // 获取SOAP消息 MessageContext msgContext = context.getMessageContext(); SOAPMessage request = (SOAPMessage) msgContext.get(MessageContext.SERVLET_REQUEST); // 转换为XML字符串 ByteArrayOutputStream out = new ByteArrayOutputStream(); request.writeTo(out); String requestXml = out.toString("UTF-8"); System.out.println("原始请求:\n" + requestXml); // 打印日志 // 业务逻辑 return "Processed: " + param; } } ``` #### 方法3:使用Apache CXF拦截器(需CXF依赖) 若项目使用CXF框架,可添加内置日志拦截器: ```java import org.apache.cxf.interceptor.LoggingInInterceptor; import org.apache.cxf.interceptor.LoggingOutInterceptor; // 客户端配置 JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean(); factory.getInInterceptors().add(new LoggingInInterceptor()); // 入站日志 factory.getOutInterceptors().add(new LoggingOutInterceptor()); // 出站日志 factory.setServiceClass(DataWebservice.class); factory.setAddress("http://endpoint-url"); DataWebservice service = (DataWebservice) factory.create(); ``` #### 配置建议 1. **日志级别控制**:生产环境应使用日志框架(如Log4j)并设置DEBUG级别 ```java private static final Logger logger = Logger.getLogger(LoggingHandler.class); if(logger.isDebugEnabled()) { logger.debug("SOAP请求:\n" + xml); } ``` 2. **敏感信息过滤**:打印前过滤密码等敏感字段 3. **性能优化**:在高并发场景限制日志输出频率 ### 关键区别总结 | 方法 | 适用场景 | 依赖项 | 复杂度 | |--------------|-------------------------|-------------|--------| | SOAPHandler | 标准JAX-WS | 无 | ★☆☆ | | MessageContext| 服务端实现 | `javax.annotation.Resource` | ★★☆ | | CXF拦截器 | Apache CXF框架项目 | CXF库 | ★☆☆ | > **最佳实践**:优先使用`SOAPHandler`方案,因其符合JAX-WS标准且无需特定框架支持。在OSGi环境中需注意类加载器隔离问题(如引用[^2]所述)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值