2.Play Framework HTTP routing Http路由

内置HTTP路由器

router是用来将请求的http request 转到对应的Action处理的一个组件
一个http请求在mvc框架中被当做是一个事件,这个事件包含两个组成部分:
1、请求的url+参数
2、请求的类型post还是get
路由的跳转规则实在conf/routes文件中配置

##依赖注入

Play的路由构造器会创建一个构造器类,这个类通过 @Inject 在构造器中接受一个controller的实例,这说明我们既可以通过依赖注入实例化,也可以通过构造函数手动的实例化
Play还有一个遗留的静态路由生成器,他和被声明的controller共同工作,不过这是不推荐的方式,这个方式不但打破了封装,而且也不被一些新的Play的接口
如果你需要使用静态路由生成器,你可以通过在build.sbt配置文件添加以下配置来进行转换

routesGenerator := StaticRoutesGenerator

Play默认的认为你使用的注解的方式创建controller 如果不想使用这个模式,你可以去使用静态的路由生成器 ,或者通过用@符号预先声明在调用controller的地方,或者将每个controller声明为一个object(静态对象)而不是一个class

路由配置文件的配置方法

conf/routes是用于配置路由的文件,这个文件中罗列了所有在应用中被用到的路由。每一个路由由一个http请求方式和一个http请求的url构成,两者通过声明关联到对应的Action生成器上

# Display a client.(可以用#来编辑注释)

    GET   /clients/:id          controllers.Clients.show(id: Long)

你也可以使用->来将路由指定到其他的配置文件

->      /api                        api.MyRouter

也可以在路由配置前用一个+开头,这可以改变以确定的Play组件的行为,这面这就是使用“nocsrf”来修饰,来绕过 CSRF filter

+ nocsrf
POST  /api/new              controllers.Api.newThing

Http请求

Play可以支持所有的请求类型:(GET, PATCH, POST, PUT, DELETE, HEAD)

URI部分

URI部分指定了路由请求的路径,而且可以动态的指定。而且支持正则表达式

静态的指定:

GET   /clients/all          controllers.Clients.list()

动态的指定:

GET   /clients/:id          controllers.Clients.show(id: Long)

动态部分使用多“/”
如果在动态部分去捕获多个urI路径(通过斜杠分开),可以使用*id,也就是使用正则表达式的通配符模式

