?? W3C組織對其的定義如下,它是一個軟件系統(tǒng),為了支持跨網(wǎng)絡(luò)的機(jī)器間相互操作交互而設(shè)計(jì)。Web Service服務(wù)通常被定義為一組模塊化的API,它們可以通過網(wǎng)絡(luò)進(jìn)行調(diào)用,來執(zhí)行遠(yuǎn)程系統(tǒng)的請求服務(wù)。 ?? 簡單的說:WebService即Web服務(wù),它是一種跨編程語言和跨操作系統(tǒng)平臺的遠(yuǎn)程調(diào)用技術(shù),是接口技術(shù)的一種。
Web服務(wù):基于HTTP和xml的技術(shù),HTTP是互聯(lián)網(wǎng)上應(yīng)用最為廣泛的一種網(wǎng)絡(luò)協(xié)議,而XML是跨平臺的基礎(chǔ)。跨編程語言和跨操作平臺:假設(shè)服務(wù)端程序采用java編寫,客戶端程序則可以采用其他編程語言編寫,反之亦然!跨操作系統(tǒng)平臺則是指服務(wù)端程序和客戶端程序可以在不同的操作系統(tǒng)上運(yùn)行。遠(yuǎn)程調(diào)用:就是一臺計(jì)算機(jī)a上的一個程序可以調(diào)用到另外一臺計(jì)算機(jī)b上的一個對象的方法,譬如,銀聯(lián)提供給商場的pos刷卡系統(tǒng),商場的POS機(jī)轉(zhuǎn)賬調(diào)用的轉(zhuǎn)賬方法的代碼其實(shí)是跑在銀行服務(wù)器上。再比如,amazon,天氣預(yù)報(bào)系統(tǒng),淘寶網(wǎng),校內(nèi)網(wǎng),百度等把自己的系統(tǒng)服務(wù)以webservice服務(wù)的形式暴露出來,讓第三方網(wǎng)站和程序可以調(diào)用這些服務(wù)功能。?? 很多個系統(tǒng),進(jìn)行分布的部署,分布的系統(tǒng)數(shù)據(jù)通信 解決技術(shù)就是WebService。
WebService開發(fā)可以分為服務(wù)器端開發(fā)和客戶端開發(fā)兩個方面: - 服務(wù)端(服務(wù)提供者)開發(fā):把公司內(nèi)部系統(tǒng)的業(yè)務(wù)方法發(fā)布成WebService服務(wù),供遠(yuǎn)程合作單位和個人調(diào)用。 - 客戶端(服務(wù)請求者)開發(fā):調(diào)用別人發(fā)布的WebService服務(wù),大多數(shù)人從事的開發(fā)都屬于這個方面,例如,調(diào)用天氣預(yù)報(bào)WebService服務(wù)。
簡單的說就是API規(guī)范,可以進(jìn)行不同系統(tǒng)間交互。 可插拔:對于軟件來說,是一個接耦合的思想。
Web Service也分為兩大類: - 一類是基于Soap協(xié)議的WebService。 - 一類是基于REST風(fēng)格的Web Service。
JAX-WS(Java API for XML Web Services)規(guī)范是一組XML web services的JAVA API。 現(xiàn)行的最新的規(guī)范版本為JAX-WS2.0 (JSR 224)。 JAX-WS主要是支持和實(shí)現(xiàn)Soap方式的WebService。
?? SOAP方式的WebService最早由微軟提出和實(shí)現(xiàn),是W3C的標(biāo)準(zhǔn)之一。在跨系統(tǒng)和跨平臺的系統(tǒng)通信中,其以平臺無關(guān)性,獲得了廣泛的應(yīng)用,他為整個企業(yè)甚至多個組織之間的業(yè)務(wù)流程的集成提供了一個通用機(jī)制。 ?? 它使用開放的XML(標(biāo)準(zhǔn)通用標(biāo)記語言下的一個子集)標(biāo)準(zhǔn)來描述、發(fā)布、發(fā)現(xiàn)、協(xié)調(diào)和配置這些應(yīng)用程序,用于開發(fā)分布式的互操作的應(yīng)用程序。XML是該技術(shù)跨平臺的基礎(chǔ)。由于XML與平臺、編程語言無關(guān),因此,誰都能讀寫。
?? CXF封裝了JAX-WS。jax-ws是sun公司規(guī)范,但也給了實(shí)現(xiàn),因此也可以直接使用JAX-WS開發(fā)WebService程序,但一般實(shí)際開發(fā)不用。 ?? CXF 大大簡化了 Services 的創(chuàng)建,同時它繼承了 XFire 傳統(tǒng),一樣可以天然地和 SPRing 進(jìn)行無縫集成。 ?? Apache CXF = Celtix + XFire,Apache CXF 的前身叫 Apache CeltiXfire,現(xiàn)在已經(jīng)正式更名為 Apache CXF 了,以下簡稱為 CXF。CXF 繼承了 Celtix 和 XFire 兩大開源項(xiàng)目的精華,提供了對 JAX-WS 全面的支持。 ?? CXF WebService 開發(fā),主要分為兩種服務(wù)提供方式 JAX-WS 、JAX-RS 。 - JAX-WS 傳輸數(shù)據(jù),就是XML格式,基于SOAP協(xié)議 。 - JAX-RS 傳輸數(shù)據(jù),傳輸XML格式或者JSON格式,基于HTTP協(xié)議 。
網(wǎng)址:http://cxf.apache.org
先解壓到一個目錄(不能有中文、特殊字符)配置環(huán)境變量 CXF_HOME=D:/DevIDE/Java/apache-cxf-2.6.15 path=%CXF_HOME%/bin;測試是否安裝成功 命令:wsdl2java -v官方案例:
<!--使用maven導(dǎo)入jar包--> <properties> <cxf.version>${project.version}</cxf.version> </properties> <dependencies> <!-- jax-ws前端控制模塊(處理發(fā)過來的服務(wù)業(yè)務(wù)) --> <dependency> <groupId>org.apache.cxf</groupId> <artifactId>cxf-rt-frontend-jaxws</artifactId> <version>3.1.9</version> </dependency> <!-- cxf的數(shù)據(jù)傳輸模塊 --> <dependency> <groupId>org.apache.cxf</groupId> <artifactId>cxf-rt-transports-http</artifactId> <version>3.1.9</version> </dependency> <!-- Jetty is needed if you're using the CXFServlet --> <!-- 用來啟動一個http服務(wù)用的(Jetty-tomcat)jetty,是cxf默認(rèn)使用的http服務(wù)的容器 切記:如果你web運(yùn)行使用是tomcat容器的話,那么你必須不能引入下面的jar --> <dependency> <groupId>org.apache.cxf</groupId> <artifactId>cxf-rt-transports-http-jetty</artifactId> <version>3.1.9</version> </dependency> <!-- 引入日志slf4j(自己引入,官方未提供) --> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> <version>${slf4j.version}</version> </dependency> </dependencies>添加log4j的核心配置文件。
開發(fā):三大步 第一步:編寫SEI SEI:jax-ws規(guī)范中,Service EndPoint InterFace服務(wù)端點(diǎn)接口 對于java的api來說,就是一組接口和實(shí)現(xiàn)類 接口里面的方法就是要暴露(expose)出去給客戶端調(diào)用的
//SEI接口 public interface HelloWorld { String sayHi(@WebParam(name = "text") String text); } //SEI實(shí)現(xiàn) public class HelloWorldImpl implements HelloWorld { public String sayHi(String text) { return "Hello " + text; } }第二步:在SEI的接口類上添加注解 可能找不到該注解,原因:該注解是jdk6版本的規(guī)范中,低于該版本的jdk沒有。
@WebService public interface HelloWorld { String sayHi(@WebParam(name = "text") String text); }第三步:發(fā)布服務(wù)
public class Server { protected Server() throws Exception { System.out.println("Starting Server"); HelloWorldImpl implementor = new HelloWorldImpl(); //new實(shí)現(xiàn)類 JaxWsServerFactoryBean svrFactory = new JaxWsServerFactoryBean(); //1.服務(wù)端工廠類 //2.設(shè)置了三個屬性 //2.1設(shè)置SEI接口class svrFactory.setServiceClass(HelloWorld.class); //2.2服務(wù)地址(給客戶端調(diào)用):協(xié)議+ip+端口+項(xiàng)目名字(服務(wù)名字) svrFactory.setAddress("http://localhost:9000/helloWorld"); //2.3設(shè)置SEI的一個實(shí)現(xiàn)者(對象) svrFactory.setServiceBean(implementor); //添加輸入日志 svrFactory.getInInterceptors().add(new LoggingInInterceptor()); //添加輸出日志 svrFactory.getOutInterceptors().add(new LoggingOutInterceptor()); //3.創(chuàng)建并發(fā)布服務(wù) //底層,默認(rèn)會發(fā)起一個http服務(wù),默認(rèn)使用jetty svrFactory.create(); } public static void main(String args[]) throws Exception { new Server(); System.out.println("Server ready..."); Thread.sleep(5 * 60 * 1000); System.out.println("Server exiting"); System.exit(0); } }測試是否服務(wù)發(fā)布成功(通過訪問wsdl):127.0.0.1:8888/helloWorld(服務(wù)名)?wsdl 如果用火狐訪問,頭部信息隱藏。其他瀏覽器沒有問題。 http://127.0.0.1:8888/helloWorld :真正的webservice服務(wù) http://127.0.0.1:8888/helloWorld?wsdl :wsdl文檔,客戶端和服務(wù)端直接的橋梁
jetty就是一個應(yīng)用服務(wù)器,和tomcat作用差不多。但它更輕量級。可以用于內(nèi)嵌的web服務(wù)、可以方便測試。
cxf開發(fā)的時候,sei上面的注解都寫在接口上。 wsdl文檔的生成更依賴于接口,和實(shí)現(xiàn)類關(guān)系不大,好處是解耦合,更加面向?qū)ο蟆?/p>
官方案例:
public final class Client { private Client() { } public static void main(String args[]) throws Exception { //1.代理樁工廠 JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean(); //添加輸入日志 factory.getInInterceptors().add(new LoggingInInterceptor()); //添加輸出日子 factory.getOutInterceptors().add(new LoggingOutInterceptor()); //2.設(shè)置WebService地址 factory.setAddress("http://localhost:9000/helloWorld"); //3.根據(jù)工廠創(chuàng)建本地代理對象(樁對象) HelloWorld client = factory.create(HelloWorld.class); System.out.println(client.sayHi("World")); } }生成樁(stub)、本地代理(proxy)接口類—wsdl2java -p :指定其wsdl的命名空間,要生成代碼的包名 -d :指定要產(chǎn)生代碼的目錄
wsdl2java -d . p cn.demo.hw.client.stub http:127.0.0.1:9000/helloWorld?wsdl?? 攔截器:增強(qiáng)功能!CXF攔截器:增強(qiáng)擴(kuò)展CXF的! ?? 日志攔截器的作用:它是cxf攔截器的一種,查看日志(soap相關(guān))。可以解決:相互調(diào)用的日志、發(fā)送或接收的報(bào)文、請求的次數(shù)等。日志攔截器中的ID,是攔截的編號,作用是為了標(biāo)識請求的次數(shù)以及請求和響應(yīng)對應(yīng)的編號。
輸入攔截器,InInterceptors:在方法進(jìn)入前執(zhí)行。輸出攔截器,OutInterceptors:在方法進(jìn)入后執(zhí)行。?? CXF已經(jīng)實(shí)現(xiàn)了很多種攔截器,如果要自定義攔截器,則需要實(shí)現(xiàn)PhaseInterceptor接口(超級接口Interceptor),不過一般都是繼承自AbstractPhaseInterceptor< T extends org.apache.cxf.message.Message >類,這個類可以指定繼承它的攔截器在什么階段被啟用,階段屬性可以通過org.apache.cxf.phase.Phase 中的常量指定值。

只要使用了注解,那么服務(wù)端的代碼怎么改其實(shí)都對wsdl或客戶端沒有影響。 好處:屏蔽了服務(wù)端的代碼的具體內(nèi)容。
類上面的注解 
方法上面的注解 
SEI的方法,必須是公有,非靜態(tài)。 當(dāng)wsdl發(fā)生變化后,客戶端的樁的代碼也需要重新生成。
服務(wù)端的整合方式: 發(fā)揮spring的粘合劑的作用,將對象創(chuàng)建的權(quán)利和管理都交給spring。(IoC思想) 可以將webservice的服務(wù)和普通的web服務(wù)放在一起啟動。換句話說,我們要使用tomcat來啟動ws服務(wù)。不再使用main方法。 整體:web容器tomcat—》加載spring容器—-》初始化webservice服務(wù)。
參考官方demo :java_first_spring_support
引入jdbc工具類
//dao接口 public interface MobileAddressDAO { /** * 根據(jù)手機(jī)號碼獲取歸屬地 * @param mobileNo * @return */ public String getAddressByMobileNo(String mobileNo); } //dao實(shí)現(xiàn) //jdbc public class MobileAddressDAOImpl implements MobileAddressDAO{ @Override public String getAddressByMobileNo(String mobileNo) { Connection conn=null; PreparedStatement pstmt=null; ResultSet rs=null; try { //獲取連接 conn = JDBCUtils.getConnection(); //獲取pstmt pstmt = conn.prepareStatement("select * from t_mobileaddress where mobileNo=?"); //設(shè)置參數(shù) pstmt.setString(1, mobileNo); //執(zhí)行查詢,獲取rs rs = pstmt.executeQuery(); //獲取歸屬地信息 String address=null; if(rs.next()){ address = rs.getString("address"); } return address; } catch (Exception e) { e.printStackTrace(); throw new RuntimeException("服務(wù)端查詢手機(jī)號歸屬地業(yè)務(wù)失敗",e); }finally { JDBCUtils.release(conn, pstmt, rs); } } }web容器啟動的時候自動加載、初始化cxf的服務(wù)。
<!-- spring配置文件位置 --> <context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:applicationContext.xml</param-value> </context-param> <!-- spring核心監(jiān)聽器 --> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <!-- 配置cxf的前端控制器 分發(fā)服務(wù)請求 --> <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>/services/*</url-pattern> </servlet-mapping>測試: 訪問地址:Web容器的地址+servletmap地址+服務(wù)地址
目標(biāo):客戶端獲取樁(本地代理—spring自動提供)對象就ok 如果和spring整合后,直接從spring容器中獲取就可以了。(原理:cxf整合進(jìn)了spring了)
引入jar和服務(wù)端一樣 pom.xml:
<properties> <!-- 全局編碼設(shè)置為u8 --> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <spring.version>3.2.12.RELEASE</spring.version> <cxf.version>3.1.9</cxf.version> <slf4j.version>1.7.21</slf4j.version> <junit.version>4.11</junit.version> <servlet.version>2.5</servlet.version> <jsp.version>2.0</jsp.version> </properties> <dependencies> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-web</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-test</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> <version>${slf4j.version}</version> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>${junit.version}</version> <scope>test</scope> </dependency> <!-- jax-ws前端控制模塊(處理發(fā)過來的服務(wù)業(yè)務(wù)) --> <dependency> <groupId>org.apache.cxf</groupId> <artifactId>cxf-rt-frontend-jaxws</artifactId> <version>${cxf.version}</version> </dependency> <!-- cxf的數(shù)據(jù)傳輸模塊 --> <dependency> <groupId>org.apache.cxf</groupId> <artifactId>cxf-rt-transports-http</artifactId> <version>${cxf.version}</version> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>servlet-api</artifactId> <version>${servlet.version}</version> <scope>provided</scope> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>jsp-api</artifactId> <version>${jsp.version}</version> <scope>provided</scope> </dependency> </dependencies> <build> <plugins> <!-- 編譯的jdk版本 --> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.1</version> <configuration> <source>1.7</source> <target>1.7</target> </configuration> </plugin> <!-- tomcat插件:內(nèi)置默認(rèn):運(yùn)行:tomcat:run --> <plugin> <groupId>org.codehaus.mojo</groupId> <artifactId>tomcat-maven-plugin</artifactId> <version>1.1</version> <configuration> <port>9999</port> </configuration> </plugin> </plugins> </build>略
esdl2java命令生成樁。
public interface MobileService { public String getAddressByMobileNo(String mobileNo); } public class MobileServiceImpl implements MobileService{ //直接注入樁(本地代理對象) private MobileAddressService mobileAddressService; public void setMobileAddressService(MobileAddressService mobileAddressService) { this.mobileAddressService = mobileAddressService; } @Override //遠(yuǎn)程調(diào)用 public String getAddressByMobileNo(String mobileNo) { return mobileAddressService.getAddressByMobileNo(mobileNo); } }新聞熱點(diǎn)
疑難解答