REST Service 开发 - JAXRS 基础

REST Service 开发 - JAXRS 基础

【摘要】本文介绍 JAXRS 常用语法与语义,案例则使用 Maven 多模块构建,集成 spring boot,
并使用 swagger 可视化工具测试服务。最终,给出同时支持 JSON 和 XML 的服务配置。

  • REST Service 开发 - JAXRS 基础
    • 1准备项目
    • 2JAX-RS 基础
      • 1 JAX-RS20 标准概述
      • 2 资源Web Resource
      • 3 常用注释
      • 4 常用参数注释
        • 41 使用 PUT 修改对象
        • 42 使用 POST 提交表单
        • 43 使用 DELETE 删除内容
        • 44 更多参数映射
    • 消息实体对象读写
      • 1 使用 XML 从 MessageBody 中读写对象
      • 2 让服务自动选择 JSON 和 XML
    • 子资源
    • 附件curl 使用简易指南

1、准备项目

1. 下载 CXF 案例

计算机学习看文档,找教程固然重要。运行官方案例 + 模仿编程才是最佳的学习方法。
编程学习总是满足“一万行定律”,即编写相关代码足够,自然理解编程的要领。
用教学学术语叫“程序性知识”,也如同学习驾驶汽车,开一万公里就学会了。

CXF 提供的案例可在官方下载获取,请下载最新二进制发行版:

http://cxf.apache.org/download.html

解压 samples 目录,作为参考

2. 创建项目

  • 建立项目目录, 例如:my-samples
  • 在项目中创建 maven 构建文件 pom.xml,内容:

<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0modelVersion>

    <groupId>com.me.testgroupId>
    <artifactId>my-samplesartifactId>
    <packaging>pompackaging>
    <version>1.0-SNAPSHOTversion>

    <name>My REST Service Samplesname>
    <description>My REST Service Samplesdescription>
    <url>http://blog.csdn.net/pmlpmlurl>

    <properties>
        
        <maven.deploy.skip>truemaven.deploy.skip>
        <project.build.sourceEncoding>UTF-8project.build.sourceEncoding>
        <spring.boot.version>1.3.6.RELEASEspring.boot.version>
        <spring.cloud.version>1.1.3.RELEASEspring.cloud.version>
        <cxf.version>3.1.10cxf.version>
        <feign.version>8.18.0feign.version>
    properties>

    <dependencies>
        <dependency>
            <groupId>org.slf4jgroupId>
            <artifactId>slf4j-jdk14artifactId>
        dependency>
        <dependency>
            <groupId>org.slf4jgroupId>
            <artifactId>jcl-over-slf4jartifactId>
        dependency>
    dependencies>

    <modules>
    modules>

project>

这里,我们定义了父项目,包括第三方组件的版本与公共依赖声明。

3. 创建 Spring Boot 模块

1.创建新模块

  • 使用 IDEA 导入项目
  • 创建模块 File –> New –> Module…
  • 设置父项目,项目坐标,位置
  • 最终产生模块的 pom.xml 如下:
    <parent>
        <artifactId>my-samplesartifactId>
        <groupId>com.me.testgroupId>
        <version>1.0-SNAPSHOTversion>
    parent>
    <modelVersion>4.0.0modelVersion>

    <groupId>com.me.test.springbootgroupId>
    <artifactId>springboot-testartifactId>
    <version>1.0-SNAPSHOTversion>
  • 按惯例在 java root 下创建包 com.me.test.springboot

