首页 > 程序开发 > 软件开发 > Java >

WebService中注解开发,CXF,Spring整合,Rest风格

2016-05-06

本文主要就WebService中的利用注解配置开发,发布WebService服务,使用CXF开源框架发布服务,如何使用REST风格,以及WebService与Spring整合的使用进行详细的讲解与分析。 1、Jaxws常用注解 2、Cxf使

本文主要就WebService中的利用注解配置开发,发布WebService服务,使用CXF开源框架发布服务,如何使用REST风格,以及WebService与Spring整合的使用进行详细的讲解与分析。

1、Jaxws常用注解
2、Cxf使用分析
3、Cxf与Spring整合开发
4、Rest风格

1、JaxWs常用注解

@WebService-定义服务
targetNamespace:指定命名空间
name:portType的名称
portName:port的名称
serviceName:服务名称
endpointInterface:SEI接口地址,如果一个服务类实现了多个接口,只需要发布一个接口的方法,可通过此注解指定要发布服务的接口。

@WebMethod-定义方法(所注解的方法必须是公开方法)
operationName:方法名
exclude:设置为true表示此方法不是webservice方法,反之则表示webservice方法

@WebResult-定义返回值(所注解位置在方法返回值名称处)
name:返回结果值的名称

@WebParam-定义参数(所注解位置在方法属性名称处)
name:指定参数的名称

无论是注释或者其他的修改,都必须要重新启动WebService服务才可以生效,否则当前的WebService服务均是以未修改之前的发布版本为准

代码片段如下:
*首先准备PO类*

import java.util.Date;
public class WeatherModel {

    //天气概况
    private String detail;

    //日期
    private Date data;

    //最高温度
    private int temperature_max;

    //最低温度
    private int temperature_min;

    public String getDetail() {
        return detail;
    }
    public void setDetail(String detail) {
        this.detail = detail;
    }

    public Date getData() {
        return data;
    }
    public void setData(Date data) {
        this.data = data;
    }

    public int getTemperature_max() {
        return temperature_max;
    }
    public void setTemperature_max(int temperature_max) {
        this.temperature_max = temperature_max;
    }

    public int getTemperature_min() {
        return temperature_min;
    }
    public void setTemperature_min(int temperature_min) {
        this.temperature_min = temperature_min;
    }

    @Override
    public String toString() {
        return "WeatherModel [detail=" + detail + ", data=" + data
                + ", temperature_max=" + temperature_max + ", temperature_min="
                + temperature_min + "]";
    }

}

利用注解开发的接口类

import java.util.List;

import javax.jws.WebParam;
import javax.jws.WebResult;
import javax.jws.WebService;
import javax.xml.ws.BindingType;

import com.ws.po.WeatherModel;

@WebService(
        targetNamespace="http://weather.ws.com/",//指定 wsdl的命名空间
        name="WeatherInterface",//指定portType的名称
        portName="WeatherInterfacePort",//指定port的名称
        serviceName="WeatherService"//服务视图的名称
        )
@BindingType(javax.xml.ws.soap.SOAPBinding.SOAP12HTTP_BINDING)
public interface WeatherInterface {
    public @WebResult(name="list") List queryWeather(@WebParam(name="cityName")String name);
}

对于实现类和server的启动类,不再贴出;当我们发布了当前的服务之后,就可以从wsdl的说明文档中看见改变如下:
利用注解后文档关键位置更加清晰易读

2、Cxf使用分析

1)首先需要明确的一点是,什么是cxf:(摘自百科,详情可以在百科中查看)
Cxf是隶属于apache下的webservice的开源框架。
简单的说:Apache CXF = Celtix + Xfire,开始叫 Apache CeltiXfire,后来更名为 > Apache CXF 了,以下简称为 CXF。Apache CXF 是一个开源的 web Services 框架,CXF 帮助您构建和开发 web Services ,它支持多种协议,比如:SOAP1.1,1,2、XML/HTTP、RESTful HTTP 或者 CORBA。
CORBA(Common Object Request Broker Architecture公共对象请求代理体系结构,早期语言使用的WS。C,c++,C#)
Cxf是基于SOA总线结构,依靠spring完成模块的集成,实现SOA方式。
Cxf可以部署在多种不同类型的服务器上面,比如:Tomcat,Jboss,Jetty(已经实现了内置),WebLogic。

2)如何配置Cxf(本文暂时叙述的是Windows下的配置方法,Ubuntu等Linux的配置实际上大同小异,在/etc/profile中添加CXF_HOME路径并且进行配置即可)
Windows中配置方法:
配置环境:Win7,apache-cxf-2.4.2
配置环境变量


