1. 程式人生 > >SSM項目中整合WebService

SSM項目中整合WebService

ann patch 建立 cat www. fir front 2.7 url

  先了解一下WebService的一些相關術語吧:

WebService
WebService是一種跨編程語言和跨操作系統平臺的遠程調用技術。

WSDL(web service definition language)
WSDL是webservice定義語言, 對應.wsdl文檔, 一個webservice會對應一個唯一的wsdl文檔, 定義了客戶端與服務端發送請求和響應的數據格式和過程

SOAP(simple object access protocal)
SOAP是"簡單對象訪問協議"
是一種簡單的、基於HTTP和XML的協議, 用於在WEB上交換結構化的數據
soap消息:請求消息和響應消息

SEI(WebService EndPoint Interface)
SEI是web service的終端接口,就是WebService服務器端用來處理請求的接口

CXF(Celtix + XFire)
一個apache的用於開發webservice服務器端和客戶端的框架。


本次采用的就是CXF框架來整合,

首先引入相關的pom包:

<!-- webservice -->
		<dependency>
			<groupId>org.apache.cxf</groupId>
			<artifactId>cxf-rt-frontend-jaxws</artifactId>
			<version>${cxf.version}</version>
		</dependency>
		<dependency>
			<groupId>org.apache.cxf</groupId>
			<artifactId>cxf-rt-transports-http</artifactId>
			<version>${cxf.version}</version>
		</dependency>

  由於版本的沖突,我將spring的版本調了,並且由於cglib包中的asm包和cxf框架中的asm包有沖突,我做了以下更改:

<!-- spring版本號 -->
		<spring.version>4.1.9.RELEASE</spring.version>

  

<dependency>
			<groupId>cglib</groupId>
			<artifactId>cglib</artifactId>
			<version>3.2.5</version>
			<exclusions>
				<exclusion>
					<groupId>org.ow2.asm</groupId>
					<artifactId>asm</artifactId>
				</exclusion>
			</exclusions>
		</dependency>

  2. 接著引入spring-context-webservice.xml和cxf-config.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:cxf="http://cxf.apache.org/core"
       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
        http://cxf.apache.org/core http://cxf.apache.org/schemas/core.xsd">

    <import resource="cxf-config.xml"/>
</beans>

  

<?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"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:jaxrs="http://cxf.apache.org/jaxrs"
	xsi:schemaLocation="http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd
		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/jaxrs
        http://cxf.apache.org/schemas/jaxrs.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" />


<!-- id 不能重復 -->
	<jaxws:endpoint id="servicemanWebService" implementor="clack.webserviceImp.ServicemanWebServiceImp"  address="/servicemanws" /> 

<!-- 	<jaxrs:server id="restContainer" address="/">
		<jaxrs:serviceBeans>
			<ref bean="roomService" />
		</jaxrs:serviceBeans>
		<jaxrs:providers>
			<bean class="org.codehaus.jackson.jaxrs.JacksonJaxbJsonProvider" />
		</jaxrs:providers>
		<jaxrs:extensionMappings>
		<entry key="json" value="application/json" />
		<entry key="xml" value="application/xml" />
		</jaxrs:extensionMappings>
	</jaxrs:server> -->

</beans>

  其中<jaxws:endpoint id="servicemanWebService" implementor="clack.webserviceImp.ServicemanWebServiceImp" address="/servicemanws" />


中的設置後續會用到。



3. 更改相應的web.xml加載順序並加入cxf配置(反正是先加載spring,後加載springmvc)
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xmlns="http://xmlns.jcp.org/xml/ns/javaee" 
    xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" 
    id="WebApp_ID" version="3.1">
    <display-name>Archetype Created Web Application</display-name>
    
    <context-param>
		<param-name>contextConfigLocation</param-name>
		<param-value>classpath:spring-context*.xml</param-value>
	</context-param>
