WebService (三)使用CXF框架開發webservice
1、CXF框架概念介紹
Apache CXF 是一個開源的 Services 框架,CXF 幫助您來構建和開發 Services 這些 Services 可以支持多種協議,比如:SOAP、POST/HTTP、RESTful HTTP CXF 大大簡化了 Service可以天然地和 Spring 進行無縫集成。
1、1ServerFactoryBean來發布web服務
服務類代碼如下:
// 註解是無效的 @WebService(name="Hello",targetNamespace="http://icast.cn") public class HelloWorld { public String sayHi(String name) { return "hello---->" + name; } } |
發佈類代碼如下:
public static void main(String[] args) { // 發佈服務的類, 類似Endpoint ServerFactoryBean serverFactoryBean=new ServerFactoryBean(); // 註冊服務器地址和端口 serverFactoryBean.setAddress("http://127.0.0.1:9999/hello"); // 註冊哪個類提供服務 serverFactoryBean.setServiceBean(new HelloWorld()); // 發佈一個cxf服務 serverFactoryBean.create(); // 一分鐘有服務終止 Thread.sleep(1 * 60 * 1000); // 正常退出程序 System.exit(0); } |
ServerFactoryBean注意事項:
這種方式沒有添加webService註解,也就是說沒有註解也可以發佈webService服務,但是這種方式不是很規範,比如我們不可以通過註解的方式來修改WSDL的標籤信息,
1、2JaxWsServerFactoryBean來發布web服務
1. JaxWsServerFactoryBean是ServerFactoryBean的子類,也是功能擴展類。
2. 此類,必須要在被髮布爲服務的類上添加@WebService註解,如果不加註解,雖然不出錯,但也不會對外暴露任何方法。使用此類生成的wsdl文件更加規範
3. 更重要的是可以通過添加攔截器攔截請求.
客戶端代碼如下:
@WebService public class HelloWorld { public String sayHi(String name) { return "hello---->" + name; } } |
發佈類代碼如下:
public static void main(String[] args)throws Exception { // 發佈服務的類, 類似Endpoint JaxWsServerFactoryBean jaxWsServer=new JaxWsServerFactoryBean(); // 註冊服務器地址和端口 jaxWsServer.setAddress("http://127.0.0.1:9999/hello"); // 註冊哪個類提供服務 jaxWsServer.setServiceBean(new HelloWorld()); // 配置輸入輸出日誌攔截器 jaxWsServer.getInInterceptors().add(new LoggingInInterceptor()); jaxWsServer.getOutInterceptors().add(new LoggingOutInterceptor()); // 發佈一個cxf服務 jaxWsServer.create(); // 一分鐘有服務終止 Thread.sleep(1 * 60 * 1000); // 正常退出程序 System.exit(0); } |
訪問:http://127.0.0.1:9999/hello?wsdl 控制檯第一次握手攔截器日誌如下:
---------------------------- ID: 1 Address: http://127.0.0.1:9999/hello?wsdl Http-Method: GET Content-Type: Headers: {Accept=[*/*], accept-encoding=[gzip, deflate], Accept-Language=[zh-CN], connection=[Keep-Alive], Content-Type=[null], Host=[127.0.0.1:9999], User-Agent=[Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0)]} -------------------------------------- |
通過Java客戶端調用服務類
public static void main(String[] args) { HelloWorldService helloWorldService=new HelloWorldService(); HelloWorld helloWorld=helloWorldService.getHelloWorldPort(); System.out.println(helloWorld.sayHi("test")); } |
攔截器日誌如下:
---------------------------- ID: 1 Address: http://127.0.0.1:9999/hello?wsdl Http-Method: GET Content-Type: text/xml Headers: {Accept=[*/*], Cache-Control=[no-cache], connection=[keep-alive], content-type=[text/xml], Host=[127.0.0.1:9999], Pragma=[no-cache], User-Agent=[Apache CXF 2.4.2]} -------------------------------------- 2013-1-6 11:28:17 org.apache.cxf.interceptor.AbstractLoggingInterceptor log 信息: Inbound Message ---------------------------- ID: 2 Address: http://127.0.0.1:9999/hello Encoding: UTF-8 Http-Method: POST Content-Type: text/xml; charset=UTF-8 Headers: {Accept=[*/*], Cache-Control=[no-cache], connection=[keep-alive], Content-Length=[191], content-type=[text/xml; charset=UTF-8], Host=[127.0.0.1:9999], Pragma=[no-cache], SOAPAction=[""], User-Agent=[Apache CXF 2.4.2]} Payload: <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"><soap:Body><ns2:sayHi xmlns:ns2="http://jaxws.cxf.g.itcast.cn/"><arg0>test</arg0></ns2:sayHi></soap:Body></soap:Envelope> -------------------------------------- 2013-1-6 11:28:17 org.apache.cxf.interceptor.AbstractLoggingInterceptor log 信息: Outbound Message --------------------------- ID: 2 Encoding: UTF-8 Content-Type: text/xml Headers: {} Payload: <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"><soap:Body><ns2:sayHiResponse xmlns:ns2="http://jaxws.cxf.g.itcast.cn/"><return>hello---->test</return></ns2:sayHiResponse></soap:Body></soap:Envelope> -------------------------------------- |
1、3CXF與Spring集成發佈WebService
前面的服務發佈包括創建服務類都是硬編碼的方式.是否可以使用配置的方式來發布服務類呢. 答案是肯定的這就要同Spring集成了, 由於cxf的項目已經集成了Spring(自帶了Spring lib)所以CXF的服務都是在Spring的配置文件中完成的, 並且我們需要把項目發佈到tomcat中,所以我們可以創建一個web項目
配置開發環境:
l 建立一個web項目
l 準備所有jar包,將CXF_HOME\lib項目下的所有jar包,全部都拷貝新項目的lib目錄下.其中裏面已經包含了Sring3.0的jar包 其中jetty 服務器的包可以不要.因爲我們要部署的tomcat服務器中了
l 在web.xml中配置cxf的核心servlet,CXFServlet
l 此配置文件的作用類 攔截/ws/*的所有請求 類似Struts2的過濾器
<servlet> <servlet-name>cxf</servlet-name> <servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>cxf</servlet-name> <url-pattern>/ws/*</url-pattern> </servlet-mapping> |
通過Spring配置文件發佈服務
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:jaxws="http://cxf.apache.org/jaxws" xmlns:p="http://www.springframework.org/schema/p" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://cxf.apache.org/core http://cxf.apache.org/schemas/core.xsd http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd"> <!-- 這樣配置自身的服務也可以使用 --> <bean id="userImpl" class="cn.itcast.i.cxf.spring.ws.UserImpl" /> <!-- id:邏輯名 serviceClass=服務接口類 address:調用的路徑 http://localhost:8888/項目名/ws/hello?wsdl> --> <jaxws:server id="userService" serviceClass="cn.itcast.i.cxf.spring.ws.IUser" address="/hello"> <jaxws:serviceBean> <ref bean="userImpl" /> </jaxws:serviceBean> <jaxws:inInterceptors> <bean class="org.apache.cxf.interceptor.LoggingInInterceptor" /> </jaxws:inInterceptors> <jaxws:outInterceptors> <bean class="org.apache.cxf.interceptor.LoggingOutInterceptor" /> </jaxws:outInterceptors> </jaxws:server> </beans> |
服務接口如下:
@WebService public interface IUser { public void saveUser(User user); public User getUser(int uid); } |
服務類如下:
public class UserImpl implements IUser { private List<User> users=new ArrayList<User>();
public User getUser(int uid) { for(User temp:users){ if(temp.getUid()==uid){ return temp; } } return null; } public void saveUser(User user) { // TODO Auto-generated method stub users.add(user); } } |
實體類如下:
public class User { private int uid; private String uname; public int getUid() { return uid; } public void setUid(int uid) { this.uid = uid; } public String getUname() { return uname; } public void setUname(String uname) { this.uname = uname; } } |
通過JSP+Servlet調用本地服務:
Servlet在web.xml中配置如下:
<servlet> <servlet-name>cxf</servlet-name> <servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class> <load-on-startup>1</load-on-startup> </servlet> <servlet> <servlet-name>UserServlet</servlet-name> <servlet-class>cn.itcast.i.cxf.servlet.UserServlet</servlet-clas> </servlet> |
Servlet核心代碼調用如下:
public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { User user = new User(); user.setUid(Integer.parseInt(request.getParameter("uid"))); user.setUname(request.getParameter("uname")); userImpl.saveUser(user); } public void init() throws ServletException { // Put your code here WebApplicationContext springContext = WebApplicationContextUtils .getWebApplicationContext(this.getServletContext()); userImpl = (IUser) springContext.getBean("userImpl"); } |
WEB頁面調用代碼如下:
<form action="/day01/servlet/UserServlet" method="post"> 用戶編號:<input type="text" name="uid" /><br/> 用戶名:<input type="text" name="uname" /><br/> <input type="submit" value="提交" /> </form> |
通過Java遠程調用訪問CXF+Spring服務如下:
public static void main(String[] args) { IUserService userService=new IUserService(); User user=new User(); user.setUid(1); user.setUname("admin"); userService.getIUserPort().saveUser(user); User temp=userService.getIUserPort().getUser(1); System.out.println(temp.getUid() + "|" + temp.getUname()); } |
通過ajax遠程調用訪問CXF+Spring服務如下:
<body> <button οnclick="mobile()">cxf+Spring測試</button> </body> <script language="javascript"> // 1:創建XMLHTTP對象 var xhr=null; function mobile(){ // 聲明在訪問的ws的地址 var url="http://localhost:8888/day01/ws/hello"; // 書寫要發送的XML文件,即 SOAP var soap='<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"><soap:Body>' + '<ns2:getUser xmlns:ns2="http://ws.spring.cxf.i.itcast.cn/"><arg0>1</arg0></ns2:getUser></soap:Body></soap:Envelope>'; // 3:打開連接 xhr.open("POST",url,true); xhr.setRequestHeader("Content-Type","text/xml; charset=utf-8"); xhr.setRequestHeader("Accept","*/*"); xhr.onreadystatechange=callBack; xhr.send(soap); } function callBack(){ if(xhr.readyState==4){ var a=xhr.responseXML; alert(xhr.responseXML.getElementsByTagName("uid")[0].text); alert(xhr.responseXML.getElementsByTagName("uname")[0].text); } } function init(){ xhr=new ActiveXObject("MSXML2.XMLHTTP.3.0"); } init(); </script> |