Java WebService
运行环境
- eclipse
- JDK 1.8
- Tomcat 7.0
- cxf 3.2.1
CXF下载
http://download.csdn.net/download/yioow/10147610(cxf 3.2.1)
http://cxf.apache.org/download.html(官方)
1.新建Dynamic Web Project
直接Finish即可。
2.1 把cxf放入项目里
解压缩cxf文件 -> 把lib目录下的所以文件放入项目lib 目录下
附:这时项目可能报一个Missing library: xdoclet-1.2.1.jar. Select the home directory for XDoclet. 1.2.1的错误(可以不管)
修复办法:
下载两个包,xdoclet-1.2.3.jar,xjavadoc-1.1.jar
http://download.csdn.net/download/yioow/10147915
把这两个jar也放到项目lib目录下
2.2 加入aspectjweaver-1.5.0 jar
不加入会报一个Error creating bean with name ‘cxf’ defined in class path resource [META-INF/cxf/cxf.xml]: BeanPostProcessor before instantiation of bean failed; nested exception is java.lang.NoClassDefFoundError: org/aspectj/lang/annotation/Aspect
暂时不知道是什么意义,应该是缺少一个aspectj这个jar。
2.3 其他jar
1.commons-httpclient-3.1 (发送请求工具类)
2.commons-lang-2.6 (发送请求工具类)
3.xstream-1.3 (对象序列化工具类)
4.dom4j-1.6.1 (xml工具类)
3. 代码部分
3.1配置spring xml
spring_config_base.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.2.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.2.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.2.xsd">
<context:annotation-config />
<aop:aspectj-autoproxy proxy-target-class="true" />
<context:component-scan base-package="com.zhuyj.*.*" />
</beans>
spring_config_soap.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:jaxws="http://cxf.apache.org/jaxws"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd">
<import resource="classpath:META-INF/cxf/cxf.xml"/>
<!-- <import resource="classpath:META-INF/cxf/cxf-extension-soap.xml"/> -->
<!-- <import resource="classpath:META-INF/cxf/cxf-servlet.xml"/> -->
<!-- TianMaoMK -->
<jaxws:endpoint id="PushInterfaceOfSupermarketTianMao" implementor="#PushInterfaceOfSupermarketTianMaoImpl" address="/TM" />
<bean id="PushInterfaceOfSupermarketTianMaoImpl" class="com.zhuyj.soap.webService.PushInterfaceOfSupermarketTianMaoImpl"></bean>
</beans>
3.2 web.xml
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" version="3.0">
<display-name>webService-Test</display-name>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.htm</welcome-file>
<welcome-file>index.jsp</welcome-file>
<welcome-file>default.html</welcome-file>
<welcome-file>default.htm</welcome-file>
<welcome-file>default.jsp</welcome-file>
</welcome-file-list>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:../xml/spring_config_*.xml</param-value>
</context-param>
<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
<servlet>
<servlet-name>CXFServlet</servlet-name>
<servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>CXFServlet</servlet-name>
<url-pattern>/soap/*</url-pattern>
</servlet-mapping>
</web-app>
3.3 实体类
这里就不做细说了,因为类比较多,这边截一下图解释一下
这是其中一个实体类,主要说一下
@XmlType propOrder 这是序列化的顺序
@XStreamAlias 生成xml的标签名称
@XmlElement 接收xml的标签名称
其他可以自己查查,这里就不做解释了
3.4 WebService类
标签参考:http://blog.csdn.net/u011666411/article/details/48087073
接口类
@WebService
public interface PushInterfaceOfSupermarketTianMao {
@WebMethod
@WebResult(name="ResultMessage", targetNamespace="http://webService.soap.zhuyj.com/")
public abstract responseMessage recMarketNotify(@WebParam(name="requestMessage") RequestMessageOfTianMao requestMessageOfTianMao);
}
实现类
@WebService(endpointInterface="com.zhuyj.soap.webService.PushInterfaceOfSupermarketTianMao")
public class PushInterfaceOfSupermarketTianMaoImpl implements PushInterfaceOfSupermarketTianMao{
private static Logger logger = LoggerFactory.getLogger(PushInterfaceOfSupermarketTianMaoImpl.class);
@Override
@WebMethod//JavaBeans 端点的服务器端点实现类
@WebResult(name="ResponseMessage", targetNamespace="http://webService.soap.zhuyj.com/")
public responseMessage recMarketNotify(@WebParam(name="requestMessage")RequestMessageOfTianMao requestMessageOfTianMao ) {
logger.info("请求参数报文: "+requestMessageOfTianMao.toString());
}
return createResultMessage(requestMessageOfTianMao.getMessageHeader());
}
private responseMessage createResultMessage(com.zhuyj.soap.webService.entity.request.Supermarket.MessageHeader reqMessageHeader){
responseMessage rm = new responseMessage();
com.zhuyj.soap.webService.entity.response.Supermarket.MessageHeader resMessageHeader = new MessageHeader();
resMessageHeader.setPhoneNumber("测试1");
resMessageHeader.setStatus("测试2");
resMessageHeader.setTime("测试3");
rm.setMessageHeader(resMessageHeader);
return rm;
}
}
下面的方法是返回数据的方法
3.5 测试类
package com.zhuyj.soap.webService;
import java.beans.PropertyDescriptor;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.io.StringWriter;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.methods.InputStreamRequestEntity;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.methods.RequestEntity;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.dom4j.Attribute;
import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import com.thoughtworks.xstream.XStream;
import com.zhuyj.soap.webService.entity.request.Supermarket.MessageHeader;
import com.zhuyj.soap.webService.entity.request.Supermarket.RequestMessageOfTianMao;
import com.zhuyj.soap.webService.entity.request.Supermarket.TianMaoInformation;
import com.zhuyj.soap.webService.entity.request.Supermarket.TianMaoMessageBody;
import com.zhuyj.soap.webService.util.HttpUtil;
import com.zhuyj.soap.webService.util.XmlUtil;
public class DynamicSoapClientCall {
private static Log logger = LogFactory.getLog(DynamicSoapClientCall.class);
//请求报文头
private String str = "";
//请求地址
private String wsdlLocation;
//返回的数据
private static String soapResponseData;
private static com.zhuyj.soap.webService.entity.response.Supermarket.MessageHeader messageHeaderxxx = new com.zhuyj.soap.webService.entity.response.Supermarket.MessageHeader();
public String getSoapResponseData(){
return this.soapResponseData;
}
public void setSoapResponseData(String soapResponseData) {
this.soapResponseData = soapResponseData;
}
/**
*
* @param wsdlLocation
*/
public DynamicSoapClientCall(String wsdlLocation){
/**
* Envelope(信封) 必选
* Header(报头) 可选
* Body(主体) 必选
* .....
*/
StringBuffer sb = new StringBuffer();
sb.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
sb.append("<soapenv:Envelope ");
sb.append("xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\" ");
sb.append("xmlns:web=\"http://webService.soap.zhuyj.com/\">");
//sb.append("soapenv:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">");//可以不加
sb.append("<soapenv:Header/>");
sb.append("<soapenv:Body>");
sb.append("<web:recMarketNotify>");
sb.append("flag");
sb.append("</web:recMarketNotify>");
sb.append("</soapenv:Body>");
sb.append("</soapenv:Envelope>");
this.str = sb.toString();
this.wsdlLocation = wsdlLocation;
}
/**
*
* @param messageHeader 请求头
* @param obj 请求体
* @return int 状态码
* @throws Exception
*/
public int invoke(MessageHeader messageHeader, Object obj)throws Exception{
//请求地址
//PostMethod postMethod = new PostMethod(this.wsdlLocation);
//生成请求报文
String soapRequestData = buildRequestData(messageHeader, obj);
Map<String,Object> map = null;
map = HttpUtil.SOPAPost(this.wsdlLocation, soapRequestData, "utf-8");
//byte[] bytes = soapRequestData.getBytes("utf-8");
//InputStream inputStream = new ByteArrayInputStream(bytes, 0, bytes.length);
//RequestEntity requestEntity = new InputStreamRequestEntity(inputStream, bytes.length, "application/soap+xml; charset=utf-8");
//postMethod.setRequestEntity(requestEntity);
//HttpClient httpClient = new HttpClient();
//状态码
int statusCode = (Integer) map.get("statusCode");//httpClient.executeMethod(postMethod);
//返回数据
this.soapResponseData = (String) map.get("response");//postMethod.getResponseBodyAsString();
return statusCode;
}
/**
* 生成请求报文
* @param messageHeader 请求头
* @param obj 请求体
* @return String 请求报文
* @throws JAXBException
*/
private String buildRequestData(MessageHeader messageHeader, Object obj)throws JAXBException{
RequestMessageOfTianMao rm = new RequestMessageOfTianMao();
rm.setMessageHeader(messageHeader);
rm.setTianMaoMessageBody((TianMaoMessageBody) obj);
String result = "";
result = XmlUtil.toXml(rm);//java 转换 xml
this.str = this.str.replace("flag", result);
logger.info("请求完整报文: " + this.str);
return this.str;
}
/**
* 没有调用???
* @param node
*/
public static void getNodes(Element node){
List<Attribute> listAttr = node.attributes();
String name;
for (Attribute attr : listAttr) {
name = attr.getName();
String value = attr.getValue();
System.out.println("属性名称:" + name + "---->属性值:" + value);
}
List<Element> listElement = node.elements();
if ((StringUtils.isNotEmpty(node.getName())) && (node.getName().equals("ResultCode"))) {
if ((StringUtils.isNotEmpty(node.getTextTrim())) && (node.getTextTrim().equals("0")))
logger.info("soap请求返回成功:" + node.getTextTrim());
else {
logger.info("soap请求返回失败!错误码:" + node.getTextTrim());
}
}
for (Element e : listElement)
getNodes(e);
}
/**
* @param args
* @throws Exception
*/
public static void main(String[] args) throws Exception{
DynamicSoapClientCall dynamicHttpclientCall = new DynamicSoapClientCall("http://localhost:8080/webService-Test/soap/TM");//?wsdl
//设置发送请求内容头
MessageHeader messageHeader = new MessageHeader();
messageHeader.setSupermarketName("天猫");
messageHeader.setAddress("www.tmall.com");
messageHeader.setBusinessHours("00:00-24:00");
//设置发送请求内容体
TianMaoMessageBody messageBody = new TianMaoMessageBody();
messageBody.setSpecialCode("00010");
messageBody.setSpecialTime("9:00-12:00");
List<TianMaoInformation> tianMaoDiscountInformation = new ArrayList<TianMaoInformation>();
tianMaoDiscountInformation.add(new TianMaoInformation("鼠标","www.tmall.com/sb","10","5"));
tianMaoDiscountInformation.add(new TianMaoInformation("键盘","www.tmall.com/jp","20","8"));
messageBody.setInformation(tianMaoDiscountInformation);
//发送请求,返回状态码
int statusCode = dynamicHttpclientCall.invoke(messageHeader, messageBody);
logger.info("状态码: "+statusCode);
//判断是否成功
if (statusCode == 200) {
logger.info("调用成功!");
logger.info("返回的数据: "+soapResponseData);
//xml 转 java
XmlUtil.getRoot(soapResponseData);
logger.info("-----------------------");
logger.info(messageHeaderxxx.getPhoneNumber());
logger.info(messageHeaderxxx.getStatus());
logger.info(messageHeaderxxx.getTime());
logger.info("-----------------------");
}else{
logger.info("调用失败!错误码:" + statusCode);
}
// <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
// <soap:Body>
// <ns2:recFlowNotifyResponse xmlns:ns2="http://webService.soap.zhuyj.com/">
// <ns2:ResultMessage>
// <MessageHeader>
// <PhoneNumber>测试1</PhoneNumber>
// <Status>测试2</Status>
// <Time>测试3</Time>
// </MessageHeader>
// </ns2:ResultMessage>
// </ns2:recFlowNotifyResponse>
// </soap:Body>
// </soap:Envelope>
}
}
4.测试
先把项目在项目里跑起来,再单独跑DynamicSoapClientCall类,
good Luck!