`
han_zw
  • 浏览: 174179 次
  • 性别: Icon_minigender_1
  • 来自: 天津
社区版块
存档分类
最新评论

JAX-RS方式的RESTful Web Service开发

阅读更多

JAX-RS 方式的 RESTful Web Service 开发

                                                                          ——基于 CXF+Spring 的实现

Web Service 目前在风格上有两大类,一个是基于 SOAP 协议,一个是完全遵循 HTTP 协议规范的 RESTful 风格。 SOAP 方式的 web service 已经很成熟了,应用也很广,已经成为 Web Service 的工业标准。不过 RESTful Web Service 现在势头越来越猛,特别是其灵活性以及与 Ajax 的完美结合,让人爱不释手,很有必要了解一下。 RESTful 就是一种架构风格,是对 HTTP 协议的完全遵循。像是人们经历了无止境的对 HTTP 引申、扩展之路后的一种回归,让 web service 开发者重新做回 HTTP 协议的信徒。 RESTful 倡导用 HTTP 协议中的 verb 与实际数据操作的增删改查相对应,如 HTTP 中的 PUT GET POST DELETE 分别对应 web 系统中数据的改、查、增、删的操作。当然 RESTful 支持的 http verb 还不仅限于上述 4 个,还有像其他的 HEAD,OPTION ……等,不过上述 4 个已经够我们日常使用了。

目前 Web Service 的框架很多,不过我只用过 CXF ,所以我还是以 apache-cxf2.2.2 为例介绍一下 RESTful Web Service 的开发。

比较常见的 RESTful Web Service 的发布有 JAX-RS 风格、 Provider 方式、 Servlet 方式、 HTTPBinding ,也许还有其他方式,不过我只知道这些了。总的感觉最偷懒的方式是采用 Servlet 方式发布 Web Service ,说是 Web Service 发布,其实就是转换下对 Servlet 的认识, Servlet 本身就支持对 HTTP 请求中各种动作的支持,所以 Servlet 原生就是一种 RESTful Web Service 。不过这种方式我觉得有些不够时尚。 Povider 的方式我了解了一下,需要实现 Provider 接口,感觉很受拘束。正在我对 RESTful 丧失兴趣的时候,发现了 JAX-RS 风格, JAX-RS 就像是一个清纯 MM ,服务端配置完成,而且配置非常的清秀。而且也非常的平易近人,客户端调用方式很灵活。接下来我就把她介绍给大家。

1.      环境搭建

在本示例中采用了 Web Project 的方式, Web 工程建立的过程就不再赘述了,只列举一下环境需要的 jar 包。如下:

下面是我本地工程中的 jar ,仅供参考。

环境信息

注:如果要在 RESTful 服务中直接返回 json 数据格式的话, jsr311-api-1.0.jar 必不可少。

2.      服务开发

我们以简单的一个客户信息服务为例进行介绍。服务的业务实现大家不用太在意,关注服务开发的过程就好了。

2.1   开门见山

首先我们先构造一个客户的 VO

 

package com.harvey.cxf.demo.rest.rs.vo;

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement(name = "Customer")
@XmlAccessorType(XmlAccessType.FIELD)
public class Customer {
    private long id;
    private String name;

    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;
    }
}

 

接下来以 CustomerService 作为客户服务的实现类

先以最常见的查询某一客户信息为例,如下:

@Path("/")
public class CustomerService {
    ……
   //普通路径参数方式GET请求
    @GET
    @Path("/customers/{id}")
    public Customer getCustomer(@PathParam("id") String id) {
        ……
    }
}

 

假设我们的服务最终发布地址为 http://127.0.0.1:8080/customerservice 的话,如果要查询某一客户的信息的话,我们只需发送 GET 请求 http://127.0.0.1:8080/customerservice/customers/123 ,或者直接在浏览器中输入该 url 就可直接访问该服务。其中 url 中传入的 123 会自动适配到服务中的 {id} 参数。这样一个简单的处理 GET 请求的 RESTful Web service 就开发完了。

2.2 参数处理

在上面的例子中我们看到, client 在服务请求时传递参数是通过的请求路径的方式传入的。如之前的 http://127.0.0.1:8080/customerservice/customers/123 , 客户 ID123 作为了路径一部分。对应的服务器端的参数配置采用了 @PathParam ( "id" ) String id
除了支持路径传递的方式之外,我们还可以在请求时的查询参数中指定。比如还是查询某一客户的信息, server 端代码可以如下:

……
@GET
    @Path("/customers/getCustomerById")
    public Customer getCustomerByQueryString(@QueryParam("id") String id){
       ……
    }

此时该服务访问 url 则为:

http://127.0.0.1:8080/customerservice/customers/getCustomerById?id=123

说着这,也许会有听众要问了(也许没人问):之前提到的都是简单参数,这个容易,那么对于一些复杂 bean 参数该怎么处理呢?

这个问题问得好,接下来我就举例说明下。说例子之前再重复一遍啊,看例子时千万不要纠结于代码的业务逻辑,只看技术实现方式。

 

……
@GET
    @Path("/customers/getCust")
    public Customer getCustomer(@QueryParam("")Customer cust) {
        ……
}

这个例子中需要传入之前声明的客户信息类作为参数。参数处理方式为 QueryParam ,所以这时候我们访问 url 格式类似以下:

http://127.0.0.1:8080/customerservice/customers/getCust?id=123&name=xiaoming

如果参数 bean 还包括其他属性,用 & 符号依次追加就好了。还通常的 web 访问没什么区别。

如果你觉得上述用查询字串的方式不够个性的话,可以采用另外一种: @MatrixParam

Server 端代码如下:

 

……
@GET
    @Path("/customers/getCustByMat")
    public Customer getCustomerByMat(@MatrixParam("")Customer cust) {
        ……
}

这时候我们再访问时就可以用下面的形式了:

http://127.0.0.1:8080/customerservice/customers/getCustByMat;id=123;name=xiaoming

如果 cusmomer 还有其他属性,直接在后面追加就可以了,参数之间用 ; 分隔 .

以上我们用到的参数虽然采用的处理方式的注解各不相同,但是都是有注解的。接下来出场的这个就属于特殊人物了。有请 body 参数出场……

  

……
@POST
    @Path("/addCustomer")
    public Customer addCustomer(String body) {
    ……
}

这个 body 参数是 JAX-RS 中比较特殊的,它前面没有任何注解,它代表的是请求的 body 内容或者请求的 inputstream ,自动解析映射为字符串参数。因为之前我们的例子都是 GET 请求,消息中是没有 body 的,所以细心的听众可能会发现我们这次的服务的 verb 配置为了 @POST

2.3 请求、应答数据格式

之前的示例中我们的方法都返回了 Customer ,但是我们的系统是一个 RESTful web service 啊,客户端接收到的肯定是一个 HTTP response 消息,那么返回的 Customer 是怎样的一个消息内容呢?

默认情况下 reponse 消息的 Customer 会以 xml 的格式返回。类似于:

<Customer><id>123</id><name>skdjl</name></Customer>

客户端调用 server 端服务,得到上述的 xml 字串结果,然后进行后续处理。

既然这说的默认情况,言外之意就是说还有很多其他情况了,不过需要配置一下。就不得不说下@Produces注解了。@Produces就是表示server端返回的数据格式类型,具体包括application/xml, application/json, application/text……,其实就是我们常见的web端的content-type中的类型。如果我们设置为application/json,自然返回的数据格式为json形式。另一个注解:@Consumes,就是与@Produces相对应的。@Consumes是设定的客户端发送的请求数据的格式,对应支持的类型与@Produces相同。具体配置如下:

 

……
@POST
    @Path("/addCustomerUseBean")
    @Produces("application/json")
    @Consumes("application/xml")
    public Customer addCustomerUseBean(Customer cust) {
        ……
    }

         这个例子的意思是客户端传入 Customer 作为参数,传递格式为 xml 风格, server 端应答的数据格式为 json 风格。我们当然也可以在类注解中加入 @Produces @Consumes 作为服务整体的 request response 风格,具体服务方法如果不设定的话采用类的 @Produces @Consumes 的设定。

3        服务配置

服务开发完成之后,我们要做的就是把服务发布出去。发布方式也很灵活,可以采用编码的方式,也可以和 spring 结合用配置的方式。在下面的例子中我们采用后者。配置的内容不再做过多的解释,大家看一下就能明白。

3.1   web.xml 的配置

 

<?xml version="1.0" encoding="UTF-8"?>

<web-app version="2.4"
         xmlns="http://java.sun.com/xml/ns/j2ee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
         http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">

         <display-name>DEMO</display-name>
         <context-param>
                   <param-name>contextConfigLocation</param-name>
                   <param-value>classpath*:/applicationContext*.xml</param-value>
         </context-param>

         <listener>
                  <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
         </listener>

         <listener>
         <listener-class>org.springframework.web.util.IntrospectorCleanupListener</listener-class>
         </listener>

         <servlet>
                 <servlet-name>CXFServlet</servlet-name>
                 <servlet-class>
                          org.apache.cxf.transport.servlet.CXFServlet
                 </servlet-class>
                 <load-on-startup>1</load-on-startup>
          </servlet>

         <servlet-mapping>
                 <servlet-name>CXFServlet</servlet-name>
                 <url-pattern>/services/*</url-pattern>
          </servlet-mapping>

  <welcome-file-list>
    <welcome-file>index.jsp</welcome-file>
  </welcome-file-list>
</web-app>

 

3.2   spring 配置文件

 

<?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:aop="http://www.springframework.org/schema/aop"
         xmlns:cxf="http://cxf.apache.org/core"
    xmlns:jaxws="http://cxf.apache.org/jaxws"
    xmlns:jaxrs="http://cxf.apache.org/jaxrs"

         xsi:schemaLocation="
         http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
         http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd
         http://cxf.apache.org/jaxrs http://cxf.apache.org/schemas/jaxrs.xsd
         http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">

         <import resource="classpath:META-INF/cxf/cxf.xml" />
         <import resource="classpath:META-INF/cxf/cxf-extension-soap.xml" />
         <import resource="classpath:META-INF/cxf/cxf-servlet.xml" />
         <import resource="classpath:META-INF/cxf/cxf-extension-jaxrs-binding.xml"/>

   <jaxrs:server id="customerService" address="/customerservice">
                   <jaxrs:serviceBeans>
          <ref bean="customerServiceBean"/>
        </jaxrs:serviceBeans>
   </jaxrs:server>
   <bean id="customerServiceBean" class="com.harvey.cxf.demo.rest.rs.server.CustomerService"/>
</beans>

 

然后启动我们的 web 程序,服务就发布完成了。可以在浏览器中敲入:

http://127.0.0.1:8080/customerservice/customers/1 测试服务是否正常。

从上面的例子也许你能发现,我们虽然是做的RESTful的例子,但是具体提供的服务verb中很多都是带有动作的成分比如getCustomer,addCustomer等等,这些词汇的存在预示着我们的服务虽然采用了RESTful的技术,但是并没有遵循ROA(面向资源的架构)的理念,真正的ROA信徒看到上面的例子可能会非常不爽。因为毕竟RESTful和ROA才是青梅竹马。不过正如前面提到的,大家值关注技术实现就好了。

4        客户端调用

我们的服务发布完成了,接下来我们可以做一个测试 client 程序进行 测试。对于 RESTful 的调用方式很多,可以用 java Connect 方式,也可以用 apche httpclint ,另外还可以用 cxf 提供的 WebClient 进行,等等。后面的 client 代码中分别采用几种调用方式,在这里我们不必拘泥,可以任意选用自己熟悉的方式。代码详见第 5 节。

5        完整代码

见附件

  • 大小: 16.4 KB
  • src.rar (3.4 KB)
  • 下载次数: 684
3
3
分享到:
评论
10 楼 dywkaifa 2013-12-13  
您好,我想问一下,就是我有多个用于服务的类,而且每个类里面有多个方法,所以我想在spring的配置文件里面配置多个服务,但是总是不成功,请问您知道怎么配置多个服务么??
9 楼 han_zw 2013-11-23  
xiyuansanlian 写道
张俊坡 写道
LZ,你好~
我想问个问题,我现在有个设计:

@POST
@Path("/updateEventStatus")
@Consumes({MediaType.APPLICATION_JSON,MediaType.APPLICATION_XML})
void updateEventStatus(String eventId,String eventStatus);

这是我接口里的一个方法,我想接收一个JSON格式的参数比如
{
    "EventID":"1234",
    "Status":"1"
}

我想问的是,当我接收到这个参数后,怎么通过参数注解把JSON里的两个参数值对应到我方法的两个参数,就是说eventId的值是"1234",eventStatus的值是"1"????

谢谢了。。




抱歉,这个我也没弄过。我一般是把json的参数直接映射为一个结构化的参数,而不是多个离散参数。
8 楼 han_zw 2013-11-23  
itcyt 写道
您好,这个rest怎么加上安全认证呢?求解,谢谢


一般会在HTTP的header中设定用户名和口令或者token,server端从header中提取认证信息。
7 楼 javaeessh 2013-10-15  
你的代码很实用,findjar.com 很多jar包都不能找到,希望能发我一份完整的代码,xsshun@gmail.com。谢谢
6 楼 xiyuansanlian 2013-08-09  
张俊坡 写道
LZ,你好~
我想问个问题,我现在有个设计:

@POST
@Path("/updateEventStatus")
@Consumes({MediaType.APPLICATION_JSON,MediaType.APPLICATION_XML})
void updateEventStatus(String eventId,String eventStatus);

这是我接口里的一个方法,我想接收一个JSON格式的参数比如
{
    "EventID":"1234",
    "Status":"1"
}

我想问的是,当我接收到这个参数后,怎么通过参数注解把JSON里的两个参数值对应到我方法的两个参数,就是说eventId的值是"1234",eventStatus的值是"1"????

谢谢了。。

5 楼 han_zw 2013-03-15  
firefly5002 写道
请问下,如果要上传附件怎么办啊?


参数类型除了上述列出的几种方式之外,还是可以用@Context这个注解,这样可以直接绑定到上下文的资源,比如 public Customer addCustomer(@Context HttpServletRequest request) {
……

这样代码中就可以直接拿到request对象了,然后的处理就和普通文件上传没有别了  
4 楼 firefly5002 2013-03-14  
请问下,如果要上传附件怎么办啊?
3 楼 张俊坡 2013-03-08  
LZ,你好~
我想问个问题,我现在有个设计:

@POST
@Path("/updateEventStatus")
@Consumes({MediaType.APPLICATION_JSON,MediaType.APPLICATION_XML})
void updateEventStatus(String eventId,String eventStatus);

这是我接口里的一个方法,我想接收一个JSON格式的参数比如
{
    "EventID":"1234",
    "Status":"1"
}

我想问的是,当我接收到这个参数后,怎么通过参数注解把JSON里的两个参数值对应到我方法的两个参数,就是说eventId的值是"1234",eventStatus的值是"1"????

谢谢了。。
2 楼 han_zw 2012-09-09  
1.采用数据证书
2.在http请求消息的header部分加入加密的认证信息,在header部分加入内容不会破坏restful对http的原教义宗旨
这两种实施起来都比较简单
1 楼 itcyt 2011-12-27  
您好,这个rest怎么加上安全认证呢?求解,谢谢

相关推荐

    jax-rs jax-ws所需包,亲测可用

    标题"jax-rs jax-ws所需包,亲测可用"表明这个压缩包包含了用于开发Java RESTful Web服务(JAX-RS)和Java SOAP Web服务(JAX-WS)所需的库文件。这些库是Java应用程序进行Web服务交互的核心组件,确保了对HTTP协议...

    一个包含jax-ws和jax-rs的例子(含服务端和客户端)

    标题中的“一个包含jax-ws和jax-rs的例子(含服务端和客户端)”是指这是一个示例项目,它演示了如何使用Java API for XML Web Services (JAX-WS)和Java API for RESTful Web Services (JAX-RS)来创建和消费Web服务。...

    JAX-WS API, JAX-RS API

    Java API for RESTful Web Services (JAX-RS) 是Java平台上的另一项重要规范,它定义了如何在Java应用中创建RESTful Web服务。REST(Representational State Transfer)是一种轻量级的架构风格,强调资源的交互,...

    jax-ws jax-rs 分别创建soap和restful类型的webservice

    JAX-WS是Java API for XML Web Services的缩写,它为开发人员提供了一种在Java平台上构建SOAP Web服务和客户端的标准化方式。以下是使用JAX-WS创建SOAP Web服务的基本步骤: 1. **定义服务接口**:使用Java SE中的`...

    JAX-RS Extension

    在Java世界中,JAX-RS(Java API for RESTful Web Services)是用于构建RESTful Web服务的标准API。这篇博客文章(遗憾的是,链接不可用)可能探讨了如何通过扩展JAX-RS来增强其功能,以满足特定需求或提高开发效率...

    JAX-RS包(内含1.0和1.4)

    JAX-RS,全称Java API for RESTful Web Services,是Java平台上的一个标准,用于构建RESTful风格的Web服务。REST(Representational State Transfer)是一种轻量级、基于HTTP协议的设计模式,常用于实现分布式系统中...

    JAX-RS cxf web服务 rest简单增删改查 集成spring webService

    **JAX-RS CXF Web服务 RESTful CRUD与Spring集成详解** JAX-RS(Java API for RESTful Web Services)是Java平台上的一个标准,用于创建RESTful Web服务。REST是一种轻量级的架构风格,它以资源为中心,通过HTTP...

    Jax-RS所需要的依赖jar

    在开发基于Java的RESTful Web服务时,JAX-RS(Java API for RESTful Web Services)扮演了核心角色。它是一种标准,允许开发者通过简单的注解来创建HTTP服务,简化了Web服务的开发过程。本资源包“Jax-RS所需要的...

    JAX-RS web 服务配置及教程

    **Jersey** 是JAX-RS的参考实现之一,它简化了Java中RESTful Web 服务的开发过程。 #### 二、环境搭建 在创建JAX-RS Web服务客户端之前,首先需要完成环境搭建: 1. **下载Eclipse IDE**:选择一个支持Java EE...

    JAX-RS-messanger-service:使用JAX-RS的消息传递REST服务

    JAX-RS(Java API for RESTful Web Services)是Java平台上的一个标准,用于创建基于REST(Representational State Transfer)风格的Web服务。REST是一种轻量级的架构风格,它强调通过HTTP协议提供资源的简单、直接...

    RESTful_Java_with_JAX-RS

    总之,《RESTful Java with JAX-RS》是一本全面介绍如何使用Java和JAX-RS来设计和开发RESTful服务的书籍。它不仅涵盖了RESTful架构的基本原则,还深入探讨了JAX-RS的具体实现细节,是Java开发者不可或缺的参考指南。

    为Android 创建一个 JAX-RS 客户端 代码示例

    在Android平台上,开发人员...在`android-jaxrs-sourcecode`这个文件中,你应该能找到一个实际的代码示例,展示了上述步骤的具体实现。通过研究和理解这些代码,你将能够更好地掌握在Android上构建JAX-RS客户端的方法。

    ssh rest ws jax-rs jersey 做的小网站后台及web service接口

    【SSH REST WS JAX-RS Jersey 小网站后台及Web Service接口详解】 SSH(Spring、Struts、Hibernate)是Java Web开发中常见的三层架构,它整合了Spring的依赖注入、Struts的MVC模式和Hibernate的对象关系映射,提供...

    web-service-jax-rs:使用jax rs创建Web服务的教程

    其中,JAX-RS(Java API for RESTful Web Services)是Java平台上的一个标准,用于简化创建RESTful Web服务的过程。本教程将深入探讨如何使用JAX-RS来构建高效、可维护的Web服务。 REST(Representational State ...

    Java Restful Web Service,edition2.代码

    代码】这个压缩包文件是关于使用Java开发RESTful Web服务的第二版源码,主要聚焦于JAX-RS 2.0规范的应用。RESTful Web服务是一种广泛用于构建分布式系统的服务架构风格,它基于HTTP协议,使得API设计简洁且易于理解...

    Java-Web-Service:带有JAX-RS的示例RESTful API(在MySQL数据库上实现基本的HTTP方法)

    带有JAX-RS的示例RESTful API(在MySQL数据库上实现基本的HTTP方法)。 ##一些东西 使用Maven。 因此,请相应地导入。 不涉及身份验证。 (就这么简单。) 没有数据库持久性或连接池完成。 不进行内容协商(仅...

    cxf-bundle-jaxrs-2.4.7.zip

    【标题】"CXF-BUNDLE-JAXRS-2.4.7.zip" 是一个与Apache CXF相关的开源项目,它包含了一个JAX-RS(Java API for RESTful Web Services)的OSGi捆绑包。JAX-RS是Java平台上的标准,用于创建RESTful服务,而CXF是一个...

    CursoWebServices:Curso Java Web服务JAX-WS JAX-RS

    本课程“CursoWebServices: Curso Java Web服务JAX-WS JAX-RS”专注于使用Java语言来开发和实现Web服务,特别关注JAX-WS和JAX-RS两个关键框架。 首先,让我们深入理解Java API for XML Web Services (JAX-WS)。JAX-...

Global site tag (gtag.js) - Google Analytics