GET   /files/*name          controllers.Application.download(name)

在上面的配置中,访问 /files/myproject/test.png ,在后面的controller里接收到的参数也就是/myproject/test.png
但是动态的路由跨越多个“/”,既不是由路由解码的也不是由反向路由编码的,校验所有用户输入的uri段是你的责任,反向路由只是做一些简单的串联工作,所以你要确保result的值是可靠的正确的,而不是像有多个前置的斜杠或者非assic字符
动态部分使用正则表达式

GET   /items/$id<[0-9]+>    controllers.Items.show(id: Long)

声明Action生成器方法

在配置的最后一部分是一个声明,这个部分必须定义一个返回 play.api.mvc.Action值的有效方法,这个方法通常是一个controller action
如果声明的方法没有定义任何参数,那只需要给一个完整的方法名就可以了

GET   /                     controllers.Application.homePage()

如果你的action定义了一些参数,所有的参数都可以通过在请求url中抽出来去或者从查询字符串中获取
从请求uri中获取:

   # Extract the page parameter from the path.
    GET   /:page                controllers.Application.show(page)
    # Extract the page parameter from the query string.
    GET   /                     controllers.Application.show(page)

与之对应的show方法的定义

def show(page: String) = Action {
  loadContentFromDatabase(page).map { htmlContent =>
    Ok(htmlContent).as("text/html")
  }.getOrElse(NotFound)
}

如果参数是String的时候,参数的类型是可选的,如果你想去指定键入的参数为指定的Scala类型,你可以明确的在action声明处指定参数的类型

GET   /clients/:id          controllers.Clients.show(id: Long)

可以在路由中设置默认的参数值

# Extract the page parameter from the path, or fix the value for /
GET   /                     controllers.Application.show(page = "home")
GET   /:page                controllers.Application.show(page)

但是上面的写法比较麻烦,我们可以用一条记录同时匹配有默认值和没有默认值的情况,也就是如果没有键入值的话就使用默认值,如果有键入值的话就使用键入值

# Pagination links, like /clients?page=3
GET   /clients              controllers.Clients.list(page: Int ?= 1)

我们也可以使用一个可选值的option去传参数,对参数没有限制

# The version parameter is optional. E.g. /api/list-all?version=3.0
GET   /api/list-all         controllers.Api.list(version: Option[String]

路由的优先级

很多时候我们在同意请求的时候会匹配到多个路由,这个时候会默认根据声明顺序选择第一个配置的路由

反向路由

路由生成器还可用于从Scala调用中生成URL。这样就可以将所有URI模式集中在一个配置文件中,这样您在重构应用程序时就会更加自信。
对于路径文件中使用的每个控制器,路由器将在routes包中生成一个“反向控制器” ,具有相同的操作方法,具有相同的签名,但返回一个 play.api.mvc.Call而不是a play.api.mvc.Action。
在play.api.mvc.Call定义了一个HTTP调用,并同时提供了HTTP方法和URI。
例如,如果您创建一个控制器,如:

package controllers

import javax.inject.Inject

import play.api._
import play.api.mvc._

class Application @Inject()(cc:ControllerComponents) extends AbstractController(cc)  {

  def hello(name: String) = Action {
    Ok("Hello " + name + "!")
  }

}

如果您将其映射到conf/routes文件中:

# Hello action

    GET   /hello/:name          controllers.Application.hello(name)

然后,您可以hello使用controllers.routes.Application反向控制器将URL反转到操作方法:

// Redirect to /hello/Bob
def helloBob = Action {
  Redirect(routes.Application.hello("Bob"))
}

注意:routes每个控制器包都有一个子包。因此,操作controllers.Application.hello可以通过反转controllers.routes.Application.hello(只要在路径文件中没有其他路径发生匹配生成的路径)。
反向操作方法非常简单:它接受您的参数并将它们替换回路径模式。在路径段(:foo)的情况下,在替换完成之前对值进行编码。对于正则表达式和通配符模式,字符串将以原始形式替换,因为该值可能跨越多个段。确保在将它们传递到反向路径时根据需要转义这些组件,并避免传递未经验证的用户输入。

相对路线

有些情况下返回相对路线而不是绝对路线可能是有用的。返回的路由play.mvc.Call始终是绝对的(它们带有一个 /),当HTTP代理,负载平衡器和API网关重写对Web应用程序的请求时,这可能会导致问题。使用相对路线有用的一些示例包括:
在Web网关后面托管应用程序,该应用程序在所有路径前面添加除conf/routes文件中配置的内容之外的其他内容,并将应用程序置于不期望的路径上。
在动态呈现样式表时,您需要资产链接是相对的,因为它们可能最终由CDN从不同的URL提供服务。
为了能够生成相对路线,您需要知道相对于(起始路线)的目标路线是什么。可以从当前检索起始路线RequestHeader。因此,要生成相对路径,您需要将当前RequestHeader路径或起始路径作为String参数传递。
例如,给定的控制器端点如:

package controllers

import javax.inject._
import play.api.mvc._

@Singleton
class Relative @Inject()(cc: ControllerComponents) extends AbstractController(cc) {

  def helloview() = Action { implicit request =>
    Ok(views.html.hello("Bob"))
  }

  def hello(name: String) = Action {
    Ok(s"Hello $name!")
  }
}

注意:当前请求通过声明来隐式传递给视图模板implicit request
如果您将其映射到conf/routes文件中:

GET     /foo/bar/hello              controllers.Relative.helloview
GET     /hello/:name                controllers.Relative.hello(name)

然后,您可以像以前一样使用反向路由器定义相对路由,并包括对relative:

@(name: String)(implicit request: RequestHeader)

<h1>Hello @name</h1>

<a href="@routes.Relative.hello(name)">Absolute Link</a>
<a href="@routes.Relative.hello(name).relative">Relative Link</a>

注意:该Request从控制器传递被转换为RequestHeader与被标记implicit在视图参数。然后它会隐式传递给调用relative
请求/foo/bar/hello生成的HTML时,如下所示:

<!DOCTYPE html>
<html lang="en">
    <head>
        <title>Bob</title>
    </head>
    <body>
      <a href="/hello/Bob">Absolute Link</a>
      <a href="../../hello/Bob">Relative Link</a>
    </body>
</html>

默认控制器

Play包括一个Default控制器,它提供了一些有用的动作。这些可以直接从routes文件中调用:

# Redirects to https://www.playframework.com/ with 303 See Other
GET   /about      controllers.Default.redirect(to = "https://www.playframework.com/")

# Responds with 404 Not Found
GET   /orders     controllers.Default.notFound

# Responds with 500 Internal Server Error
GET   /clients    controllers.Default.error

# Responds with 501 Not Implemented
GET   /posts      controllers.Default.todo

在此示例中,GET /about重定向到外部网站,但也可以重定向到另一个操作(例如/posts在上面的示例中)。
自定义路由
Play提供了一个用于定义嵌入式路由器的DSL,称为字符串插入路由DSL,或简称为sird。此DSL有许多用途,包括嵌入轻量级Play服务器,为常规Play应用程序提供自定义或更高级的路由功能,以及模拟REST服务以进行测试。
请参阅字符串插值路由DSL

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值