CXF_HOME=CXF的目录
Path = %JAVA_HOME%\bin;%CXF_HOME%\bin;
CLASSPATH=.;%CXF_HOME%\lib\cxf-manifest.jar

配置成功后可以使用wsdl2java命令进行测试;

3)CXF开发步骤:
SEI开发:
PO类还是使用上文1)中的POWeatherModel类不变;

WeatherInterface.java

@WebService(
        targetNamespace="http://weather.ws.com/",//指定 wsdl的命名空间
        name="WeatherInterface",//指定portType的名称
        portName="WeatherInterfacePort",//指定port的名称
        serviceName="WeatherService"//服务视图的名称
        )
@BindingType(javax.xml.ws.soap.SOAPBinding.SOAP12HTTP_BINDING)
public interface WeatherInterface {
    public @WebResult(name="list") List queryWeather(@WebParam(name="cityName")String name);
}

WeatherInterfaceImpl.java

public class WeatherInterfaceImpl implements WeatherInterface {

    @Override
    public List queryWeather(String name) {
        //构造测试数据
        List list = new ArrayList();

        WeatherModel weatherModel_1  =new WeatherModel();
        weatherModel_1.setDetail("晴");
        weatherModel_1.setData(new Date());
        weatherModel_1.setTemperature_max(30);
        weatherModel_1.setTemperature_min(28);

        WeatherModel weatherModel_2  =new WeatherModel();
        weatherModel_2.setDetail("晴转多云");
        weatherModel_2.setData(new Date());
        weatherModel_2.setTemperature_max(24);
        weatherModel_2.setTemperature_min(20);

        list.add(weatherModel_1);
        list.add(weatherModel_2);
        return list;
    }

}

WeatherService.java

public class WeatherService {

    public static void main(String[] args) {
        //使用Jaxws发布soap协议的webservice
        JaxWsServerFactoryBean jaxWsServerFactoryBean = new JaxWsServerFactoryBean();
        //指定webService的地址
        jaxWsServerFactoryBean.setAddress("http://127.0.0.1:12345/weather");
        //指定portType
        jaxWsServerFactoryBean.setServiceClass(WeatherInterface.class);
        //指定服务类对象
        jaxWsServerFactoryBean.setServiceBean(new WeatherInterfaceImpl());
        //发布服务
        jaxWsServerFactoryBean.create();
    }
}

运行WeatherService 发布服务

首先使用创建客户端工程,导入CXF的jar包,在使用wsdl2java生成客户端代码

wsdl2java -d . http://127.0.0.1:12345/weather?wsdl

生成的类,注意包名不得改变生成时候的自动生成的包名,但是可以使用命令自己制定包名

WeatherClientCXF.java : 客户端使用CXF

public class WeatherClientCXF {

    public static void main(String[] args) {
        //利用JaxWsProxyFactoryBean调用webService的服务端
        JaxWsProxyFactoryBean jaxWsProxyFactoryBean = new JaxWsProxyFactoryBean();
        //调用地址
        jaxWsProxyFactoryBean.setAddress("http://127.0.0.1:12345/weather?wsdl");
        //获取service服务视图
        jaxWsProxyFactoryBean.setServiceClass(WeatherInterface.class);
        //获取portType
        WeatherInterface weatherInterface = (WeatherInterface) jaxWsProxyFactoryBean.create();
        //调用portType方法
        List list = weatherInterface.queryWeather("");
        for (WeatherModel weatherModel : list) {
            System.out.println(weatherModel.getDetail());
            System.out.println(weatherModel.getTemperatureMax());
            System.out.println(weatherModel.getTemperatureMin());
            System.out.println("==============================");
        }   
    }
}

3、Cxf与Spring整合开发

Cxf框架本身依赖spring,在Cxf的下载包中本身就带有了Spring的jar包,但是一定要注意在整合的时候,要先对自己的项目备份,并且查看自己当前项目中所以依赖的jar有哪些,如果有Spring包那用的是哪一个版本的Spring,是否要先删除,或者删除CXF中的Spring包,否则造成包的冲突出现的问题很不好解决。 在上面的项目中主要是使用JaxWsServerFactoryBean和JaxWsProxyFactoryBean,所以与Spring的结合点就在这个位置,利用Spring来生成类。 发布服务:使用spring和cxf整合的标签 客户端调用服务:使用spring和cxf整合的标签 可以理解为spring容器中的bean,发布服务和客户端调用交给spring容器管理。

applicationContext.xml配置




    
    

    
    
        
            
        
    

