在所有的 Web 类应用中,参数的绑定都是一个非常重要的话题,本章中,就来看看 Jersey 中的参数绑定方式。
绑定路径参数
在 Jersey 中,使用 @PathParam 完成路径参数绑定:
package com.example.jerseydemo.parameterbinding;
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;
@Path("/pathparam") // 基路径
@Produces(value = MediaType.APPLICATION_JSON)
public class TestService {
/**
* 映射 url中的路径参数
* @param id
* @return
*/
@GET
@Path("/test1/{id}")
public String testPathParam(@PathParam("id") String id){
return id;
}
/**
* 映射多个路径参数
* @param key
* @param value
* @return
*/
@GET
@Path("/test2/{key}/{value}")
public String testPathParam2(@PathParam("key") String key, @PathParam("value") String value){
return key+":"+value;
}
}
映射普通请求参数
在实际开发中,类似对资源的查询等操作,需要通过获取请求中的查询参数内容。Jersey 提供了 @QueryParam 注解完成参数绑定。
package com.example.jerseydemo.parameterbinding;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.QueryParam;
/**
* @author hanliukui
* @Date 2021/4/3 14:43
*/
@Path("/queryparam")
public class QueryParamService {
/**
* 映射 普通参数传参
* @param param1
* @param param2
* @return
*/
@GET
@Path("/test1")
public String queryParam1(@QueryParam("aa") String param1,@QueryParam("bb") String param2 ){
return "param1:"+param1+",param2:"+param2;
}
}
映射表单提交参数
使用表单提交是互联网应用再常见不过的方式,在 SpringMVC 中,提供了各种牛逼的能力来把表单中的数据映射到方法的参数,模型中,但是在这块上,Jersey 同样很强大,但是稍微使用复杂一点。要演示表单提交参数绑定,我们先创建一个简单的 Employee 类:
@Setter
@Getter
@NoArgsConstructor
@AllArgsConstructor
public class Employee {
private Long id;
private String name;
private int age;
}
需求:根据提交的数据创建一个 Employee 对象。
/**
* 映射表单提交参数,要求请求是POST,PUT,并且编码格式必须是x-www-form-urlencoded
*
* @param name
* @param age
* @return
*/
@PUT
@Path("/form")
@Produces(MediaType.APPLICATION_JSON)
public Employee formParam(@FormParam("name") String name, @FormParam("age") int age) {
return new Employee(1L, name, age);
}
普通值绑定
第一种方式,在 Jersey 中,提供了一个 @FormParam 注解来完成表单中内容到参数的绑定(API 文档解释,是绑定一个请求实体中的表单参数到资源方法参数 Binds the value(s) of a form parameter contained within a request entity body to a resource method parameter)。
注意几个点:
1、@FormParam 注解只能接受 x-www-form-urlencoded 编码格式的 form 表单提交,这个是必要条件;
2、@FormParam 注解能够完成的绑定类型有:
- 简单类型;
绑定到一个对象,要求这个对象的类有一个接受单个 String 类型的构造器;
class Employee {
private Long id;
private String name;
private int age;
public Employee() {
}
// 单个 String 类型的构造器
public Employee(String name) {
this.name = name;
}
...
}
绑定到一个对象,要求这个对象的类有一个 valueOf(String) 或者 fromString(String) 的静态的构建方法,比如
public static Employee valueOf(String name){
return new Employee(name);
}
提供一个 ParamConverterProvider(这个后面讲 Provider);
- 可以绑定到一个 List,Set 上面,例如:
@POST
@Path("/hobby")
@Produces(MediaType.APPLICATION_JSON)
public Employee formParam(@FormParam("hobby") Set<String> hobbies) {
System.out.println(hobbies);
return new Employee();
}
那么,使用 POST param/hobby?hobby=java&hobby=haha&hobby=hehe 就可以完成 Set 的绑定(注意表单编码格式一定是 x-www-form-urlencoded)。
另外,@FormParam 可以配合一个 @DefaultValue 标签来设置默认值,简单演示:
@PUT
@Path("/form")
@Produces(MediaType.APPLICATION_JSON)
public Employee formParam(@FormParam("name") String name,
@DefaultValue("18") @FormParam("age") int age) {
return new Employee(1L, name, age);
}
当 @FormParam 绑定失败即可使用 @DefaultValue 设置的值。
绑定到对象
在 SpringMVC 中,我们更常见的是直接把请求参数绑定到一个我们需要的模型或者 VO 中。在 Jersey 中,使用 @FormParam
注解无法完成,可以使用 @BeanParam
和 @FormParam
配合使用:
首先修改 Employee 对象:
@Setter
@Getter
@NoArgsConstructor
@AllArgsConstructor
public class Employee {
private Long id;
@FormParam("name")
private String name;
@FormParam("age")
private int age;
}
注意,我们把 @FormParam
标签移动到了 Employee
的对应属性上。当然在实际开发中,更多应该是在 VO 对象类中;
/**
* 直接映射到模型,要求请求是POST,PUT,并且编码格式必须是x-www-form-urlencoded
*
* @param e
* @return
*/
@POST
@Path("/formpojo")
@Produces(MediaType.APPLICATION_JSON)
public Employee formPojoParam(@BeanParam Employee e) {
e.setId(2L);
return e;
}
然后,再使用 Jersey 提供了 @BeanParam
注解,完成请求参数到自定义模型的绑定。
注意,在自定义模型中,不光可以使用 @FormParam
,可以使用 @XXXParam
,比如前面提到过的 @PathParam
。
直接获取表单内容
前面介绍过使用 @FormParam
和 @BeanParam
来获取表单中的数据,下面再介绍一种通过直接获取表单内容的方式:
/**
* 使用MultivaluedMap直接获取POST表单编码格式必须是x-www-form-urlencoded的表单内容
*
* @param fs
* @return
*/
@POST
@Path("/formui2")
public String formPojoParam(MultivaluedMap<String, String> fs) {
System.out.println(fs);
return "success";
}
那么获取到的 MultivaluedMap
类型中,就包含了表单里面所有的参数内容。
映射请求头参数
从请求头中获取一些参数,比如请求头中自定义的 token 等信息,可以直接使用 Jersey 提供的 @HeaderParam
注解完成:
/**
* 通过@HeaderParam获取请求头内容
*/
@GET
@Path("/head")
public String headParam(@HeaderParam("token") String token) {
System.out.println(token);
return "success";
}
那么在请求的时候,我们可以在头信息中添加:
就可以正常看到后台把 token 绑定到 token 参数中。需要注意的是, @DefaultValue
标签都是可以和这些 @XXXParam
配合使用的,并且也可以添加到需要绑定的模型属性上的。
绑定矩阵参数
矩阵参数听着很奇怪,其实很简单,比如我们在做分页的时候,可以使用类似这样的请求:/resource;pageSize=10;currentPage=2
注意,这个请求并不是普通的参数提交方式,按照普通的方式,应该是:/resource?pageSize=10&tPage=2
注意查看两者的区别。
那么使用矩阵参数有什么好处呢?在 REST 架构中,矩阵参数可以把这些参数一起看做一个资源,意思就是上面的两个连接中,第一个 URI 可以看做第二页,每页 10 条 resource 资源,把这个整体作为一个资源去看待;又比如这样一个资源:/players/ladder;level=king
就可以看成天梯中等级为王者的玩家,把这个概念直接作为一个资源整体看待。
理解了矩阵参数,Jersey 提供了 @MatrixParam
标签来完成矩阵参数的绑定:
/**
* 从请求路径中分离出key=value的值
*
* @param currentPage
* @param pageSize
* @param keyword
* @return
*/
@GET
@Path("/matrix")
public String matrix(@MatrixParam("currentPage") int currentPage, @MatrixParam("pageSize") int pageSize,
@MatrixParam("keyword") String keyword) {
System.out.println("currentPage:" + currentPage);
System.out.println("pageSize:" + pageSize);
System.out.println("keyword:" + keyword);
return "success";
}
那么,当我们做出请求
就可以正确的分别解析出其中的 pageSize,currentPage
和 keyword
参数。但是需要注意一点,Jersey 只能解析出处于最后一个路径中的矩阵参数。
至此,Jersey 提供的最基本的几种请求参数绑定方式介绍完毕,下一结介绍 @Context 注解的使用。