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

来源:互联网 发布:数控冲床用什么编程 编辑:程序博客网 时间:2024/06/08 19:00

本文主要就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<WeatherModel> 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<WeatherModel> queryWeather(@WebParam(name="cityName")String name);}

WeatherInterfaceImpl.java

public class WeatherInterfaceImpl implements WeatherInterface {    @Override    public List<WeatherModel> queryWeather(String name) {        //构造测试数据        List<WeatherModel> list = new ArrayList<WeatherModel>();        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<WeatherModel> 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整合的标签<jaxws:server>
  • 客户端调用服务:使用spring和cxf整合的标签<jaxws:client>
  • <jaxws:server><jaxws:client>可以理解为spring容器中的bean,发布服务和客户端调用交给spring容器管理。

applicationContext.xml配置

<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans"    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"    xmlns:context="http://www.springframework.org/schema/context"    xmlns:aop="http://www.springframework.org/schema/aop"    xmlns:tx="http://www.springframework.org/schema/tx"    xmlns:jaxws="http://cxf.apache.org/jaxws"    xmlns:jaxrs="http://cxf.apache.org/jaxrs"     xmlns:cxf="http://cxf.apache.org/core"    xsi:schemaLocation="http://www.springframework.org/schema/beans                         http://www.springframework.org/schema/beans/spring-beans-3.2.xsd                        http://www.springframework.org/schema/context                        http://www.springframework.org/schema/context/spring-context.xsd                        http://www.springframework.org/schema/aop                        http://www.springframework.org/schema/aop/spring-aop.xsd                        http://www.springframework.org/schema/tx                         http://www.springframework.org/schema/tx/spring-tx.xsd                        http://cxf.apache.org/jaxrs                         http://cxf.apache.org/schemas/jaxrs.xsd                        http://cxf.apache.org/jaxws                         http://cxf.apache.org/schemas/jaxws.xsd                        http://cxf.apache.org/core                         http://cxf.apache.org/schemas/core.xsd">    <!--         配置发布服务端      -->    <bean id="weatherInterface" class="com.ws.service.WeatherInterfaceImpl"></bean>    <!--         发布服务        和使用endpoint发布服务类似         WebService地址=tomcat地址+cxf+/weather     -->    <jaxws:server address="/weather" serviceClass="com.ws.service.WeatherInterface">        <jaxws:serviceBean>            <ref bean="weatherInterface" />        </jaxws:serviceBean>    </jaxws:server></beans>

web.xml配置

<?xml version="1.0" encoding="UTF-8"?><web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5">  <display-name>SpringWebServiceServer</display-name>  <!-- 加载spring容器 -->  <context-param>    <param-name>contextConfigLocation</param-name>    <param-value>/WEB-INF/classes/applicationContext.xml</param-value>  </context-param>  <listener>    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>  </listener>  <!-- cxf的Servlet -->  <servlet>    <servlet-name>cxf</servlet-name>    <servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class>    <load-on-startup>1</load-on-startup>  </servlet>  <!-- 配置cxf的访问地址 -->  <!-- 本系统中webService必须以/ws/*开头 -->  <servlet-mapping>    <servlet-name>cxf</servlet-name>    <url-pattern>/ws/*</url-pattern>  </servlet-mapping>  <welcome-file-list>    <welcome-file>index.jsp</welcome-file>  </welcome-file-list></web-app>

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

测试结果:测试结果


Client客户端的开发

applicationContext.xml的配置

<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans"    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"    xmlns:context="http://www.springframework.org/schema/context"    xmlns:aop="http://www.springframework.org/schema/aop"    xmlns:tx="http://www.springframework.org/schema/tx"    xmlns:jaxws="http://cxf.apache.org/jaxws"    xmlns:jaxrs="http://cxf.apache.org/jaxrs"     xmlns:cxf="http://cxf.apache.org/core"    xsi:schemaLocation="http://www.springframework.org/schema/beans                         http://www.springframework.org/schema/beans/spring-beans-3.2.xsd                        http://www.springframework.org/schema/context                        http://www.springframework.org/schema/context/spring-context.xsd                        http://www.springframework.org/schema/aop                        http://www.springframework.org/schema/aop/spring-aop.xsd                        http://www.springframework.org/schema/tx                         http://www.springframework.org/schema/tx/spring-tx.xsd                        http://cxf.apache.org/jaxrs                         http://cxf.apache.org/schemas/jaxrs.xsd                        http://cxf.apache.org/jaxws                         http://cxf.apache.org/schemas/jaxws.xsd                        http://cxf.apache.org/core                         http://cxf.apache.org/schemas/core.xsd">    <!-- 使用client标签调用服务端 -->    <jaxws:client        id="weatherClient"        address="http://localhost:8080/SpringWebServiceServer/ws/weather?wsdl"        serviceClass="com.ws.weather.WeatherInterface">    </jaxws:client> </beans>

使用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<WeatherModel> 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<Student> 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<Student> queryStudentList(String type) throws Exception {        List<Student> list = new ArrayList<Student>();        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();    }}
0 0
原创粉丝点击