第3章 核心概念 - 3.1 请求
在前面的章节中我们已经感受到了 Blade 的强大和简洁,但是对于详细的 API 还不了解,从本章节开始一起来看看都有哪些好玩的,其实也都是web开发一些常见的概念,如果你是一个老司机一定对这不陌生,只是方法名可能有些变动而已。
Blade 不依赖 Servlet/JSP/Tomcat!!!所以这里面的对象都是属于Blade的,不是Servlet的
当我们编写好应用后从浏览器发送一个请求,这时候会经过 web 服务器 (Blade中是netty实现),然后到核心的调度器(Dispatcher),当请求传递到某个路由的时候我们可以获取到 Request
对象,你在之前看到的位于方法的 Request
是 Blade
帮你注入的,包括 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
表单
<form action="/save" method="post">
<input name="name" type="text" />
<input name="age" type="text" />
</form>
我们在后台获取它的参数
// 下面两行代码是相同的含义
String name = request.query("name").orElse("未知");
String name = request.query("name", "未知");
Optional<Integer> age = request.queryInt("age");
同时 Blade 也提供使用注解的方式将参数注入进来,怎么做呢?
public Response save(@Param String name, @Param Integer age){
// 这样就可以获取到 name 和 age 了
}
对框架熟悉的同学可能也发现了,Query
开头的都是获取表单参数的。有时候有些奇葩的需求,我的表单参数名不叫name,Java
方法的变量却是 name
,怎么办…
haha~ 你可以点开 @Param
这个注解看看:
public @interface Param {
boolean required() default false;
String name() default "";
String defaultValue() default "";
}
哦… 原来长这个样子,假如你的 form 表单中 input name 为 wss_name
对应 Java
方法的变量为 name
这时候框架是匹配不到的,所以应该这么写:
public Response save(@Param(name="wss_name") String name, @Param Integer age){
// 这样就可以获取到 name 和 age 了
}
老哥,学会了吗?至于您喜欢用哪种方式可以自行选择。
但。。。问题又来了,我的表单一堆参数,我想封装一个对象传,你支持么?支持么?支持么?
哥,支持!支持!支持!
来,袖子卷起来,我们先建个实体
public User {
private String name;
private Integer age;
// getter setter 省略
}
然后
public Response save(User user){
// 通过user.getName() user.getAge()
}
嗯,就这么简单。
获取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)
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
的元素,我们上传文件后在后端如何接收并保存起来呢?
Optional<FileItem> img = request.fileItem("img");
if(img.isPresent()){
FileItem fileItem = img.get();
System.out.println("文件名:" + fileItem.name());
System.out.println("文件大小:" + fileItem.length());
System.out.println("文件类型:" + fileItem.contentType());
byte[] data = fileItem.data();
FileOutputStream fos = new FileOutputStream("/data/img/a.jpg");
fos.write(data);
fos.close();
} else {
System.out.println("并没有img这个文件");
}
这里没有进行异常的处理,给出了上传文件的核心代码,没有什么比 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。
获取Cookie信息
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
域获取一个数据,至于这里设置的数据在前端如何使用取决于你的模板引擎是哪个,根据其语法而来,比如默认的模板引擎非常简单,我们举个例子:
request.attribute("name", "blade2.0");
在我们的模板中(存储在/resources/templates
之下的视图文件)
<h1>这是 ${name}</h1>