目录

Restful Web Services(JAX-RS)

Restful的WebService说明

之前的章节都是基于SOAP的,接下来介绍基于Restful风格的WebService。

Rest风格介绍

http://img.cana.space/picStore/20201109223656.png

常见状态码

20201109223955

503网站不存在,服务无效,可以试试访问被墙掉的网站。

JAX-RS

JAX-RS = Java Architecture For Restful Web Services(JSR311)

JAX-RS是JavaEE6引入的一个新规范。是一个Java编程语言的应用程序接口,支持按照表述性状态转移(REST)架构风格创建WEB服务。

JAX-RS使用了Java SE5引入的Java注解来简化Web服务的客户端和服务端开发和部署。

JAX-RS提供了一些注解标注资源类和POJO,封装为Web资源,如下:

http://img.cana.space/picStore/20201109224819.png

基于JAX-RS实现的框架有Jersey,RESTEasy等。

这两个框架创建的应用可以很方便地部署到Servlet容器中。

示例程序

  1. 新建springboot工程,引入相关jar包

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    
    <?xml version="1.0" encoding="UTF-8"?>
    <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.0</modelVersion>
       
        <parent>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-parent</artifactId>
            <version>2.0.1.RELEASE</version>
            <relativePath/>
        </parent>
       
        <groupId>org.eh</groupId>
        <artifactId>springboot-cxf</artifactId>
        <version>1.0-SNAPSHOT</version>
       
        <properties>
            <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
            <maven.compiler.source>1.8</maven.compiler.source>
            <maven.compiler.target>1.8</maven.compiler.target>
        </properties>
       
        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter</artifactId>
            </dependency>
            <!-- CXF webservice -->
            <dependency>
                <groupId>org.apache.cxf</groupId>
                <artifactId>cxf-spring-boot-starter-jaxrs</artifactId>
                <version>3.3.4</version>
            </dependency>
            <!--lombok-->
            <dependency>
                <groupId>org.projectlombok</groupId>
                <artifactId>lombok</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-configuration-processor</artifactId>
            </dependency>
        </dependencies>
       
    </project>
    
  2. 建Book.java的entity并添加注解@XmlRootElement

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    
    package com.eh.cxf;
       
    import lombok.AllArgsConstructor;
    import lombok.Data;
    import lombok.NoArgsConstructor;
       
    import javax.xml.bind.annotation.XmlRootElement;
       
       
    @XmlRootElement
    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    public class Book {
        private long id;
        private String bookName;
        private double price;
    }
    
  3. 建HelloService接口并添加Restful风格相关的注释

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    
    package com.eh.cxf;
       
    import javax.ws.rs.*;
    import javax.ws.rs.core.MediaType;
       
    @Path("/book")
    public interface HelloService {
       
        @GET
        @Path("/{id}")
        @Produces(MediaType.APPLICATION_XML) // 表示输出为xml
        @Consumes(MediaType.WILDCARD) // 表示输入为 */*
        Book sayHello(@PathParam("id") Integer id);
    }
    
  4. 编写HelloServiceImpl实现类

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    
    package com.eh.cxf;
       
    import org.springframework.stereotype.Service;
       
    @Service
    public class HelloServiceImpl implements HelloService {
       
        @Override
        public Book sayHello(Integer id) {
            System.out.println("@PathParam get id:" + id);
            Book book = new Book(100L, "水浒传", 25.5);
            return book;
        }
    }
    
  5. yml,配置cxf路径和包扫描

    1
    2
    3
    4
    5
    6
    7
    8
    9
    
    server:
      port: 9999
    cxf:
      path: /hello
      servlet.init:
        service-list-path: /info
      jaxrs:
        # 配置扫描服务,必须要设置为true,否则找不到要暴露的服务
        component-scan: true
    
  6. 启动主程序

    启动后注意目前用rest而不是soap,所以没有WSDL的描述了。

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    
    package com.eh;
       
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
       
    @SpringBootApplication
    public class SpringBootCxfApplication {
        public static void main(String[] args) {
            SpringApplication.run(SpringBootCxfApplication.class, args);
        }
    }
    
  7. 浏览器地址栏里面按照Restful风格的路径进行访问和测试

    http://localhost:9999/hello/book/1

    http://img.cana.space/picStore/20201109235215.png