<listener>
		<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
	</listener>
	<listener>
		<listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>
	</listener>
	<!-- ================配置SpringMVC核心調度器================ -->
	<!-- 不指定具體文件的話,默認為"/WEB-INF/<servlet name>-servlet.xml" -->
	<!-- load-on-startup代表啟動順序,設置為大於等於0表示容器在應用啟動時就加載並初始化這個servlet -->
	<!-- 推薦攔截/,風格優雅 -->
	<servlet>
		<servlet-name>SpringMVC</servlet-name>
		<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
		<init-param>
			<param-name>contextConfigLocation</param-name>
			<param-value>classpath*:spring-mvc.xml</param-value>
		</init-param>
		<load-on-startup>1</load-on-startup>
	</servlet>
	<servlet-mapping>
		<servlet-name>SpringMVC</servlet-name>
		<url-pattern>/</url-pattern>
	</servlet-mapping>
	<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>/ws/*</url-pattern>
	</servlet-mapping>
</web-app>

  4. 接著添加一個工具類用於調出springmvc中加載的service註解

package clack.utils;

import java.util.Enumeration;
import javax.servlet.ServletContext;

import org.springframework.web.context.ContextLoader;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;

public class ContextUtils {
	public static WebApplicationContext getSpringMVCContext() {
		WebApplicationContext rootWac = ContextLoader.getCurrentWebApplicationContext();
		// 獲取servletContext
		System.out.println(rootWac+"ddddd");
		ServletContext servletContext = rootWac.getServletContext();
		// 獲取子容器,名字最後對應servlet名字
		//1.查看spring容器中的對象名稱
		String[] beannames = rootWac.getBeanDefinitionNames();
		for(String beanname:beannames){
			System.out.println(beanname);
		}
		
		System.out.println(servletContext);
	
		
		//2.查看servlet中容器列表
		Enumeration<String> servletnames  = servletContext.getAttributeNames();
		while(servletnames.hasMoreElements()){
			System.out.println(servletnames.nextElement());
		}
		
		WebApplicationContext springmvc = WebApplicationContextUtils.getWebApplicationContext(servletContext,
				"org.springframework.web.servlet.FrameworkServlet.CONTEXT.SpringMVC");
		//System.out.println(springmvc+"eee");
		return springmvc;
	}

}

  5. 準備工作就緒後就建立webservice接口和webservice實現類:

package clack.webservice;

import java.util.List;

import javax.jws.WebMethod;
import javax.jws.WebService;

import clack.entity.Serviceman;

@WebService
public interface ServicemanWebService {
	//使用@WebMethod註解標註WebServiceI接口中的方法
    @WebMethod
	List<Serviceman> getAllServiceman() throws Exception;
}

  其中使用的 getAllServiceman()方法是本身的service中的方法調用。

package clack.webserviceImp;

import java.util.List;

import javax.jws.WebService;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import clack.entity.Serviceman;
import clack.service.ServicemanService;
import clack.utils.ContextUtils;
import clack.webservice.ServicemanWebService;
//endpointInterface 編寫實現接口類名 service name 網絡訪問的名字 對應<wsdl:service name="studentws">
@Component("servicemanWebService")
@WebService(endpointInterface = "clack.webservice.ServicemanWebService", serviceName = "servicemanws")
public class ServicemanWebServiceImp implements ServicemanWebService{
	@Autowired
	private ServicemanService servicemanService;
	
	
	public ServicemanService getServicemanService() {
		return servicemanService;
	}


	public void setServicemanService(ServicemanService servicemanService) {
		this.servicemanService = servicemanService;
	}


	@Override
	public List<Serviceman> getAllServiceman() throws Exception {
		// TODO Auto-generated method stub
		servicemanService = (ServicemanService)ContextUtils.getSpringMVCContext().getBean("servicemanService");
		List<Serviceman> servicemans = servicemanService.getAllServiceman();
		return servicemans;
	}

}

  理清其中註解的對應關系後問題不大,

啟動項目,輸入地址:http://localhost:8080/StudyMaven1/ws/servicemanws?wsdl

技術分享圖片


測試:

建立一個簡單的maven項目並導入相關的cxf包:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>clack</groupId>
  <artifactId>MyWebService</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  
  <properties>
		<cxf.version>2.2.3</cxf.version>
	</properties>

	<dependencies>
		<!-- webservice -->
		<dependency>
			<groupId>org.apache.cxf</groupId>
			<artifactId>cxf-rt-frontend-jaxws</artifactId>
			<version>${cxf.version}</version>
		</dependency>
		<dependency>
			<groupId>org.apache.cxf</groupId>
			<artifactId>cxf-rt-transports-http</artifactId>
			<version>${cxf.version}</version>
		</dependency>



	</dependencies>
	<build>
		<defaultGoal>compile</defaultGoal>
		<finalName>MyWebService</finalName>
		<plugins>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-compiler-plugin</artifactId>
				<version>3.1</version>
				<configuration>
					<source>1.8</source>
					<target>1.8</target>
					<encoding>utf-8</encoding>
				</configuration>
			</plugin>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-resources-plugin</artifactId>
				<version>2.6</version>
				<configuration>


					<failOnMissingWebXml>false</failOnMissingWebXml>

				</configuration>
			</plugin>
		</plugins>
		<resources>
			<!--編譯之後包含xml -->
			<resource>
				<directory>src/main/java</directory>
				<includes>
					<include>**/*.xml</include>
				</includes>
			</resource>
			<resource>
				<directory>src/main/resources</directory>
				<includes>
					<include>**/*</include>
				</includes>
			</resource>

		</resources>
	</build>
</project>

 2. 使用了一個插件生成相關的文件 apache-cxf-3.2.7

3. 將所得的文件拷入maven項目中,並新建一個測試類測試是否能取得數據:

目錄樹如下:

技術分享圖片

其中WebServiceApp是測試類:

package clack.webserviceimp;

import java.net.URL;
import java.util.List;

import javax.xml.namespace.QName;
import javax.xml.ws.Service;

import org.apache.cxf.endpoint.Client;
import org.apache.cxf.jaxws.endpoint.dynamic.JaxWsDynamicClientFactory;

import clack.webservice.Serviceman;
import clack.webservice.ServicemanWebService;

/**
 * 通過客戶端編程的方式調用Webservice服務
 *
 */
