3.1 请求

在前面的章节中我们已经感受到了 Blade 的强大和简洁,但是对于详细的 API 还不了解,从本章节开始一起来看看都有哪些好玩的,其实也都是web开发一些常见的概念,如果你是一个老司机一定对这不陌生,只是方法名可能有些变动而已。

Blade 不依赖 Servlet/JSP/Tomcat!!!所以这里面的对象都是属于Blade的,不是Servlet的

当我们编写好应用后从浏览器发送一个请求,这时候会经过 web 服务器 (Blade中是netty实现),然后到核心的调度器(Dispatcher),当请求传递到某个路由的时候我们可以获取到 Request 对象,你在之前看到的位于方法的 RequestBlade 帮你注入的,包括 Response, Session 都是可以的。

我们获取到请求对象后就可以进行很多的操作了,比如获取表单的参数,读取 Request Body,获得上传的文件字节,读取Cookie等等。下面列举几个常用的功能。

获取表单参数

先看看Request提供的操作表单参数的API

  • Optional<String> query(String name)
  • Optional<Integer> queryInt(String name)
  • Optional<Long> queryLong(String name)
  • Optional<Double> queryDouble(String name)
  • String query(String name, String defaultValue)
  • int queryInt(String name, int defaultValue)
  • long queryLong(String name, long defaultValue)
  • double queryDouble(String name, double defaultValue)

这几组API非常的清晰明了,因为使用了Java8,有一组里面用了 Optional 的写法,为了让大家拿不到值的时候进行判断或其他处理,其实和带 defaultValue 的API是差不多的,因为 Optional 提供一个 orElse 方法让你设置默认值。怎么用呢?其实只要API设计的到位大家十有八九都可以猜到怎么用的,我能告诉你的是这组API获取的是Form表单的参数。举个栗子吧:

假设有一个 form 表单

  1. <form action="/save" method="post">
  2. <input name="name" type="text" />
  3. <input name="age" type="text" />
  4. </form>

我们在后台获取它的参数

  1. // 下面两行代码是相同的含义
  2. String name = request.query("name").orElse("未知");
  3. String name = request.query("name", "未知");
  4. Optional<Integer> age = request.queryInt("age");

同时 Blade 也提供使用注解的方式将参数注入进来,怎么做呢?

  1. public Response save(@Param String name, @Param Integer age){
  2. // 这样就可以获取到 name 和 age 了
  3. }

对框架熟悉的同学可能也发现了,Query 开头的都是获取表单参数的。有时候有些奇葩的需求,我的表单参数名不叫name,Java 方法的变量却是 name,怎么办…

haha~ 你可以点开 @Param 这个注解看看:

  1. public @interface Param {
  2. boolean required() default false;
  3. String name() default "";
  4. String defaultValue() default "";
  5. }

哦… 原来长这个样子,假如你的 form 表单中 input name 为 wss_name 对应 Java 方法的变量为 name 这时候框架是匹配不到的,所以应该这么写:

  1. public Response save(@Param(name="wss_name") String name, @Param Integer age){
  2. // 这样就可以获取到 name 和 age 了
  3. }

老哥,学会了吗?至于您喜欢用哪种方式可以自行选择。

但。。。问题又来了,我的表单一堆参数,我想封装一个对象传,你支持么?支持么?支持么?

哥,支持!支持!支持!

来,袖子卷起来,我们先建个实体

  1. public User {
  2. private String name;
  3. private Integer age;
  4. // getter setter 省略
  5. }

然后

  1. public Response save(User user){
  2. // 通过user.getName() user.getAge()
  3. }

嗯,就这么简单。

获取URL Restful Path参数

我们经常也会用到 REST 接口,一般它的URL形如:http://www.exmaple.com/users/128

这时候我们在 Blade 中定义的路由 Path/users/:id,如何获取这个 id 呢,下面的API可以帮到你

  • String pathString(String name)
  • String pathInt(String name)
  • String pathLong(String name)
  1. Integer userId = request.pathInt("id");

这样就可以获取到 userId,其他变量的获取方式相应你闭着眼睛都可以猜到。

获取表单文件

先看看API

  • Optional<FileItem> fileItem(String name)
  • Map<String, FileItem> fileItems()

很简单,给我们提供了按名称查找 FileItem 和一个 fileItems() 方法,后面的应该是以文件名为 key 的一个 map。

那么怎么用呢?假设 form 中有一个 input 类型为 file, name 为 img 的元素,我们上传文件后在后端如何接收并保存起来呢?

  1. Optional<FileItem> img = request.fileItem("img");
  2. if(img.isPresent()){
  3. FileItem fileItem = img.get();
  4. System.out.println("文件名:" + fileItem.name());
  5. System.out.println("文件大小:" + fileItem.length());
  6. System.out.println("文件类型:" + fileItem.contentType());
  7. byte[] data = fileItem.data();
  8. FileOutputStream fos = new FileOutputStream("/data/img/a.jpg");
  9. fos.write(data);
  10. fos.close();
  11. } else {
  12. System.out.println("并没有img这个文件");
  13. }

这里没有进行异常的处理,给出了上传文件的核心代码,没有什么比 show code 来的更实际了。

获取header信息

依然看API,虽然我一直在重复看API,因为框架编写的API就是为了给用户提供便捷。

  • Map<String, String> headers()
  • String header(String name)
  • String header(String name, String defaultValue)
  • boolean isIE()
  • boolean isAjax()
  • String contentType()
  • String userAgent()

上面的API除了给出获取 header 的方法,也提供了常用的几个附件方法,用于获取是否是IE浏览器、是否是Ajax请求、ContentType以及UserAgent。

  • Map<String, String> cookies()
  • Optional<Cookie> cookieRaw(String name)
  • String cookie(String name, String defaultValue)

这里的几个方法介绍一下,第一个是获取所有的Cookie,map的key是cookie名,value是cookie值;第二个方法根据名称获取cookie,这里可以获取到cookie的详细信息,包括path、有效期等;最后一个方法根据名称获取cookie,获取不到则设置一个默认值。

向 Request 域设置数据

很多时候我们都会用模板引擎,即便你没用过至少也知道JSP,我们会在 Request 作用域中设置一些数据,然后在模板中获取。在 Blade 中也是如此,API也很简单。

  • attribute(String name, Object value)
  • T attribute(String name)

这里第一个方法是像 Request 域设置一个数据,第二个方法从 Request 域获取一个数据,至于这里设置的数据在前端如何使用取决于你的模板引擎是哪个,根据其语法而来,比如默认的模板引擎非常简单,我们举个例子:

  1. request.attribute("name", "blade2.0");

在我们的模板中(存储在/resources/templates之下的视图文件)

  1. <h1>这是 ${name}</h1>