服务端返回json

  1. 此时实体类不需要再加注解@XmlRootElement

  2. 引入jaxrs转json工具

    1
    2
    3
    4
    5
    6
    
    <!--jaxrs转json工具-->
    <dependency>
        <groupId>com.fasterxml.jackson.jaxrs</groupId>
        <artifactId>jackson-jaxrs-json-provider</artifactId>
        <version>2.8.5</version>
    </dependency>
    
  3. jaxb默认支持xml格式, 而实现对象转json是需要额外的转换器的,往容器中注入MessageBodyReader,这里使用实现类JacksonJaxbJsonProvider,这样cxf在将对象转为json时会自动使用这个工具对象

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    
    package com.eh;
       
    import com.fasterxml.jackson.jaxrs.json.JacksonJaxbJsonProvider;
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.context.annotation.Bean;
       
    @SpringBootApplication
    public class SpringBootCxfApplication {
        public static void main(String[] args) {
            SpringApplication.run(SpringBootCxfApplication.class, args);
        }
       
        // 配置一个对象与json转换的工具
        @Bean
        public JacksonJaxbJsonProvider jacksonJaxbJsonProvider() {
            return new JacksonJaxbJsonProvider();
        }
    }
    
  4. 接口上添加输出类型为application/json的注解

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    
    package com.eh.cxf;
       
    import javax.ws.rs.*;
    import javax.ws.rs.core.MediaType;
       
    @Path("/book")
    public interface HelloService {
       
        @GET
        @Path("/{id}")
        @Produces(MediaType.APPLICATION_JSON) // 表示输出为json
        @Consumes(MediaType.WILDCARD) // 表示输入为 */*
        Book sayHello(@PathParam("id") Integer id);
    }
    
  5. 验证

    http://img.cana.space/picStore/20201110000219.png

使用HttpClient进行访问

HTTP 协议可能是现在 Internet 上使用得最多、最重要的协议了,越来越多的 Java 应用程序需要直接通过 HTTP 协议来访问网络资源。虽然在 JDK 的 java net包中已经提供了访问 HTTP 协议的基本功能,但是对于大部分应用程序来说,JDK 库本身提供的功能还不够丰富和灵活。HttpClient 是 Apache Jakarta Common 下的子项目,用来提供高效的、最新的、功能丰富的支持 HTTP 协议的客户端编程工具包,并且它支持 HTTP 协议最新的版本和建议。

使用步骤

  1. 引入httpclient jar包

    1
    2
    3
    4
    5
    6
    
    <!-- https://mvnrepository.com/artifact/org.apache.httpcomponents/httpclient -->
    <dependency>
        <groupId>org.apache.httpcomponents</groupId>
        <artifactId>httpclient</artifactId>
        <version>4.5.12</version>
    </dependency>
    
  2. 使用

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    
    package com.eh.cxf;
       
    import lombok.SneakyThrows;
    import org.apache.http.HttpResponse;
    import org.apache.http.client.HttpClient;
    import org.apache.http.client.methods.HttpGet;
    import org.apache.http.impl.client.HttpClients;
    import org.apache.http.util.EntityUtils;
       
    public class ClientTest {
        @SneakyThrows
        public static void main(String[] args) {
            // 创建HttpClient实例
            HttpClient httpClient = HttpClients.custom().build();
            // 调用
            HttpResponse httpResponse = httpClient.execute(new HttpGet("http://localhost:9999/hello/book/1"));
            // 将InputStream转换成String输出
            System.out.println(EntityUtils.toString(httpResponse.getEntity()));
        }
    }
    

完整示例地址