WebService之soap类型的服务和rest类型的服务 1.引言 2.什么是WSDL? 3.在WSDL文件中我们可以获得什么信息? 4.利用Java发布soap服务 5.利用JDK注释控制WSDL文件 6.1利用wsimport进行soap服务进行调用 6.2通过UrlConnection访问Soap服务 6.3利用JDK的Service方法 7.CXF发布服务 8.CXF与Web程序的整合 9.CXF与spring的整合 10.SpringBeanAutowiringSupport介绍

WebService之soap类型的服务和rest类型的服务
1.引言
2.什么是WSDL?
3.在WSDL文件中我们可以获得什么信息?
4.利用Java发布soap服务
5.利用JDK注释控制WSDL文件
6.1利用wsimport进行soap服务进行调用
6.2通过UrlConnection访问Soap服务
6.3利用JDK的Service方法
7.CXF发布服务
8.CXF与Web程序的整合
9.CXF与spring的整合
10.SpringBeanAutowiringSupport介绍

      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服务,代码如下:

 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 }
View Code

5.利用JDK注释控制WSDL文件

代码如下:

 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 }
View Code

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服务,代码如下

  

 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 }
View Code

总结:wsimport调用web服务的java代码是有规律的,总共分为三步:

  • 创建服务名对象
  • 通过服务名获得接口对象(一般是getXXX,其中XXX代表服务名的port属性)
  • 通过接口对象调用服务方法

  

6.2通过UrlConnection访问Soap服务

 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 }
View Code

6.3利用JDK的Service方法

      在前两种方法中,第一种方案生成的代码非常多,第二种方案服务器返回的数据需要我们来解析,都不是非常的完美,我们可以使用第三种方法,生成的代码不是非常的多,对于服务器返回的数据也不需要我们自己来解析,过程如下。

  • 首先我们使用wsimport生成本地代码(但是我们只把接口文件拷贝到我们项目中来)
 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 }
View Code
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("\", "/");
View Code

  注: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服务
 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 }
View Code
 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 }
View Code

7.2 CXF发布SOAP类型的服务-有接口(服务地址:”http://localhost:8080/hello“)

接口:

1 package com.skd.service;
2 @WebService
3 public interface IHi {
4     public String sayHi(String name);
5 }
View Code

实现类:

 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 }
View Code

发布服务:

 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 }
View Code

7.3.cxf发布rest服务(服务地址:http://localhost:8080/hello/*)

创建Person类(必须实现Serializable接口

 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 }
View Code

接口:

 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 }
View Code

实现类:

 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 }
View Code

发布服务(注意必须添加序列化类此处用的是JacksonJsonProvider):

 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 }
View Code

8.CXF与Web程序的整合

8.1 POM.xml文件

 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>
View Code

8.2 web.xml文件

 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>
View Code

8.3 SOAP服务的接口,类,实体类

 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 }
View Code

8.4 rest服务的实体类,接口,接口的实现类

 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 }
View Code

8.5 CXF的配置文件(cxf.xml)

 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>
View Code

查看网址http://localhost:8080/ws

9.CXF与spring的整合

所实现的功能有:

  • 将Person,PersonService,PersonServiceImpl发布为Rest类型的服务
  • 将User ,UserService,UserServiceImpl发布为Soap类型的服务
  • 允许我们的Web服务可以跨域请求

9.1POM.xml文件

 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>
View Code

9.2web.xml文件

 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>
View Code

9.3soap接口,实现类,实体类

 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 }
View Code

9.4rest接口,实现类,实体类

 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 }
View Code

9.5spring-cxf配置文件

 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>
View Code

访问地址http://localhost:8080/ws

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。 

官方Doc: 
http://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/web/context/support/SpringBeanAutowiringSupport.html 

1. 例子:在Servlet中使用: 

 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 }  
View Code

2. 例子:在Quartz Job中使用:

 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 }  
View Code

3. SpringBeanAutowiringSupport源码分析: 

 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     }  
View Code

  从方法第2行可以看出通过ContextLoader拿到当前的WebApplicationContext对象,再通过AutowiredAnnotationBeanPostProcessor类来解决当前传入的目标class的@Autowired注入能力。 
(AutowiredAnnotationBeanPostProcessor在Spring2.5随着Annotation功能的扩展而增加的,我们平时用context namepace的标签<context:component-scan>时,Spring会默认生成注册AutowiredAnnotationBeanPostProcessor类来帮助解析@Autowired @Value @Inject等标签。) 

4. 使用另一个工具类WebApplicationContextUtils来获取Service Bean: 

1 WebApplicationContext context = WebApplicationContextUtils.getWebApplicationContext(config.getServletContext());  
2 ServiceA ServiceA = context.getBean(ServiceA.class);  
View Code

当然这个方法更强大,因为直接拿到WebApplicationContext对象了! 

5. 补充WebApplicationContext相关: 
对于Web项目,通常使用org.springframework.web.context.ContextLoaderListener,设置属性contextConfigLocation来生成WebApplicationContext。 

WebApplicationContext类图(用StarUML画的): 
WebService之soap类型的服务和rest类型的服务
1.引言
2.什么是WSDL?
3.在WSDL文件中我们可以获得什么信息?
4.利用Java发布soap服务
5.利用JDK注释控制WSDL文件
6.1利用wsimport进行soap服务进行调用
6.2通过UrlConnection访问Soap服务
6.3利用JDK的Service方法
7.CXF发布服务
8.CXF与Web程序的整合
9.CXF与spring的整合
10.SpringBeanAutowiringSupport介绍

webservice发布使用spring的SpringBeanAutowiringSupport自动装配不了属性