java webservice CXF JAX-WS(SOAP) + JAX-RS(RESTfull)
一、环境说明:
1>.在ssh(Struts2+Spring+Hibernate)架构中加入webservice服务,web服务使用Apache CXF,采用cxf+spring的方式发布web服务
2>. Apache CXF Releases 2.7.5, apache-cxf-2.7.5.zip 下载地址 http://www.apache.org/dyn/closer.cgi?path=/cxf/2.7.5/apache-cxf-2.7.5.zip
二、环境配置
1>.导入jar依赖
cxf-2.7.5.jar neethi-3.0.2.jar spring-asm-3.0.7.RELEASE.jar spring-beans-3.0.7.RELEASE.jar spring-context-3.0.7.RELEASE.jar spring-core-3.0.7.RELEASE.jar spring-expression-3.0.7.RELEASE.jar spring-web-3.0.7.RELEASE.jar spring-aop-3.0.7.RELEASE.jar slf4j-api-1.7.5.jar xmlschema-core-2.0.3.jar httpasyncclient-4.0-beta3.jar httpclient-4.2.1.jar httpcore-4.2.2.jar httpcore-nio-4.2.2.jar wsdl4j-1.6.3.jar javax.ws.rs-api-2.0-m10.jar jaxb-impl-2.2.6.jar jettison-1.3.3.jar wss4j-1.6.10.jar woodstox-core-asl-4.2.0.jar stax2-api-3.1.1.jar
2>.web.xml 中的配置(spring和cxf的servlet)
<listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class></listener> <context-param> <param-name>contextConfigLocation</param-name> <param-value> <!-- webservice --> classpath:/applicationContext_ws.xml </param-value> </context-param> <!-- webservice --> <servlet> <servlet-name>CXFService</servlet-name> <servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>CXFService</servlet-name> <url-pattern>/cxfservlet/*</url-pattern> </servlet-mapping>
3>.struts.xml 配置 webservice servlet ,要不然请把struts的url-pattern尽量带上后缀,比如 *.action,而不要配置为 /* 拦截所有请求,不然就需要有这一步在struts.xml的文件里配置放过webservice servlet 的请求
<!-- webservice --> <package name="cxf" extends="struts-default"> <action name="cxfservlet/*"> <result>cxfservlet/{1}</result> </action> </package>
4>.定义DTO,用户请求和返回xml或者json和javaBean的相互转换
package com.emcs.dm.bean; import java.util.List; import javax.xml.bind.annotation.XmlRootElement; import javax.xml.bind.annotation.XmlType; /** * 使用cxf默认自带的jettison-1.3.3.jar对json支持 * 需要返回List集合时需要使用一个包装对象 * */ @XmlRootElement @XmlType(name="",propOrder="hosts") public class DMHostMachines { private List<DMHostMechine> hosts; public List<DMHostMechine> getHosts() { return hosts; } public void setHosts(List<DMHostMechine> hosts) { this.hosts = hosts; } } package com.emcs.dm.bean; import java.io.Serializable; import java.util.Date; import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlRootElement; import javax.xml.bind.annotation.XmlType; @XmlRootElement //将类或枚举类型映射到 XML 元素 @XmlType(name="DMHostMechine") @XmlAccessorType(XmlAccessType.FIELD) public class DMHostMechine implements Serializable { /** * */ private static final long serialVersionUID = 8206718006545121379L; private Integer hostId; private String enterpriseName; private Date lastUploadTime; public DMHostMechine() { } public DMHostMechine(Integer hostId,String enterpriseName,Date lastUploadTime) { this.hostId = hostId; this.enterpriseName = enterpriseName; this.lastUploadTime = lastUploadTime; } public Integer getHostId() { return hostId; } public void setHostId(Integer hostId) { this.hostId = hostId; } public String getEnterpriseName() { return enterpriseName; } public void setEnterpriseName(String enterpriseName) { this.enterpriseName = enterpriseName; } public Date getLastUploadTime() { return lastUploadTime; } public void setLastUploadTime(Date lastUploadTime) { this.lastUploadTime = lastUploadTime; } @Override public String toString() { return super.toString(); } }
5>.定义发布接口
package com.ws.service; import java.util.List; import javax.jws.WebMethod; import javax.jws.WebService; import javax.jws.soap.SOAPBinding; import javax.jws.soap.SOAPBinding.Style; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.PathParam; import javax.ws.rs.Produces; import javax.ws.rs.core.MediaType; import com.emcs.dm.bean.DMHostMachines; import com.emcs.dm.bean.DMHostMechine; import com.framework.exception.BaseException; @WebService(targetNamespace="com.ws.service") //for SOAP @SOAPBinding(style=Style.RPC) //for SOAP @Produces("*/*") //for REST public interface IDMRequestService { @WebMethod(operationName="request") //for SOAP @GET //for REST @Path("/{name}/request") @Produces(MediaType.TEXT_PLAIN) String request(@PathParam("name") String name); @WebMethod(operationName="getAllHostMachine") @GET @Path("/hostmachine") @Produces({MediaType.APPLICATION_XML,MediaType.APPLICATION_JSON}) List<DMHostMechine> getAllHostMachine() throws BaseException; @WebMethod(operationName="getHosts") @GET @Path("/hosts") @Produces({MediaType.APPLICATION_XML,MediaType.APPLICATION_JSON}) DMHostMachines getHosts() throws BaseException; }
6>.定义实现类
package com.ws.service.impl; import java.util.List; import javax.jws.WebService; import com.emcs.dm.bean.DMHostMachines; import com.emcs.dm.bean.DMHostMechine; import com.framework.base.service.impl.DBServiceImpl; import com.framework.exception.BaseException; import com.ws.service.IDMRequestService; /** * @author Admin * @description Expose CXF Service With REST And SOAP * * @Consumes annotation specifies, the request is coming from the client * you can specify the Mime type as @Consumes("application/xml"), if the request is in xml format * * @Produces annotation specifies, the response is going to the client * you can specify the Mime type as @Produces ("application/xml"), if the response need to be in xml format * */ @WebService(endpointInterface="com.ws.service.IDMRequestService") public class DmRequestServiceImpl extends DBServiceImpl implements IDMRequestService { @Override public List<DMHostMechine> getAllHostMachine() throws BaseException { String hql = "select new com.emcs.dm.bean.DMHostMechine(v.id,b.enterpriseName,v.lastUploadTime) " + "from DmVideo v,BbEnterprise b where v.enterpriseId=b.id"; @SuppressWarnings("unchecked") List<DMHostMechine> ts = this.getDao().query(hql); return ts; } @Override public String request(String name) { return "hello world"; } @Override public DMHostMachines getHosts() throws BaseException { List<DMHostMechine> ts = this.getAllHostMachine(); DMHostMachines hosts = new DMHostMachines(); hosts.setHosts(ts); return hosts; } }
7>.在classpath下新建webservice的受spring管理的配置文件applicationContext_ws.xml(在web.xml中加入,请参照环境配置第二步),并加入spring的上下文管理位置 contextConfigLocation
<?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:tx="http://www.springframework.org/schema/tx" xmlns:jaxws="http://cxf.apache.org/jaxws" xmlns:cxf="http://cxf.apache.org/core" xmlns:jaxrs="http://cxf.apache.org/jaxrs" xmlns:wsa="http://cxf.apache.org/ws/addressing" xmlns:util="http://www.springframework.org/schema/util" xsi:schemaLocation=" http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.1.xsd http://cxf.apache.org/core http://cxf.apache.org/schemas/core.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://cxf.apache.org/jaxrs http://cxf.apache.org/schemas/jaxrs.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd"> <!-- REST --> <import resource="classpath:META-INF/cxf/cxf.xml" /> <!-- SOAP --> <import resource="classpath:META-INF/cxf/cxf-servlet.xml" /> <import resource="classpath:META-INF/cxf/cxf-extension-soap.xml" /> <!-- 注入实现类 --> <bean id="hello" class="com.ws.service.impl.DmRequestServiceImpl" scope="prototype"> <property name="dao" ref="baseDao"></property> <property name="entity" ref="dmVideoBean"></property> </bean> <util:list id="jsonKeys"> <value>hosts</value> </util:list> <!-- 对json提供支持 --> <bean id="jsonProvider" class="org.apache.cxf.jaxrs.provider.json.JSONProvider"> <property name="dropRootElement" value="true"/> <property name="dropCollectionWrapperElement" value="true"/> <property name="serializeAsArray" value="true"/> <!-- <property name="arrayKeys" ref="jsonKeys"/> --> </bean> <cxf:bus> <cxf:inInterceptors> <bean class="org.apache.cxf.interceptor.LoggingInInterceptor" /> </cxf:inInterceptors> </cxf:bus> <!-- Expose CXF Service With REST And SOAP --> <!-- SOAP SERVER(JAX-WS) <jaxws:endpoint id="soapService" address="/soap" implementor="#hello" publish="true" /> --> <jaxws:server serviceClass="com.ws.service.IDMRequestService" serviceBean="#hello" address="/soap"> </jaxws:server> <!-- REST SERVER(restful/JAX-RS) --> <jaxrs:server address="/rest" id="base" publishedEndpointUrl="http://外网IP地址:8000/cxfservlet/rest"> <jaxrs:serviceBeans> <ref bean="hello" /> </jaxrs:serviceBeans> <!-- --> <jaxrs:providers> <ref local="jsonProvider"/> </jaxrs:providers> </jaxrs:server> <cxf:bus> <cxf:features> <cxf:logging /> </cxf:features> </cxf:bus> </beans>
8>.这里使用tomcat服务器,启动服务器在浏览器里输入
http://localhost:8080/cxfservlet/ 访问webservice服务,出现下面画面说明发布成功
发布成功的SOAP,也可以通过 http://localhost:8080/cxfservlet/soap?wsdl查看wsdl
发布成功的REST,也可以通过 http://127.0.0.1:8080/cxfservlet/rest?_wadl查看wadl
9>.客户端调用,远程调用
[list]
操作步骤:
DOS命令窗口→切换到cxf SDK bin目录
通过执行wsdl2java -h 命令查看各参数作用
执行命令
wsdl2java -p soap.client –d E:\ http://localhost:8080/cxfservlet/soap?wsdl
在E盘下生成soap.client文件夹,并在文件夹中生成客户端代码
其中package-info.java、ObjectFactory.java 是JAXB 需要的文件;IDMRequestServiceService.java
继承自 javax.xml.ws.Service 类,用于提供 WSDL 的客户端视图
package com.ws.service.test; import java.util.ArrayList; import java.util.Collection; import java.util.List; import javax.ws.rs.core.MediaType; import org.apache.cxf.jaxrs.client.WebClient; import org.apache.cxf.jaxrs.provider.json.JSONProvider; import com.emcs.dm.bean.DMHostMechine; public class WsClient { public static void main(String[] args) { /* ----------------------标准 JAX-WS API-----------------------------------*/ /** * new QName(arg0,arg1) * arg0 -------------------- targetNamespace * arg1 -------------------- 对应<wsdl:service 的那么属性,也就是在发布service是的serviceName */ QName qname = new QName("com.ws.service","IDMRequestServiceService"); String wsdlLocation = "http://localhost:8080/cxfservlet/soap?wsdl"; try { IDMRequestServiceService serviceName = new IDMRequestServiceService(new URL(wsdlLocation),qname); IDMRequestService jaxWsService = serviceName.getIDMRequestServicePort(); DMHostMechineArray arr = jaxWsService.getAllHostMachine(); List<DMHostMechine> list = arr.getItem(); if(list.size() > 0) { System.out.println(list.size()); } } catch (MalformedURLException e) { e.printStackTrace(); } catch (BaseException_Exception e) { e.printStackTrace(); } /* ----------------------------CXF----------------------------------- JaxWsProxyFactoryBean jwpf = new JaxWsProxyFactoryBean(); jwpf.setAddress("http://localhost:8080/cxfservlet/soap"); jwpf.setServiceClass(IDMRequestService.class); Object o = jwpf.create(); IDMRequestService service = (IDMRequestService)o; try { DMHostMechineArray arr = service.getAllHostMachine(); List<DMHostMechine> list = arr.getItem(); if(list.size() > 0) { System.out.println(list.size()); } } catch (BaseException_Exception e) { e.printStackTrace(); } --------------------------------------------------------------------------*/ } }
package com.ws.service.test; import java.util.ArrayList; import java.util.Collection; import java.util.List; import javax.ws.rs.core.MediaType; import org.apache.cxf.jaxrs.client.WebClient; import org.apache.cxf.jaxrs.provider.json.JSONProvider; import com.emcs.dm.bean.DMHostMechine; public class WsClient { public static void main(String[] args) { String restBaseUrl = "http://localhost:8080/cxfservlet/rest"; WebClient client = WebClient.create(restBaseUrl); client.type(MediaType.APPLICATION_XML).accept(MediaType.APPLICATION_XML); Collection<? extends DMHostMechine> c = client.path("hostmachine").getCollection(DMHostMechine.class); if(!c.isEmpty()) { System.out.println(c.size()); } /* String restBaseUrl = "http://localhost:8080/cxfservlet/rest"; WebClient client = WebClient.create(restBaseUrl); client.type(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON); DMHostMachines c = client.path("hosts").get(DMHostMachines.class); if(c != null) { List<DMHostMechine> l = c.getHosts(); } */ } }
RESTFull 使用http协议,可以在浏览器里直接访问
比如可以通过后缀?_type=xml 或者 ?_type=json 来请求响应 XML数据 或者 json 数据,比如:
http://localhost:8080/cxfservlet/rest/hosts?_type=xml
[/list]