Scalatra in Action 3. 你要去哪里?
路由概览
之前我们有提到,Scalatra的核心,就是处理http请求,这里需要仔细弄明白请求是怎么被处理的。
▲ 图片来源:scalatra in action
Scalatra的路由 由三部分构成。
- http method , http只支持8种方法,如下表所示
- route matcher, 组成路径表达式的路由匹配灵活多变,下面会详细说明
- action, 该部分代码块表示执行到相应路由的情况下该执行的操作
CRUD code boy
http method
http协议不关心数据是存储在关系型数据库的表中,还是存放在MongoDB的文件里,又或者是其他的数据存储实现里,我们在Scalatra的服务中谈论CRUD时,指的是资源。
GET
GET是最常见的http操作,当我们在地址栏键入网址时,按下回车,其实这时GET请求就已经被发送出去了
1 | // fetching a artist with GET method |
GET适用于以下几个场景
- 只读操作
- 请求可以重复提交,
比如我用F5一直刷新最新的新闻 - 回应为标签或者搜索结果时
POST
WEB表单的默认操作是POST,但是POST能做的事不止这一个,POST可以处理json,xml,图片,文件等各种资源。
1 | // adding a new artist with post |
POST的典型操作:解析请求的正文(body),在服务器上创建一个新的资源并返回它的指针。
POST适用于以下几个场景:
- 创建操作
- 为创建的实体建立url
- 非幂等的写操作
PUT
PUT和POST最相似,PUT的正文中修改特定位置的资源
1 | class RecordStore extends ScalatraServlet { |
关于POST和PUT的区别,可以参考这里
简单来说PUT执行的是幂等的操作。
PUT适用于以下几个场景:
- 更新操作
- 创建操作(当客户端完全了解资源的URL时)
DELETE
顾名思义,就是删除
1 | class RecordStore extends ScalatraServlet { |
以上是比较常见的http method.
匹配
之前的例子中,我们其实已经接触过了静态路径和参数变量
- get(“/artists”)
- get(“/artists/:name”)
在静态路径中,部分特殊字符需要经过URL编码,下面是一个例子。
在参数变量中,我们可以这样获取
1 | /articles/52?foo=uno&bar=dos&baz=three&foo=anotherfoo |
参见官方文档
可选参数
在匹配过程中,?
代表在其之前的字符或者参数变量是可选的
1 | get("/artists/?"){ |
上边的/artists/?
会匹配以下两个请求
1 | class RecordStore extends ScalatraServlet { |
以上这段代码可以匹配如下请求
URL | Format param |
---|---|
http://localhost:8080/artists/Otis_Redding/info | undefined |
http://localhost:8080/artists/Otis_Redding/info.json | “json” |
http://localhost:8080/artists/Otis_Redding/info.xml | “xml” |
http://localhost:8080/artists/Otis_Redding/info. | undefined |
http://localhost:8080/artists/Otis_Redding/infojson | “json” |
通配符
通配符为”*”,下面是一个简单的例子,其中splat
是一个保留字,用来匹配通配符。
1 | get("/say/*/to/*") { |
正则
如果你对正则有一定了解的话,那么看了之前的?
和*
,你一定会联想到元字符,没错,Scalatra当然支持正则匹配
Some people, when confronted with a problem, think “I know, I’ll use regular
expressions.” Now they have two problems.
—Jamie Zawinski
上次我看到这个笑话的时候说的是多线程
1 | get("""^/f(.*)/b(.*)""".r) { |
我们来详细讲解下"""^/f(.*)/b(.*)""".r
这段和天书一样的代码
如果把它看成"""<pattern>""".r
,<pattern>
为^\/f(.*)/b(.*)
外层三引号加点r说明内部的表达式是正则格式,内部正则则是说明需要匹配的文本
^
表示匹配 开始
这里有两个括号,是用来捕获的(.*)
代表捕获任意字符(这里当然不包括/
)
如果你想了解更多,推荐阅读精通正则表达式
这里还有一个点要注意,captures
是Scalatra的保留字,类似于for
在各种语言中的地位,是有其特殊含义的。
mutiParams(”captures“)的作用就是获取所有被捕获的参数。
Scalatra将路径表达式编译成正则表达式,下面是部分映射关系表格
路径表达式 | 等效正则 |
---|---|
:param | ([/*#?]+) |
? | ? |
* | (.*?) |
() | \(\) |
布尔表达式
和路径表达式、正则表达式不同,布尔表达式不能提取出URL中的某个字段,它的作用更像是一个门卫,判断哪些请求可以通过而哪些请求不可以通过。
1 | class RecordStore extends ScalatraServlet { |
匹配顺序
自底向上,首次匹配,一图流
1 | class MyScalatraServlet extends ScalatraServlet { |
其他详细的使用,参考官方文档
小结
了解路由匹配的基本规则
版权声明:
除另有声明外,本博客文章均采用 知识共享(Creative Commons) 署名-非商业性使用-相同方式共享 3.0 中国大陆许可协议 进行许可。
分享