Play Framework Web开发教程(30): 使用静态资源

从Web应用中页面上显示的不全都是需要动态生成的,通常的Web应用也包含一些静态文件:比如图像,JavaScript文件,CSS文件等。Play支持这些静态资源,方法和前面生成动态HTTP响应类型,也是通过路由配置,把HTTP请求映射到一个Controller动作。
使用缺省配置
大部分情况,你想在Web应用中使用一些静态文件,此时缺省的配置就足够了。此时,你需要把这些文件和目录放在Web应用的public目录下,而使用URL路径/assets来访问它们,后面的路径为相对于public的路径。
比如,你的Play应用使用了一个图标,存放在public/images/favicon.png, 你可以使用http://localhost:9000/assets/images/favicon.png 来访问这个图片:

<link href="/assets/images/favicon.png" rel="shortcut icon" type="image/png">

同样的,缺省你可以把javascripts文件和CSS 文件分别放在public/javascripts和public/sytlesheets目录下。

你可以查看一下conf/routes文件,缺省的HTTP路由配置,定义了如何访问静态资源:

GET /assets/*file controllers.Assets.at(path="/public", file)

这条规则,表明 HTTP GET请求 /assets/时映射到Controllers.Assets.at方法,该方法使用两个参数,告诉该action方法在什么地方查找所需文件。缺省使用public路径,如果你需要使用其它目录存放不同类型的资源,可以定义自己的路由规则,比如:

GET /images/*file controllers.Assets.at(path="/public/images", file)
GET /styles/*file controllers.Assets.at(path="/public/styles", file)

使用assets逆向路由
之前我们介绍了使用逆向路由来避免hardocded的URL,因为Assets.at也是一个普通的Action方法,因此你可以使用assets逆向路由,例如:

<link href="@routes.Assets.at("images/favicon.png")"
rel="shortcut icon" type="image/png">

缓存和ETag
除了逆向路由的优点,使用asset控制器的另外一个优点是内置的缓存支持以及和Http Entity Tag(Etag)的支持。 从而允许客户端根据需要是否要从服务器请求资源还是可以使用Cached中的文件。
比如,如果我们发送一个请求网站的图标,assets控制器计算Etag的值,然后在HTTP返回的响应消息头添加如下:
Etag: 978b71a4b1fef4051091b31e22b75321c7ff0541

ETag 的值为资源文件名和修改时间的一个Hash值。一但获得了这个ETag值,客户端,可以发出一个条件请求,表示只有在资源在上次请求后有变化时再给我,它可以在请求中添加消息头:

If-None-Match: 978b71a4b1fef4051091b31e22b75321c7ff0541

如果Play assets控制器计算出同样的Hash值,就可以通知客户端,不需要重新下载,可以使用缓存中的拷贝:

HTTP/1.1 304 Not Modified
Content-Length: 0

使用gzip 压缩资源
网页加载的速度至关重要,HTTP压缩是Web服务器和客户端解决网页大小的一个重要功能。使用gzip可以大大缩小大文本文件(比如JavaScript等)。
它的工作流程是:首先浏览器(客户端)告诉服务器,它可以接受压缩过的资源,这可以通过在请求消息头中添加:
Accept-Encoding:gzip
来告知服务器,它支持的压缩方法,服务器由此可以发送一个压缩过的资源,而不是原来未经处理的资源。同时告诉浏览器压缩的方法:
Content-Encoding: gzip
对于Play应用,这部分处理是内置的,不需要程序员做特别处理,如果浏览器支持压缩,Play应用自动压缩资源然后发给浏览器。这种情况发生在下面条件为真时:

  • Play运行在产品模式(Prod 模式),在开发环境中,压缩不是期望的结果。
  • Play接受的请求被映射到Asset控制器。
  • HTTP请求消息头包含有Accept-Encoding: gzip
  • HTTP请求映射到静态文件,存在同名的含有.gz后缀的文件

如果其中任意一个条件为假,Asset控制器就发回原始(非压缩)文件。

后面我们跳过MVC中的Model部分,这部分可以参考Slick开发教程,和Play开发本身关系不是非常密切。你也可以选用其它ORM框架,或者直接使用SQL。