web.xml配置



  SpringWebServiceServer

  
  
    contextConfigLocation
    /WEB-INF/classes/applicationContext.xml
  
  
    org.springframework.web.context.ContextLoaderListener
  

  
  
    cxf
    org.apache.cxf.transport.servlet.CXFServlet
    1
  

  
  
  
    cxf
    /ws/*
  

  
    index.jsp
  

在PO类,service接口以及Service的实现类均不变,与上文中的相同

测试结果:测试结果

Client客户端的开发<喎"http://www.2cto.com/kf/ware/vc/" target="_blank" class="keylink">vc3Ryb25nPjwvcD4NCjxwPjxzdHJvbmc+YXBwbGljYXRpb25Db250ZXh0LnhtbLXExeTWwzwvc3Ryb25nPjwvcD4NCjxwcmUgY2xhc3M9"brush:java;">

使用wsdl2java命令生成相关的类之后,就可以进行客户端的测试了

ClientTest.java

public class ClientTest {

    private ApplicationContext applicationContext;

    @Before
    public void before() {
        applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
    }

    @Test
    public void testClientByCxfAndSpring() {
        //从Spring容器中取出portType方法
        WeatherInterface weatherInterface = (WeatherInterface) applicationContext.getBean("weatherClient");
        //调用portType方法
        List list = weatherInterface.queryWeather("北京");

        for (WeatherModel weatherModel : list) {

            System.out.println(weatherModel);
            System.out.println("=======================================");

        }
    }
}

4、Rest风格
REST 是一种软件架构模式,只是一种风格,rest服务采用HTTP 做传输协议,REST 对于HTTP 的利用分为以下两种:资源定位和资源操作。
更加准确去定位一个互联网资源。使用url定位一个互联网资源。
比如:查询一个学生信息url
资源定位要定位一个学生信息:
不使用 rest 的url:http://ip:port/queryUser.actionuserType=XXX&studentid=001&XXXX
使用 rest 的url:http://ip:port/user/student/001
使用 rest 方式表达url更加简单、可以准确表达这个url是一个学生信息查询url

代码实现

Student.java

package com.ws.rest.pojo;

import java.util.Date;

import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement(name="student")
public class Student {
    private long id;
    private String name;
    private Date birthday;

    public long getId() {
        return id;
    }
    public void setId(long id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public Date getBirthday() {
        return birthday;
    }
    public void setBirthday(Date birthday) {
        this.birthday = birthday;
    }

    @Override
    public String toString() {
        return "Student [id=" + id + ", name=" + name + ", birthday="
                + birthday + "]";
    }

}

StudentService.java

package com.ws.rest.service;

import java.util.List;

import javax.jws.WebService;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;

import com.ws.rest.pojo.Student;

@WebService
@Path("/student")
public interface StudentService {

    //查询学生信息
    @GET //http中的GET方法
    @Path("/query/{id}") //id参数通过URL访问传递
    @Produces(MediaType.APPLICATION_XML) //返回XML
    public Student queryStudent(@PathParam("id")long id);

    //查询学生列表
    @GET //http中的GET方法
    @Path("/querylist/{type}") //JSON格式
    @Produces({MediaType.APPLICATION_JSON,"application/json;charset=utf-8"}) //返回JSON
    //如果想让json返回xml需要在rest的url后边添加?_type=xml
    public List queryStudentList(@PathParam("type")String type) throws Exception;

}   

StudentServiceImpl.java

package com.ws.rest.service;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import com.ws.rest.pojo.Student;

public class StudentServiceImpl implements StudentService {

    public Student queryStudent(long id) {
        //使用静态数据
        Student student = new Student();
        student.setId(id); 
        student.setName("张三");
        student.setBirthday(new Date());

        return student;
    }

    public List queryStudentList(String type) throws Exception {

        List list = new ArrayList();

        Student student1 = new Student();
        student1.setId(1L); 
        student1.setName("张三");
        student1.setBirthday(new Date());
        Student student2 = new Student();
        student2.setId(2L); 
        student2.setName("王五");
        student2.setBirthday(new Date());
        list.add(student1);
        list.add(student2);
        return list;
    }

}

StudentServer.java

package com.ws.rest.service;

import org.apache.cxf.jaxrs.JAXRSServerFactoryBean;

/**
 * 编程方式发布查询学生信息的服务
 * @author YQ
 *
 */
public class StudentServer {

    public static void main(String[] args) {
        //使用jaxrsServerFactoryBean发布rest的服务
        JAXRSServerFactoryBean jaxrsServerFactoryBean = new JAXRSServerFactoryBean();
        //设置rest的服务地址
        jaxrsServerFactoryBean.setAddress("http://127.0.0.1:12345/rest");
        //设置服务对象
        jaxrsServerFactoryBean.setServiceBean(new StudentServiceImpl());
        //设置资源独享
        jaxrsServerFactoryBean.setResourceClasses(StudentServiceImpl.class);
        //发布rest服务
        jaxrsServerFactoryBean.create();
    }

}
热点推荐