2.导入 cxf 官方案例 spring_boot

  • 将 spring_boot 的 /src/main.java/samples/rs/service 目录下内容(全选中)拖入项目包 com.me.test.springboot
  • 参考 spring_boot 的 pom.xml 修改模块 pom.xml
    <dependencyManagement>
        <dependencies>
            <dependency>
                
                <groupId>org.springframework.bootgroupId>
                <artifactId>spring-boot-dependenciesartifactId>
                <version>${spring.boot.version}version>
                <type>pomtype>
                <scope>importscope>
            dependency>
        dependencies>
    dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.apache.cxfgroupId>
            <artifactId>cxf-spring-boot-starter-jaxrsartifactId>
            <version>${cxf.version}version>
        dependency>
        <dependency>
            <groupId>org.webjarsgroupId>
            <artifactId>swagger-uiartifactId>
            <version>2.2.6version>
        dependency>
        <dependency>
            <groupId>org.apache.cxfgroupId>
            <artifactId>cxf-rt-rs-service-description-swaggerartifactId>
            <version>${cxf.version}version>
        dependency>
        <dependency>
            <groupId>org.slf4jgroupId>
            <artifactId>slf4j-jdk14artifactId>
            <scope>testscope>
        dependency>
    dependencies>

3.修改 java 文件

  • 打开所有(4)个类
  • 如果有因为包名修改导致导入错误,修改 import 的位置

4.在 IDEA 直接运行 SampleRestApplication 类

在运行输出的 INFO 中仔细查看 服务器端口服务绑定的根

