1.引言
WebService顾名思义就是web服务,web服务主要有两种,一种是基于soap类型的服务,一种是基于rest类型的服务,其中soap类型的服务有两种版本,一种是soap1.1版本,一种是soap1.2版本,soap服务类型的数据是xml数据格式的,而rest服务的数据类型是json格式的。
2.什么是WSDL?
wsdl(网络服务描述语言)是Web Service的描述语言,也就是说wsdl文件是soap的使用说明书。在学习soap之前,认识WSDL是非常有必要的,只有能看懂WSDL文件,我们才可以去调用soap类型的Web服务,下面是一个非常简单的wsdl文件。
3.在WSDL文件中我们可以获得什么信息?
- soap服务的名称
- soap服务的地址
- soap服务暴露的方法
- soap服务方法的参数
- soap服务方法参数的类型和相应的返回值执行
4.利用Java发布soap服务
接下来我们利用Java发布一个soap类型的服务,在Java JDK1.6版本以后,我们可以通过Endpoint
来发布一个soap服务,代码如下:
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 package com.skd.service; 2 3 import javax.jws.WebMethod; 4 import javax.jws.WebParam; 5 import javax.jws.WebResult; 6 import javax.jws.WebService; 7 import javax.xml.ws.Endpoint; 8 9 //必须要加注释 10 @WebService 11 public class Hello { 12 public String sayHello(String name){ 13 return "hello " + name; 14 } 15 public static void main(String[] args) { 16 //服务的地址 17 String address = "http://localhost:8080/hello"; 18 Hello implementor = new Hello(); 19 //发布服务,第一个参数是服务的地址,第二个参数是发布出去服务的方法 20 Endpoint.publish(address, implementor); 21 } 22 }
5.利用JDK注释控制WSDL文件
代码如下:
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 package com.skd.service; 2 3 import javax.jws.WebMethod; 4 import javax.jws.WebParam; 5 import javax.jws.WebResult; 6 import javax.jws.WebService; 7 import javax.xml.ws.Endpoint; 8 9 10 @WebService(targetNamespace="http://com.wpx",serviceName="WPXService") 11 public class Hello { 12 //提供一个合法的web方法 13 @WebMethod(operationName="myMethod") 14 @WebResult(name="myRet") 15 public String sayHello( 16 @WebParam(name="name") 17 String name){ 18 return "hello " + name; 19 } 20 //排除当前方法 21 @WebMethod(exclude=true) 22 public String sayHi(String name){ 23 return "hi " + name; 24 } 25 public static void main(String[] args) { 26 String address = "http://localhost:8080/hello";//服务的发布地址 27 Hello implementor = new Hello();//提供服务的实例 28 Endpoint.publish(address, implementor);//发布服务 29 } 30 }
6.1利用wsimport进行soap服务进行调用
wsimport原理是根据wsdl文件生成本地代理。
- 首先我们使用wsimport命令生成java文件(需要安装JDK)
1 wsimport -s ./ http://localhost:8080/hello?wsdl 2 //如果指定输出的包名代码为: 3 wsimport -s ./ -p com.skd.client.wsimport http://localhost:8080/hello?wsdl 4 //打jar包的命令:(将当前的com文件夹打成ws.jar) 5 jar cvf ws.jar ./com
- 创建一个方法,调用Web服务,代码如下
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 import wpx.com.Hello; 2 import wpx.com.WPXService; 3 4 public class APP { 5 public static void main(String[] args) { 6 WPXService service=new WPXService(); 7 Hello h=service.getHelloPort(); 8 String result=h.myMethod("wpx"); 9 System.out.println(result); 10 } 11 12 }
总结:wsimport调用web服务的java代码是有规律的,总共分为三步:
- 创建服务名对象
- 通过服务名获得接口对象(一般是getXXX,其中XXX代表服务名的port属性)
- 通过接口对象调用服务方法
6.2通过UrlConnection访问Soap服务
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 import java.io.InputStream; 2 import java.io.OutputStream; 3 import java.net.HttpURLConnection; 4 import java.net.URL; 5 6 /** 7 * 使用UrlConnection方式调用WebService服务 8 * 9 */ 10 public class APP { 11 public static void main(String[] args) throws Exception { 12 // WebService服务的地址 13 URL url = new URL("http://localhost:8080/hello"); 14 HttpURLConnection conn = (HttpURLConnection) url.openConnection(); 15 //是否具有输入参数 16 conn.setDoInput(true); 17 //是否输出输入参数 18 conn.setDoOutput(true); 19 //发POST请求 20 conn.setRequestMethod("POST"); 21 //设置请求头(注意一定是xml格式) 22 conn.setRequestProperty("content-type", "text/xml;charset=utf-8"); 23 24 // 构造请求体,符合SOAP规范(最重要的) 25 String requestBody = "<soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:q0=\"http://com.wpx\" " 26 + "xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">" 27 + "<soapenv:Body>" 28 + "<q0:myMethod>" 29 + "<name>wpx</name>" 30 + "</q0:myMethod>" 31 + "</soapenv:Body>" 32 + "</soapenv:Envelope>"; 33 34 //获得一个输出流 35 OutputStream out = conn.getOutputStream(); 36 out.write(requestBody.getBytes()); 37 38 //获得服务端响应状态码 39 int code = conn.getResponseCode(); 40 StringBuffer sb = new StringBuffer(); 41 if(code == 200){ 42 //获得一个输入流,读取服务端响应的数据 43 InputStream is = conn.getInputStream(); 44 byte[] b = new byte[1024]; 45 int len = 0; 46 47 while((len = is.read(b)) != -1){ 48 String s = new String(b,0,len,"utf-8"); 49 sb.append(s); 50 } 51 is.close(); 52 } 53 54 out.close(); 55 System.out.println("服务端响应数据为:"+sb.toString()); 56 57 } 58 }
6.3利用JDK的Service方法
在前两种方法中,第一种方案生成的代码非常多,第二种方案服务器返回的数据需要我们来解析,都不是非常的完美,我们可以使用第三种方法,生成的代码不是非常的多,对于服务器返回的数据也不需要我们自己来解析,过程如下。
- 首先我们使用wsimport生成本地代码(但是我们只把接口文件拷贝到我们项目中来)
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 import java.net.MalformedURLException; 2 import java.net.URL; 3 4 import javax.xml.namespace.QName; 5 import javax.xml.ws.Service; 6 public class APP { 7 public static void main(String[] args) throws Exception { 8 String wsdlUrl = "http://localhost:8080/hello?wsdl"; 9 //QName,第一个参数是服务的命名空间,第二个参数是服务的名称 10 Service service = Service.create(new URL(wsdlUrl), new QName("http://com.wpx", "WPXService")); 11 //QName,第一个参数是服务的命名空间,第二个参数是得到接口的Port 12 Hello port = service.getPort(new QName("http://com.wpx","HelloPort"), Hello.class); 13 String ret = port.myMethod("wpx"); 14 System.out.println(ret); 15 } 16 }
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 QName qname = new QName("http://...", 2 "Service"); 3 Service service = new Service(Url,qname); 4 ServiceSoap sop =service.getServiceSoap(); 5 String res = sop.docUpload(bs, clntnum+"_"+strformat.format(date)+"_"+i + ".jpg"); 6 res = res.replace("\\", "/");
注:QName
api:https://www.oschina.net/uploads/doc/flex-doc-3.2/QName.html
1.来历:qname是qualified name 的简写
2.构成:由名字空间(namespace)前缀(prefix)以及冒号(:),还有一个元素名称构成
3.举例:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns="http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"
version="1.0">
<xsl:template match="foo">
<hr/>
</xsl:template>
</xsl:stylesheet>
xsl是名字空间前缀,template是元素名称,xsl:template 就是一个qname
4.总结:qname无非是有着特定格式的xml元素,其作用主要是增加了名字空间,比如有同样的元素名称,而名字空间不同的情况。
7.CXF发布服务
7.1 CXF发布SOAP类型的服务-无接口(http://localhost:8080/hello)
- 首先引用cxf的jar包
- 利用CXF发布没有接口的SOAP服务
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 package com.skd.service; 2 3 import javax.jws.WebService; 4 5 @WebService 6 public class Hello { 7 public String sayHello(String name){ 8 System.out.println("sayHi called..."); 9 return " hello " + name; 10 } 11 12 }
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 package com.skd.soap; 2 3 import org.apache.cxf.jaxws.JaxWsServerFactoryBean; 4 import com.skd.service.Hello; 5 6 public class JaxWsBean { 7 8 /** 9 * 使用JaxWsServerFactoryBean发布CXF的WebService服务 10 */ 11 public static void main(String[] args) { 12 //使用JaxWsServerFactoryBean发布服务,需要在类上加入@WebService注解, 13 //如果不加,当前类中的方法都不能被发布为web方法 14 JaxWsServerFactoryBean bean = new JaxWsServerFactoryBean(); 15 //发布服务的地址 16 bean.setAddress("http://localhost:8080/hello"); 17 //因为没有接口,所以 18 bean.setServiceClass(Hello.class); 19 //发布服务的实现类 20 bean.setServiceBean(new Hello()); 21 //发布服务 22 bean.create(); 23 } 24 25 }
7.2 CXF发布SOAP类型的服务-有接口(服务地址:”http://localhost:8080/hello“)
接口:
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 package com.skd.service; 2 @WebService 3 public interface IHi { 4 public String sayHi(String name); 5 }
实现类:
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 package com.skd.service; 2 3 public class HiImpl implements IHi { 4 5 @Override 6 public String sayHi(String name) { 7 return name+"Hi"; 8 } 9 10 }
发布服务:
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 package com.skd.soap.impl; 2 3 import org.apache.cxf.jaxws.JaxWsServerFactoryBean; 4 import com.skd.service.Hello; 5 import com.skd.service.HiImpl; 6 import com.skd.service.IHi; 7 8 public class JaxWsBean { 9 10 /** 11 * 使用JaxWsServerFactoryBean发布CXF的WebService服务 12 */ 13 public static void main(String[] args) { 14 //使用JaxWsServerFactoryBean发布服务,需要在类上加入@WebService注解, 15 //如果不加,当前类中的方法都不能被发布为web方法 16 JaxWsServerFactoryBean bean = new JaxWsServerFactoryBean(); 17 //发布服务的地址 18 bean.setAddress("http://localhost:8080/hello"); 19 //接口类型 20 bean.setServiceClass(IHi.class); 21 //接口的实现类 22 bean.setServiceBean(new HiImpl()); 23 //发布服务 24 bean.create(); 25 } 26 27 }
7.3.cxf发布rest服务(服务地址:http://localhost:8080/hello/*)
创建Person类(必须实现Serializable接口)
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 package com.skd.rest.service; 2 3 import java.io.Serializable; 4 5 public class Person implements Serializable{ 6 7 private static final long serialVersionUID = 1L; 8 private String name; 9 private int age; 10 public String getName() { 11 return name; 12 } 13 public void setName(String name) { 14 this.name = name; 15 } 16 public int getAge() { 17 return age; 18 } 19 public void setAge(int age) { 20 this.age = age; 21 } 22 23 24 }
接口:
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 package com.skd.rest.service; 2 3 import java.util.List; 4 5 import javax.ws.rs.GET; 6 import javax.ws.rs.Path; 7 import javax.ws.rs.PathParam; 8 import javax.ws.rs.Produces; 9 import javax.ws.rs.core.MediaType; 10 11 @Produces( { MediaType.APPLICATION_JSON }) 12 public interface IPerson { 13 @GET//当前方法可以通过GET方式访问 14 @Path("hello/{name}")//当前方法的访问路径 15 public Person getPerson(@PathParam("name") String name);//将id获得赋予方法 16 17 }
实现类:
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 package com.skd.rest.service; 2 3 public class PersonImpl implements IPerson { 4 5 @Override 6 public Person getPerson(String name) { 7 Person p=new Person(); 8 p.setName(name); 9 p.setAge(11); 10 return p; 11 } 12 13 14 }
发布服务(注意必须添加序列化类此处用的是JacksonJsonProvider
):
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 package com.skd.rest.server; 2 import java.util.ArrayList; 3 import java.util.List; 4 import org.apache.cxf.jaxrs.JAXRSServerFactoryBean; 5 import org.codehaus.jackson.jaxrs.JacksonJsonProvider; 6 import com.skd.rest.service.PersonImpl; 7 public class JaxWsBean { 8 9 /** 10 * 使用JaxWsServerFactoryBean发布CXF的WebService服务 11 */ 12 public static void main(String[] args) { 13 //注意发布rest服务的类为JAXRSServerFactoryBean 14 JAXRSServerFactoryBean bean = new JAXRSServerFactoryBean(); 15 //发布服务的地址 16 bean.setAddress("http://localhost:8080"); 17 bean.setResourceClasses(PersonImpl.class); 18 List<Object> list=new ArrayList<Object>(); 19 //必须添加,用于序列化person类为json对象 20 list.add(new JacksonJsonProvider()); 21 bean.setProviders(list); 22 //发布服务 23 bean.create(); 24 System.out.println("web服务"); 25 } 26 27 }
8.CXF与Web程序的整合
8.1 POM.xml文件
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 2 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> 3 <modelVersion>4.0.0</modelVersion> 4 <groupId>web</groupId> 5 <artifactId>cxf</artifactId> 6 <packaging>war</packaging> 7 <version>1.0-SNAPSHOT</version> 8 <name>cxf Maven Webapp</name> 9 <url>http://maven.apache.org</url> 10 <properties> 11 <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> 12 <cxf.version>3.1.9</cxf.version> 13 <jackson.version>1.9.13</jackson.version> 14 <spring.version>4.0.5.RELEASE</spring.version> 15 </properties> 16 <dependencies> 17 <!-- Spring --> 18 <dependency> 19 <groupId>org.springframework</groupId> 20 <artifactId>spring-context</artifactId> 21 <version>${spring.version}</version> 22 </dependency> 23 <dependency> 24 <groupId>org.springframework</groupId> 25 <artifactId>spring-web</artifactId> 26 <version>${spring.version}</version> 27 </dependency> 28 <!--cxf所需要的jar包--> 29 <!--cxf-rt-frontend-jaxws 对soap服务的支持--> 30 <dependency> 31 <groupId>org.apache.cxf</groupId> 32 <artifactId>cxf-rt-frontend-jaxws</artifactId> 33 <version>${cxf.version}</version> 34 </dependency> 35 <!--cxf-rt-frontend-jaxrs 对rest服务的支持--> 36 <dependency> 37 <groupId>org.apache.cxf</groupId> 38 <artifactId>cxf-rt-frontend-jaxrs</artifactId> 39 <version>${cxf.version}</version> 40 </dependency> 41 <dependency> 42 <groupId>org.apache.cxf</groupId> 43 <artifactId>cxf-rt-transports-http</artifactId> 44 <version>${cxf.version}</version> 45 </dependency> 46 <dependency> 47 <groupId>org.apache.cxf</groupId> 48 <artifactId>cxf-rt-transports-http-jetty</artifactId> 49 <version>${cxf.version}</version> 50 </dependency> 51 <!-- 用于rest服务序列化对象--> 52 <dependency> 53 <groupId>org.codehaus.jackson</groupId> 54 <artifactId>jackson-jaxrs</artifactId> 55 <version>${jackson.version}</version> 56 </dependency> 57 <!--用于跨域的jar包--> 58 <dependency> 59 <groupId>com.thetransactioncompany</groupId> 60 <artifactId>java-property-utils</artifactId> 61 <version>1.9</version> 62 </dependency> 63 <dependency> 64 <groupId>com.thetransactioncompany</groupId> 65 <artifactId>cors-filter</artifactId> 66 <version>1.7</version> 67 </dependency> 68 <dependency> 69 <groupId>junit</groupId> 70 <artifactId>junit</artifactId> 71 <version>4.9</version> 72 <scope>test</scope> 73 </dependency> 74 </dependencies> 75 <build> 76 <finalName>cxf</finalName> 77 </build> 78 </project>
8.2 web.xml文件
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 <!DOCTYPE web-app PUBLIC 2 "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" 3 "http://java.sun.com/dtd/web-app_2_3.dtd" > 4 5 <web-app> 6 <display-name>Archetype Created Web Application</display-name> 7 <filter> 8 <filter-name>CORS</filter-name> 9 <filter-class>com.thetransactioncompany.cors.CORSFilter</filter-class> 10 <init-param> 11 <param-name>cors.allowOrigin</param-name> 12 <param-value>*</param-value> 13 </init-param> 14 <init-param> 15 <param-name>cors.supportedMethods</param-name> 16 <param-value>GET, POST, HEAD, PUT, DELETE</param-value> 17 </init-param> 18 <init-param> 19 <param-name>cors.supportedHeaders</param-name> 20 <param-value>Accept, Origin, X-Requested-With, Content-Type, Last-Modified</param-value> 21 </init-param> 22 <init-param> 23 <param-name>cors.exposedHeaders</param-name> 24 <param-value>Set-Cookie</param-value> 25 </init-param> 26 <init-param> 27 <param-name>cors.supportsCredentials</param-name> 28 <param-value>true</param-value> 29 </init-param> 30 </filter> 31 <filter-mapping> 32 <filter-name>CORS</filter-name> 33 <!--允许跨域的路径,这里只允许我们发布的Web服务跨域--> 34 <url-pattern>/ws/*</url-pattern> 35 </filter-mapping> 36 <servlet> 37 <servlet-name>cxf</servlet-name> 38 <servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class> 39 <init-param> 40 <param-name>config-location</param-name> 41 <param-value>classpath:cxf.xml</param-value> 42 </init-param> 43 </servlet> 44 <!--web服务的地址--> 45 <servlet-mapping> 46 <servlet-name>cxf</servlet-name> 47 <url-pattern>/ws/*</url-pattern> 48 </servlet-mapping> 49 50 51 </web-app>
8.3 SOAP服务的接口,类,实体类
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 //实体类 2 public class User { 3 private String username; 4 private String password; 5 6 public String getUsername() { 7 return username; 8 } 9 10 public void setUsername(String username) { 11 this.username = username; 12 } 13 14 public String getPassword() { 15 return password; 16 } 17 18 public void setPassword(String password) { 19 this.password = password; 20 } 21 } 22 23 //接口 24 @WebService 25 public interface UserService { 26 public User getUser(String name); 27 } 28 29 //接口实现类 30 public class UserServiceImpl implements UserService{ 31 public User getUser(String name) { 32 User u=new User(); 33 u.setUsername(name); 34 u.setPassword("123456"); 35 return u; 36 } 37 }
8.4 rest服务的实体类,接口,接口的实现类
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 //实体类(注意要实现接口Serializable) 2 public class Person implements Serializable{ 3 private String name; 4 private int age; 5 public String getName() { 6 return name; 7 } 8 public void setName(String name) { 9 this.name = name; 10 } 11 public int getAge() { 12 return age; 13 } 14 public void setAge(int age) { 15 this.age = age; 16 } 17 } 18 19 //接口 20 @Produces( {MediaType.APPLICATION_JSON }) 21 public interface PersonService { 22 @GET 23 @Path("/person/{name}") 24 public Person getPerson(@PathParam("name") String name); 25 @GET 26 @Path("/persons") 27 public List<Person> getPersons(); 28 } 29 30 //实现类 31 public class PersonServiceImpl implements PersonService{ 32 public Person getPerson(String name) { 33 Person p=new Person(); 34 p.setName(name); 35 p.setAge(100); 36 return p; 37 } 38 39 public List<Person> getPersons() { 40 List<Person> persons=new ArrayList<Person>(); 41 Person p1=new Person(); 42 p1.setName("wpx"); 43 p1.setAge(100); 44 persons.add(p1); 45 Person p2=new Person(); 46 p2.setName("zlr"); 47 p2.setAge(100); 48 persons.add(p2); 49 return persons; 50 } 51 }
8.5 CXF的配置文件(cxf.xml)
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 <?xml version="1.0" encoding="UTF-8"?> 2 <beans xmlns="http://www.springframework.org/schema/beans" 3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:jaxws="http://cxf.apache.org/jaxws" 4 xmlns:soap="http://cxf.apache.org/bindings/soap" xmlns:jaxrs="http://cxf.apache.org/jaxrs" 5 xsi:schemaLocation="http://www.springframework.org/schema/beans 6 http://www.springframework.org/schema/beans/spring-beans.xsd 7 http://cxf.apache.org/bindings/soap 8 http://cxf.apache.org/schemas/configuration/soap.xsd 9 http://cxf.apache.org/jaxws 10 http://cxf.apache.org/schemas/jaxws.xsd 11 http://cxf.apache.org/jaxrs 12 http://cxf.apache.org/schemas/jaxrs.xsd 13 "> 14 <!-- 15 id:当前服务的唯一标识 address:当前服务对应的请求url serviceClass:接口类型 16 --> 17 <jaxws:server id="soapuser" address="/user" 18 serviceClass="com.skd.service.UserService"> 19 <jaxws:serviceBean> 20 <bean class="com.skd.service.impl.UserServiceImpl" /> 21 </jaxws:serviceBean> 22 <jaxws:inInterceptors> 23 <bean class="org.apache.cxf.interceptor.LoggingInInterceptor"></bean> 24 </jaxws:inInterceptors> 25 </jaxws:server> 26 <!-- 发布一个Restful方式的WebService服务 --> 27 <bean id="personServiceImpl" class="com.skd.service.impl.PersonServiceImpl"></bean> 28 <jaxrs:server id="personService" address="/p"> 29 <jaxrs:serviceBeans> 30 <ref bean="personServiceImpl" /> 31 </jaxrs:serviceBeans> 32 <!--提供序列化为json数据的实现类--> 33 <jaxrs:providers> 34 <bean class="org.codehaus.jackson.jaxrs.JacksonJsonProvider"></bean> 35 </jaxrs:providers> 36 <jaxrs:inInterceptors> 37 <bean class="org.apache.cxf.interceptor.LoggingInInterceptor"></bean> 38 </jaxrs:inInterceptors> 39 <jaxrs:outInterceptors> 40 <bean class="org.apache.cxf.interceptor.LoggingOutInterceptor"></bean> 41 </jaxrs:outInterceptors> 42 </jaxrs:server> 43 </beans>
9.CXF与spring的整合
所实现的功能有:
- 将Person,PersonService,PersonServiceImpl发布为Rest类型的服务
- 将User ,UserService,UserServiceImpl发布为Soap类型的服务
- 允许我们的Web服务可以跨域请求
9.1POM.xml文件
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 2 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> 3 <modelVersion>4.0.0</modelVersion> 4 <groupId>spring</groupId> 5 <artifactId>cxf</artifactId> 6 <packaging>war</packaging> 7 <version>1.0-SNAPSHOT</version> 8 <name>cxf Maven Webapp</name> 9 <url>http://maven.apache.org</url> 10 <properties> 11 <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> 12 <cxf.version>3.1.9</cxf.version> 13 <jackson.version>1.9.13</jackson.version> 14 <spring.version>4.1.9.RELEASE</spring.version> 15 </properties> 16 <dependencies> 17 <!-- Spring --> 18 <dependency> 19 <groupId>org.springframework</groupId> 20 <artifactId>spring-context</artifactId> 21 <version>${spring.version}</version> 22 </dependency> 23 <dependency> 24 <groupId>org.springframework</groupId> 25 <artifactId>spring-web</artifactId> 26 <version>${spring.version}</version> 27 </dependency> 28 <!-- CXF --> 29 <!--cxf-rt-frontend-jaxws支持soap类型服务--> 30 <dependency> 31 <groupId>org.apache.cxf</groupId> 32 <artifactId>cxf-rt-frontend-jaxws</artifactId> 33 <version>${cxf.version}</version> 34 </dependency> 35 <!--cxf-rt-frontend-jaxrs支持rest服务--> 36 <dependency> 37 <groupId>org.apache.cxf</groupId> 38 <artifactId>cxf-rt-frontend-jaxrs</artifactId> 39 <version>${cxf.version}</version> 40 </dependency> 41 <dependency> 42 <groupId>org.apache.cxf</groupId> 43 <artifactId>cxf-rt-transports-http</artifactId> 44 <version>${cxf.version}</version> 45 </dependency> 46 <!--用于跨域的jar包--> 47 <dependency> 48 <groupId>com.thetransactioncompany</groupId> 49 <artifactId>java-property-utils</artifactId> 50 <version>1.9</version> 51 </dependency> 52 <dependency> 53 <groupId>com.thetransactioncompany</groupId> 54 <artifactId>cors-filter</artifactId> 55 <version>1.7</version> 56 </dependency> 57 <!-- 用于序列化json服务 --> 58 <dependency> 59 <groupId>org.codehaus.jackson</groupId> 60 <artifactId>jackson-jaxrs</artifactId> 61 <version>${jackson.version}</version> 62 </dependency> 63 <!--测试框架--> 64 <dependency> 65 <groupId>junit</groupId> 66 <artifactId>junit</artifactId> 67 <version>4.9</version> 68 <scope>test</scope> 69 </dependency> 70 </dependencies> 71 <build> 72 <finalName>cxf</finalName> 73 </build> 74 </project>
9.2web.xml文件
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 <!DOCTYPE web-app PUBLIC 2 "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" 3 "http://java.sun.com/dtd/web-app_2_3.dtd" > 4 5 <web-app> 6 <display-name>Archetype Created Web Application</display-name> 7 <!-- 通过上下文参数指定spring配置文件的位置 --> 8 <context-param> 9 <param-name>contextConfigLocation</param-name> 10 <param-value>classpath:spring.xml</param-value> 11 </context-param> 12 <!--用于设置跨域的拦截器--> 13 <filter> 14 <filter-name>CORS</filter-name> 15 <filter-class>com.thetransactioncompany.cors.CORSFilter</filter-class> 16 <!--允许哪一些客户端跨域--> 17 <init-param> 18 <param-name>cors.allowOrigin</param-name> 19 <param-value>*</param-value> 20 </init-param> 21 <init-param> 22 <param-name>cors.supportedMethods</param-name> 23 <param-value>GET, POST, HEAD, PUT, DELETE</param-value> 24 </init-param> 25 <init-param> 26 <param-name>cors.supportedHeaders</param-name> 27 <param-value>Accept, Origin, X-Requested-With, Content-Type, Last-Modified</param-value> 28 </init-param> 29 <init-param> 30 <param-name>cors.exposedHeaders</param-name> 31 <param-value>Set-Cookie</param-value> 32 </init-param> 33 <init-param> 34 <param-name>cors.supportsCredentials</param-name> 35 <param-value>true</param-value> 36 </init-param> 37 </filter> 38 <!-- 编码过滤器 --> 39 <filter> 40 <filter-name>encodingFilter</filter-name> 41 <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class> 42 <init-param> 43 <param-name>encoding</param-name> 44 <param-value>UTF-8</param-value> 45 </init-param> 46 </filter> 47 <filter-mapping> 48 <filter-name>encodingFilter</filter-name> 49 <url-pattern>/*</url-pattern> 50 </filter-mapping> 51 <filter-mapping> 52 <filter-name>CORS</filter-name> 53 <!--允许跨域的路径,这里只允许我们发布的Web服务跨域--> 54 <url-pattern>/ws/*</url-pattern> 55 </filter-mapping> 56 <!-- 配置spring提供的上下文载入器监听器,当项目启动时加载spring配置文件,初始化spring工厂 --> 57 <listener> 58 <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> 59 </listener> 60 <servlet> 61 <servlet-name>cxf</servlet-name> 62 <servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class> 63 </servlet> 64 <servlet-mapping> 65 <servlet-name>cxf</servlet-name> 66 <url-pattern>/ws/*</url-pattern> 67 </servlet-mapping> 68 <!--springmvc的配置--> 69 </web-app>
9.3soap接口,实现类,实体类
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 public class User { 2 private String username; 3 private String password; 4 5 public String getUsername() { 6 return username; 7 } 8 9 public void setUsername(String username) { 10 this.username = username; 11 } 12 13 public String getPassword() { 14 return password; 15 } 16 17 public void setPassword(String password) { 18 this.password = password; 19 } 20 } 21 22 //------------------------ 23 @WebService 24 public interface UserService { 25 public User getUser(String name); 26 } 27 28 29 30 31 //-------------------------- 32 public class UserServiceImpl implements UserService{ 33 public User getUser(String name) { 34 User u=new User(); 35 u.setUsername(name); 36 u.setPassword("123456"); 37 return u; 38 } 39 }
9.4rest接口,实现类,实体类
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 public class Person implements Serializable{ 2 private String name; 3 private int age; 4 public String getName() { 5 return name; 6 } 7 public void setName(String name) { 8 this.name = name; 9 } 10 public int getAge() { 11 return age; 12 } 13 public void setAge(int age) { 14 this.age = age; 15 } 16 } 17 18 19 //interface 20 @Produces( {MediaType.APPLICATION_JSON }) 21 public interface PersonService { 22 @POST 23 @Path("/person/{name}") 24 public Person getPerson(@PathParam("name") String name); 25 @POST 26 @Path("/persons") 27 public List<Person> getPersons(); 28 } 29 30 31 //------------ 32 public class PersonServiceImpl implements PersonService{ 33 public Person getPerson(String name) { 34 Person p=new Person(); 35 p.setName(name); 36 p.setAge(100); 37 return p; 38 } 39 40 public List<Person> getPersons() { 41 List<Person> persons=new ArrayList<Person>(); 42 Person p1=new Person(); 43 p1.setName("wpx"); 44 p1.setAge(100); 45 persons.add(p1); 46 Person p2=new Person(); 47 p2.setName("zlr"); 48 p2.setAge(100); 49 persons.add(p2); 50 return persons; 51 } 52 }
9.5spring-cxf配置文件
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 <?xml version="1.0" encoding="UTF-8"?> 2 <beans xmlns="http://www.springframework.org/schema/beans" 3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 4 xmlns:jaxws="http://cxf.apache.org/jaxws" 5 xmlns:jaxrs="http://cxf.apache.org/jaxrs" 6 xsi:schemaLocation="http://www.springframework.org/schema/beans 7 http://www.springframework.org/schema/beans/spring-beans-4.0.xsd 8 http://cxf.apache.org/jaxws 9 http://cxf.apache.org/schemas/jaxws.xsd 10 http://cxf.apache.org/jaxrs 11 http://cxf.apache.org/schemas/jaxrs.xsd"> 12 <!-- 13 id:当前服务的唯一标识 address:当前服务对应的请求url serviceClass:接口类型 14 --> 15 <jaxws:server id="soapuser" address="/user" 16 serviceClass="com.skd.service.UserService"> 17 <jaxws:serviceBean> 18 <bean class="com.skd.service.impl.UserServiceImpl" /> 19 </jaxws:serviceBean> 20 </jaxws:server> 21 <!-- 发布一个Restful方式的WebService服务 --> 22 <bean id="personServiceImpl" class="com.skd.service.impl.PersonServiceImpl"></bean> 23 <jaxrs:server id="personService" address="/rest"> 24 <jaxrs:serviceBeans> 25 <ref bean="personServiceImpl" /> 26 </jaxrs:serviceBeans> 27 <jaxrs:providers> 28 <!--提供序列化为json数据的实现类--> 29 <bean class="org.codehaus.jackson.jaxrs.JacksonJsonProvider"></bean> 30 </jaxrs:providers> 31 <jaxrs:inInterceptors> 32 <bean class="org.apache.cxf.interceptor.LoggingInInterceptor"></bean> 33 </jaxrs:inInterceptors> 34 <jaxrs:outInterceptors> 35 <bean class="org.apache.cxf.interceptor.LoggingOutInterceptor"></bean> 36 </jaxrs:outInterceptors> 37 </jaxrs:server> 38 </beans>
10.SpringBeanAutowiringSupport介绍
Spring为JAX-WS Servlet 终端实现类(SpringBeanAutowiringSupport
)提供了一个方便的基类。为暴露我们的AccountService
,我们扩展了Spring的SpringBeanAutowiringSupport
类并在这里实现了业务逻辑,通常委托这个调用给业务层。我们将简单地在Spring管理的beans的依赖上使用Spring的@Autowired注解。
Spring之集成之Web Services:https://blog.csdn.net/luccs624061082/article/details/40797107
spring-web在version2.5.1的时候,在package org.springframework.web.context.support下加入了一个工具类叫SpringBeanAutowiringSupport,主要用来对Spring Web Application Context之外的类提供@Autowired注入功能。
具体来讲,Servlet中本来不能使用@Autowired注入bean,解决办法是在Servlet的init(ServletConfig)方法中调用SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext(this),就可以直接使用@Autowired来注入Web Application Context下的一些Service等Bean了。(见下例)
又或者使用Quartz Job的时候,可以在Job类中使用SpringBeanAutowiringSupport,就可以直接直使Spring的bean了。(当然如果Job比较多的话,这种方法还是很不方便,推荐使用SchedulerFactoryBean来集成。另一种更方便的办法是直接将Job集成到Spring Context中,当做一个bean)。
值得注意的是,这个类的作用域是Web Application Context,如果应用中实现的是一个比如ConfigurableApplicationContext,那就不能用该方法来对Servlet或是Job或是其它目标类提供@Autowired。
1. 例子:在Servlet中使用:
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 public class InitServlet extends HttpServlet { 2 3 @Autowired 4 private ServiceA serviceA; 5 6 public void init(ServletConfig config) throws ServletException { 7 super.init(config); 8 SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext(this); 9 assertNotNull("Service should be injected.", serviceA); 10 } 11 12 // Omitted doGet(req, res), doPost(req, res); 13 }
2. 例子:在Quartz Job中使用:
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 public class DumpJob implements Job { 2 3 @Autowired 4 private ServiceA serviceA; 5 6 public void execute(JobExecutionContext context) throws JobExecutionException { 7 SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext(this); 8 assertNotNull("Service should be injected.", serviceA); 9 } 10 }
3. SpringBeanAutowiringSupport源码分析:
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 /** 2 * Process {@code @Autowired} injection for the given target object, 3 * based on the current web application context. 4 * <p>Intended for use as a delegate. 5 * @param target the target object to process 6 * @see org.springframework.web.context.ContextLoader#getCurrentWebApplicationContext() 7 */ 8 public static void processInjectionBasedOnCurrentContext(Object target) { 9 Assert.notNull(target, "Target object must not be null"); 10 WebApplicationContext cc = ContextLoader.getCurrentWebApplicationContext(); 11 if (cc != null) { 12 AutowiredAnnotationBeanPostProcessor bpp = new AutowiredAnnotationBeanPostProcessor(); 13 bpp.setBeanFactory(cc.getAutowireCapableBeanFactory()); 14 bpp.processInjection(target); 15 } 16 else { 17 if (logger.isDebugEnabled()) { 18 logger.debug("Current WebApplicationContext is not available for processing of " + 19 ClassUtils.getShortName(target.getClass()) + ": " + 20 "Make sure this class gets constructed in a Spring web application. Proceeding without injection."); 21 } 22 } 23 }
从方法第2行可以看出通过ContextLoader拿到当前的WebApplicationContext对象,再通过AutowiredAnnotationBeanPostProcessor类来解决当前传入的目标class的@Autowired注入能力。
(AutowiredAnnotationBeanPostProcessor在Spring2.5随着Annotation功能的扩展而增加的,我们平时用context namepace的标签<context:component-scan>时,Spring会默认生成注册AutowiredAnnotationBeanPostProcessor类来帮助解析@Autowired @Value @Inject等标签。)
4. 使用另一个工具类WebApplicationContextUtils来获取Service Bean:
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 WebApplicationContext context = WebApplicationContextUtils.getWebApplicationContext(config.getServletContext()); 2 ServiceA ServiceA = context.getBean(ServiceA.class);
当然这个方法更强大,因为直接拿到WebApplicationContext对象了!
5. 补充WebApplicationContext相关:
对于Web项目,通常使用org.springframework.web.context.ContextLoaderListener,设置属性contextConfigLocation来生成WebApplicationContext。
WebApplicationContext类图(用StarUML画的):