zoukankan      html  css  js  c++  java
  • WebService之soap类型的服务和rest类型的服务

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

     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发布使用spring的SpringBeanAutowiringSupport自动装配不了属性

  • 相关阅读:
    Java中==和equals的区别
    (转)JAVA-反射机制的使用
    JAVA三框架工作原理是什么?
    Spring的IoC模式
    JavaEE中为什么出现中文乱码?
    Android--Apache HttpClient(2种实现)
    Android之网络----使用HttpClient发送HTTP请求(通过get方法获取数据)
    Android—Http连接之GET/POST请求
    2014 12 04
    struts2的HelloWorld的基本过程
  • 原文地址:https://www.cnblogs.com/soul-wonder/p/8881976.html
Copyright © 2011-2022 走看看