请求参数出现的地方将变成控制器的方法的输入参数,即每个 Java 参数映射着 HTTP 请求参数;然后控制器方法执行后返回的结果就是响应客户端的结果。
原生请求响应对象
原生对象指的是 HttpServletRequest、HttpServletResponse 这类由 Servlet 提供的接口。只要方法定义了这些接口的参数,即可送入,不管参数名具体如何。请看下面的例子。
@GET
public String get(HttpServletRequest request, HttpServletResponse response) {
HttpSession session = request.getSession();// 原生方法
ServletContext context = request.getServletContext();
return "/my.jsp";
}
为满足其他额外的需求有必要实现新的实用工具函数。我们封装在继承的 MvcRequest、MvcOutput 对象中。
获取查询参数
查询参数(QueryString)指的URL上的参数,类似请求 http://localhost:8080/news/getDetail?pageNo=1&limit=5
的地址中,参数部分指的是问号后面的部分,它是键对值结构,多个参数通过&
分割,例如参数 pageN o的值为1,参数 limit 的值为 5。如果要获取查询参数及其值需要用到@QueryParam
注解,它会将请求参数绑定到方法参数。
@GET
@Path("getDetail")
public String gotoJSP(@QueryParam("pageNo")String pageNo, @QueryParam("limit")String limit) {
return "html:: pageNo= " + pageNo;
}
默认值和非空的参数
在配置请求参数时可以指定丰富的选项,例如是否非空、参数的默认值。通过指定@DefaultValue
注解定义默认值,表示当客户端传过来的参数值不存在或者为空时就会采用这个默认值,如下例子中设置了默认 name 值为 Jack。
@POST
@Path("testDefault")
public String testDefault(@DefaultValue("Jack") @QueryParam("name") String name) {
return "json::{\"name\":\"" + name + "\"}";
}
如果想把参数设置为必填的,可声明一个@NotNull
的注解。下面例子演示了非空的判断,若 name 为空会打印相关错误信息,如“java.lang.NullPointerException: 客户端缺少提交的参数 name”
。
@POST
@Path("testDefault")
public String testDefault(@NotNull @QueryParam("name")String name, @QueryParam("age") int age) {
return "json::{\"name\":\"" + name + "\"}";
}
@DefaultValue和@NotNull适用于各种HTTP方法注解(@GET/@POST
等)。
自动类型转换
HTTP 请求过来都是 String,如果可根据方法参数类型作适当的转换,那样就省去了开发者手动转换的麻烦。如下例增加的获取年龄的参数,最终希望获取的是一个 int 类型的值,只要我们声明方法是声明 int age 而不是 String age,那么框架就会自动帮助我们尽量地尝试转换,当然输入如“20A”那样含有字符串的转换,Java 肯定抛出不能转换的异常。
@POST
@Path("testDefault")
public String testDefault(@DefaultValue("Jack") @QueryParam("name") String name, @QueryParam("age") int age) {
return "json::{\"age\":\"" + age + "\"}";
}
当前支持的输入目标类型有 String、int/Integer、long/Long、boolean/Boolean。具体对应转换后的Java类型如表格 4.3下所示。
请求路经获取参数
为了达到 RESTful 风格的控制器这个目标,MVC 允许请求路径中包含一个占位符,占位符名称需要用一对尖括号{id}
括起来。在客户的请求资源时,请求路径的其它部分还是用来匹配资源路径,而占位符部分则直接用来传输参数值。下面就是通过占位符的方式实现路径中传递参数值:
@GET
@Path("getUserDetailInfo/{id}")
public String getUserDetailInfo(@PathParam("id")long userId) {
return "userInfo";
}
从@Path
和@PathParam
可以看出,{id}
的值会传递到方法的userId
参数中。比如按照上面的配置,如果我们的请求是/getUserDetailInfo/12345
,则 123456 便会传入变成 userId 的值。需要注意的是,当前 id 的值只能转换为数字类型的(int/long)。
处理表单数据(转换为 Map 或 Bean)
表单都是以 POST 方式提交的,所以这个控制器对应@POST
注解,执行下面几种方法接收表单数据。
@POST
@Path("/map")
public String map(Map<String, Object> map) { // 使用Map装载请求数据
int age = (int)map.get("age");//
return "html::年龄是: " + map.get("age");
}
使用 Map 装载请求数据的同时还尝试转换字符串为真实值的类型,所谓真实类似是根据字符串尝试转化为 Java 各种数据类型,最后保存在 Map 对象<String, Object>
中(其中 String 是参数名,Object 是参数值)。
除了 Map 类型的数据对象,很多时候使用 Bean 装载请求数据,能不能直接从请求数据自动转为 Bean 呢?答案是肯定的。如下例bean()
方法还有一个含有 User 对象的参数,这个 User 对象中含有 name、age、password 属性,MVC会根据名称从请求中解析相同名称参数并赋值到对象属性中,组装好一个实体。
@POST
@Path("/bean")
public String bean(User user) {
System.out.println(user .getName());
return "html::" + user.getName();
}
注意 Bean 必须是 BaseModel 的子类,因为它是判断 Object 是否为 Bean 的一个必要条件。