JAX-RS API请求与响应头处理实例解析

JAX-RS API请求与响应头处理实例解析

在JAX-RS API开发中,处理请求头和响应头是一项常见的任务。本文将通过一系列实例,详细解析如何在JAX-RS中访问和设置请求头,以及如何返回响应头。

访问请求头

HttpHeaders示例

我们可以通过HttpHeaders接口访问所有的请求头。使用@Context注解可以注入HttpHeaders的实例:

@Path("/")
public class TestResource {
  @GET
  @Path("test1")
  public String allHeaders(@Context HttpHeaders headers) {
    MultivaluedMap<String, String> rh = headers.getRequestHeaders();
    String str = rh.entrySet()
                   .stream()
                   .map(e -> e.getKey() + " = " + e.getValue())
                   .collect(Collectors.joining("<br/>"));
    return str;
  }
}

要运行示例,可以在项目的pom.xml中配置嵌入式Tomcat:

<plugin>
  <groupId>org.apache.tomcat.maven</groupId>
  <artifactId>tomcat7-maven-plugin</artifactId>
  <version>2.2</version>
  <configuration>
    <path>/</path>
  </configuration>
</plugin>

然后运行命令mvn tomcat7:run启动服务。

HttpHeaders类还提供了许多有用的强类型方法来获取特定的请求头,例如getAcceptableLanguages(), getCookies(), getLength()等。以下是一个获取Accept-Language请求头值的简单示例:

@Path("/")
public class TestResource {
  @GET
  @Path("test2")
  public String acceptableLanguages(@Context HttpHeaders headers) {
    List<Locale> locales = headers.getAcceptableLanguages();
    return locales.stream()
                  .map(l -> l.toString())
                  .collect(Collectors.joining("<br/>"));
  }
}

使用@HeaderParam注解

@HeaderParam注解可以将请求头的值绑定到资源方法的参数上:

@Path("/")
public class TestResource {
  @GET
  @Path("test3")
  public String requestParamTest1(@HeaderParam(HttpHeaders.HOST) String host) {
    return "The request 'host' header value = " + host;
  }
}

自动类型绑定

JAX-RS可以隐式地将请求头字符串绑定到合适的Java类型值上。以下是一些示例:

绑定到Java基本类型

@Path("/")
public class TestResource {
  @GET
  @Path("test4")
  public String requestParamTest2(@HeaderParam("anInt") int anInteger) {
    return "The request header 'anInt' value: " + anInteger;
  }
}

我们可以使用HTTPie工具发送自定义的anInt头:

http --header "anInt:123" http://localhost:8080/test4

绑定到具有String接受构造函数的Java类型

具有String接受构造函数的类型,并且被@HeaderParam注解标记的类型,可以自动使用目标请求头进行初始化。例如java.util.Date

new Date("Fri, 3 March 2017 20:35:00 GMT");
@Path("/")
public class TestResource {
  @GET
  @Path("test5")
  public String requestParamTest3(@HeaderParam("aDate") Date date) {
    return "The request header 'aDate' value: " + date;
  }
}

绑定到具有valueOf(String)工厂方法的类型

具有以下签名的方法的类型T也可以使用:

public static T valueOf(String s) { .. }

Java中有多种类具有此方法,例如Integer.valueOf(..), Long.valueOf(..)等。自定义类型也可以使用。以下示例创建了一个自定义类型来演示用法:

public class DateInfo {
  private Date date;
  public static DateInfo valueOf(String dateStr) {
    if(dateStr==null){
      return null;
    }
    DateInfo dateInfo = new DateInfo();
    dateInfo.date = new Date(dateStr);
    return dateInfo;
  }
  public LocalDateTime asLocalDateTime() {
    return LocalDateTime.ofInstant(date.toInstant(), ZoneId.systemDefault());
  }
  public Date asDate() {
    return date;
  }
}
@Path("/")
public class TestResource {
  @GET
  @Path("test6")
  public String valueOfTest(@HeaderParam("aDate") DateInfo dateInfo) {
    return "The request header 'aDate' converted to LocalDateTime:  " +
            dateInfo.asLocalDateTime();
  }
}