public class WebServiceApp {

	//1. 自定義方法
	public void mysoap() throws Exception {

		// CXF動態客戶端工廠
		JaxWsDynamicClientFactory dcf = JaxWsDynamicClientFactory.newInstance();

		// WSDL文檔url配置()
		String wsdlUrl = "http://localhost:8080/StudyMaven1/ws/servicemanws?wsdl";

		Object[] objects = null;
		try {
			// 獲取CXF客戶端
			Client client = dcf.createClient(wsdlUrl);
			// 調用Web Service方法
			objects = client.invoke("add", 1, 2);
		} catch (Exception e) {
			e.printStackTrace();
		}

		// 獲取調用結果
		System.out.println("調用結果:" + objects[0]);

		System.out.println("=========>");
		try {
			// 獲取CXF客戶端
			Client client = dcf.createClient(wsdlUrl);
			// 調用Web Service方法
			objects = client.invoke("sayHello", "World!");
		} catch (Exception e) {
			e.printStackTrace();
		}

		// 獲取調用結果
		System.out.println("調用結果:" + objects[0]);
	}
	//第二種 client工具生成輔助類 需使用apche cxf工具  
	//步驟 cmd wsdl2java   -encoding  utf8 http://localhost:8080/StudyMavenSSM/ws/studentws?wsdl
	//
	public void clientsoap() throws Exception{
		// 創建WSDL的URL,註意不是服務地址
				URL url = new URL("http://localhost:8080/StudyMaven1/ws/servicemanws?wsdl");

				// 創建服務名稱
				// 1.namespaceURI - 命名空間地址 (wsdl文檔中的targetNamespace
				// targetNamespace="http://webserviceImp.gxa/")
				// 2.localPart - 服務視圖名 (wsdl文檔中服務名稱,例如<wsdl:service name="studentws">)
				QName qname = new QName("http://webserviceImp.clack/", "servicemanws");

				// 創建服務視圖
				// 參數解釋:
				// 1.wsdlDocumentLocation - wsdl地址
				// 2.serviceName - 服務名稱
				Service service = Service.create(url, qname);
				// 獲取服務實現類
				// 參數解釋:serviceEndpointInterface - 服務端口(wsdl文檔中服務端口的name屬性,例如<wsdl:port
				// binding="tns:studentwsSoapBinding" name="StudentWebServiceImpPort">)
				ServicemanWebService studentWebService =
				service.getPort(ServicemanWebService.class);
				 //調用查詢方法
				 List<Serviceman> students = studentWebService.getAllServiceman();
				 for(Serviceman serviceman:students){
					 System.out.println(serviceman.getSname());
				 }
	}

	public static void main(String[] args) throws Exception {
		new WebServiceApp().clientsoap();
	}

}

  4. 最後運行如下,成功調用:

技術分享圖片

至此,一個簡單的webservice就整合進去了,但是,其中還有很多細節無法言說,學而無涯。

SSM項目中整合WebService