...
...Tomcat initialized with port(s): 8080 (http)
...
...Mapping servlet: 'CXFServlet' to [/services/*]
...

然后,根据JAX-RS映射,在浏览器中分别输入以下 url:

http://localhost:8080/services/sayHello/cxf1
http://localhost:8080/services/sayHello2/cxf2
http://localhost:8080/services/swagger.json
http://localhost:8080/services/services

这个案例展示了服务api映射与实现的关系,以及服务可视化工具 swagger 的使用

2、JAX-RS 基础

2.1 JAX-RS2.0 标准概述

The Java API for RESTful Web Services provides portable APIs for developing, exposing and accessing Web applications designed and implemented in compliance with principles of REST architectural style.

https://jax-rs-spec.java.net/nonav/2.0-rev-a/apidocs/index.html

https://jax-rs-spec.java.net/

它由一组软件包构成,最常用的就是高层包 javax.ws.rs ,它是 High-level interfaces and annotations used to create RESTful service resources

2.2 资源(Web Resource)

一个 Java POJO 类,使用 申明式 的javax.ws.rs 注释标记技术,成为能被暴露访问的 Web 资源。

主资源(Root Resource),它字少有 @Path 注释,且被注册发布。

例如:创建一个主资源对象的接口 CustomerService

@Path("/customer")
public interface CustomerService {
    @GET
    @Path("/id/{id}")
    @Produces(MediaType.TEXT_PLAIN)
    String GetCustomerName(@PathParam("id") String id);
}

添加它的实现类 CustomerServiceImpl , 注意 @api(“\customer”)
就可以使用 swagger 调试服务了!!!

@Api("/customer")
public class CustomerServiceImpl implements CustomerService {
    public String GetCustomerName(String id) {
        return "hello" + id;
    }
}

然后,修改发布代码:

endpoint.setServiceBeans(Arrays.asList(new HelloServiceImpl1(), new HelloServiceImpl2()
        , new CustomerServiceImpl())); 
  

运行!

浏览 http://localhost:8080/services/customer/id/123,或者
使用 swagger http://localhost:8080/services/services

2.3 常用注释

@Path: 用于类型和方法的注释,用于识别资源的 URI

例如:调用 GetCustomerName 方法的 URI 是 \customer\id\{id}

@PathParam : 用于方法参数的注释,绑定 URI 路径的模板

例如:请求 /customer/id/123 对应的模板{id},则 123 作为参数输入。

@GET : 用于主资源方法的注释,用于指定该方法处理 HTTP 请求的方法

例如:调用 GetCustomerName 方法的请求是 GET 方法

注:

  • HTTP 方法 JAX-RS2.0 直接支持 @GET @POST @PUT @DELETE @HEAD @OPTIONS 方法
  • @GET = @HttpMethod(“GET”)

@Produces : 定义 HTTP 响应 消息体 类型。javax.ws.rs.core.MediaType 给出了常用的枚举

例如:MediaType.TEXT_PLAIN = “text/plain” 的结果:

$ curl -v http://localhost:8080/services/customer/id/123
...
< Content-Type: text/plain;charset=UTF-8
...

@Consumes : 定义请求消息体的类型。

2.4 常用参数注释

参数注释就是将 HTTP 的请求行、header行、body体的内容映射到函数输入之中。
除了 @PathParam 外:

2.4.1 使用 PUT 修改对象

@QueryParam : 将 URL 中 QueryString 作为参数。

例如:我们希望修改客户信息,因此添加服务接口方法:

    @PUT
    @Path("/update")
    public Response updateCustomer(@DefaultValue("123") @QueryParam("id") Long id, @QueryParam("name") String name);

@PUT :修改一个对象;

@DefaultValue :参数不存在时的默认值;

服务实现中代码:

    public Response updateCustomer(Long id, String name){
        System.out.println("----invoking updateCustomer, Customer name is: " + name);
        Response r;
        //if modify OK!
        if (id == 123) {
            r = Response.ok().build();
        } else {
            r = Response.notModified().build();
        }
        return r;
    }

其中,Response 是 javax.ws.rs.core.Response

用 swagger 测试。

2.4.2 使用 POST 提交表单

@FormParam : 从输入 body 中提取参数。

例如:我们希望添加客户信息,因此添加服务接口方法:

    @POST
    @Path("/add/")
    @Consumes(MediaType.APPLICATION_FORM_URLENCODED)
    @Produces(MediaType.TEXT_PLAIN)
    public Response addCustomer(@DefaultValue("123") @FormParam("id") Long id, @FormParam("name") String name);

@Consumes 必须是 MediaType.APPLICATION_FORM_URLENCODED

服务实现中代码:

    public Response addCustomer(Long id, String name){
        System.out.println("----invoking updateCustomer, Customer name is: " + name);
        Response r;
        r = Response.ok().build();
        return r;
    }

2.4.3 使用 DELETE 删除内容

2.4.4 更多参数映射

@BeanParam : 将一个对象与 HTTP 请求映射

@Context,@MatrixParam, @HeaderParam, @CookieParam 的使用,建议看文档:

https://jersey.java.net/documentation/latest/jaxrs-resources.html#d0e2225

3 消息实体对象读写

3.1 使用 XML 从 MessageBody 中读写对象

  • 添加 Customer 对象

    • 直接从 samples/jax_rs/basic/src/main/java/demo/jaxrs/server/ 中将 Customer 类拖入项目
    • 检查语法是否有错误
  • 添加服务接口方法:

    @POST
    @Path("/addObj/")
    @Consumes(MediaType.APPLICATION_XML)
    @Produces(MediaType.TEXT_PLAIN)
    public Response addCustomer(Customer customer);
  • 添加实现代码:
    public Response addCustomer(Customer customer) {
        System.out.println("----invoking updateCustomer, Customer name is: " + customer.getName());
        Response r;
        r = Response.ok().build();
        return r;
    }
  • 用 swagger 测试 服务!

  • 如果,返回的也是 Customer 对象,应该如何修改?

3.2 让服务自动选择 JSON 和 XML

  • 添加项目依赖
        
        <dependency>
            <groupId>org.codehaus.jacksongroupId>
            <artifactId>jackson-jaxrsartifactId>
            <version>1.9.13version>
        dependency>
  • 修改服务发布程序,添加代码:
        endpoint.setProviders(Arrays.asList(
                new JacksonJsonProvider(),
                new JAXBElementProvider()
        )); 
  

它为 endpoint 配置了两种读写 body 的方法处理

  • 修改服务接口定义
    @POST
    @Path("/addObj/")
    @Consumes({MediaType.APPLICATION_JSON,MediaType.APPLICATION_XML})
    @Produces({MediaType.APPLICATION_JSON,MediaType.APPLICATION_XML})
    public Customer addCustomer(Customer customer);
  • 运行!

    • 在 swagger-ui 中可以自由选择 JSON XML 格式,结果自动与出入对应
    • 这是满足生产要求的服务

4. 子资源

https://jersey.java.net/documentation/latest/user-guide.html#d0e2495

附件:curl 使用简易指南

使用curl指令測試REST服務 http://ju.outofmemory.cn/entry/84875

你可能感兴趣的:(Java&Spring)