绑定到实现ParamConverter接口的类型

一般来说,实现javax.ws.rs.ext.ParamConverter接口的实现可以绑定任何HTTP消息属性(@HeaderParam, @QueryParam, @PathParam, @MatrixParam等)到相应的合适的Java类型(预定义或用户定义)。以下示例展示了如何直接转换LocalDateTime(与上一个示例相比):

public class MyDateConverter implements ParamConverter<LocalDateTime> {
  @Override
  public LocalDateTime fromString(String value) {
    Date date = new Date(value);
    return LocalDateTime.ofInstant(date.toInstant(), ZoneId.systemDefault());
  }
  @Override
  public String toString(LocalDateTime value) {
    return value.toString();
  }
}

我们还需要实现ParamConverterProvider并用@Provider注解标记,以便我们的自定义转换器可以在部署时被发现和注册。

@Provider
public class MyDateConverterProvider implements ParamConverterProvider {
  @Override
  public <T> ParamConverter<T> getConverter(Class<T> rawType, Type genericType,
                                            Annotation[] annotations) {
    if (rawType == LocalDateTime.class) {
      return (ParamConverter<T>) new MyDateConverter();
    }
    return null;
  }
}

相应的资源方法如下:

@Path("/")
public class TestResource {
  @GET
  @Path("test7")
  public String paramConverterTest(@HeaderParam("aDate") LocalDateTime date) {
    return "The request header 'aDate' converted by MyDateConverter:  " + date;
  }
}

绑定到java.util.Collection

我们可以使用集合(java.util.List, java.util.Set, java.util.SortedSet)作为资源方法参数。集合中的元素可以是我们之前讨论的任何类型。集合实例是只读的。

@Path("/")
public class TestResource {
  @GET
  @Path("test8")
  public String collectionTest(@HeaderParam("myHeader") List<String> list) {
    String rv = "header collection values: \n";
    rv += list.stream()
              .map(Object::toString)
              .collect(Collectors.joining("\n"));
    return rv;
  }
}

返回响应头

需要提供响应附加元数据的方法应该返回Response实例。ResponseBuilder类提供了一种方便的方式来使用构建者模式创建Response实例。以下示例展示了如何使用ResponseBuilder添加响应头:

@Path("/")
public class TestResource {
  @GET
  @Path("test10")
  public Response responseHeaderTest1() {
    Response.ResponseBuilder rb = Response.ok("the test response");
    Response response = rb.header("header1", "value1")
                            .header("header2", "value2")
                            .build();
    return response;
  }
}

使用JAX-RS客户端发送请求头

以下示例展示了如何使用JAX-RS客户端API向资源服务发送请求头。

@Path("/")
public class TestResource {
  @GET
  @Path("test10")
  public Response responseHeaderTest1() {
    Response.ResponseBuilder rb = Response.ok("the test response");
    Response response = rb.header("header1", "value1")
                            .header("header2", "value2")
                            .build();
    return response;
  }
  @GET
  @Path("test11")
  public String clientTest(@Context HttpHeaders headers) {
    MultivaluedMap<String, String> rh = headers.getRequestHeaders();
    String str = rh.entrySet()
                   .stream()
                   .map(e -> e.getKey() + " = " + e.getValue())
                   .collect(Collectors.joining("\n"));
    return str;
  }
}
public class MyClient {
  public static void main(String[] args) {
    Client client = ClientBuilder.newClient();
    WebTarget target = client.target("http://localhost:8080/test11");
    Invocation.Builder builder = target.request();
    String response = builder.header("myHeader", "a")
                             .header("aDateHeader", new Date())
                             .get(String.class);
    System.out.println(response);
    client.close();
  }
}
输出
myheader = [a]
adateheader = [Sun, 19 Mar 2017 17:13:28 GMT]
user-agent = [Jersey/2.25
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

t0_54coder

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值