Go製のウェブフレームワークRevelを試してみる。
サンプルを動かしてみる
$ go get github.com/revel/cmd/revel
$ revel run github.com/revel/revel/samples/chat
~
~ revel! http://revel.github.io
~
2014/08/02 22:18:17 revel.go:320: Loaded module testrunner
2014/08/02 22:18:17 revel.go:320: Loaded module static
2014/08/02 22:18:17 run.go:57: Running chat (github.com/revel/revel/samples/chat) in dev mode
2014/08/02 22:18:17 harness.go:165: Listening on :9000
http://localhost:9000
でアクセス出来る。
スケルトンを作成してみる
$ revel new board # $GOPATH # $GOPATH/src/board にスケルトンアプリケーションが作成される
revel run board
でサーバが起動する。
ディレクトリ構成
$ tree
.
├── app
│ ├── controllers
│ │ └── app.go
│ ├── init.go
│ ├── routes
│ │ └── routes.go
│ ├── tmp
│ │ └── main.go
│ └── views
│ ├── App
│ │ └── Index.html
│ ├── debug.html
│ ├── errors
│ │ ├── 404.html
│ │ └── 500.html
│ ├── flash.html
│ ├── footer.html
│ └── header.html
├── conf
│ ├── app.conf
│ └── routes
├── messages
│ └── sample.en
├── public
│ ├── css
│ │ └── bootstrap.css
│ ├── img
│ │ ├── favicon.png
│ │ ├── glyphicons-halflings-white.png
│ │ └── glyphicons-halflings.png
│ └── js
│ └── jquery-1.9.1.min.js
└── tests
└── apptest.go
各種機能概要
Routingの設定
conf/routes
に必要なルーティングを設定する
# conf/routes
# This file defines all application routes (Higher priority routes first)
module:jobs # Import all routes from the jobs module
GET /login App.Login # A simple path
GET /hotels/ Hotels.Index # Match /hotels and /hotels/ (optional trailing slash)
GET /hotels/:id Hotels.Show # Extract a URI argument
WS /hotels/:id/feed Hotels.Feed # WebSockets.
POST /hotels/:id/:action Hotels.:action # Automatically route some actions.
GET /public/*filepath Static.Serve("public") # Map /app/public resources under /public/...
* /debug/ module:testrunner # Prefix all routes in the testrunner module with /debug/
* /:controller/:action :controller.:action # Catch all; Automatic URL generation
例えば /hello
にアクセスした時にページを表示させたい場合は
GET /hello Hello.Index
と書く。
Controllers
app/controllers/
以下にcontroller用のファイルを置く
package controllers
import "github.com/revel/revel"
type Hello struct {
*revel.Controller
}
func (h Hello) Index() revel.Result {
return h.Render()
}
Templates
app/views/
以下にいわゆるViewファイルを置いていく。
デフォルトでは、app/views/#{controller名}/#{action名}.html
になる。
{{set . "title" "Hello"}}
{{template "header.html" .}}
<header class="hero-unit" style="background-color:#A9F16C">
<div class="container">
<div class="row">
<div class="hero-text">
<h1>Hello World!</h1>
<p></p>
</div>
</div>
</div>
</header>
<div class="container">
<div class="row">
<div class="span6">
{{template "flash.html" .}}
</div>
</div>
</div>
{{template "footer.html" .}}
この時点で、$ go run board
でサーバー起動し
http://localhost:9000/hello
にアクセスすれば上のページが表示される。
Interceptors
Interceptors
はcontrollerメソッドの前後やpanic時、
複数のcontrollerからアクセスがある場合に利用する。
package controllers
import (
"fmt"
"github.com/revel/revel"
)
type Intercepter struct {
}
func (i *Intercepter) Before() revel.Result { // 返り値は `revel.Result`
fmt.Println("Before Method")
return nil
}
func (i *Intercepter) After() revel.Result {
fmt.Println("After Method")
return nil
}
func (i *Intercepter) Panic() revel.Result {
fmt.Println("Panic Method")
return nil
}
func init() {
revel.InterceptMethod((*Intercepter).Before, revel.BEFORE) // コントローラ実行前
revel.InterceptMethod((*Intercepter).After, revel.AFTER) // コントローラ実行後
revel.InterceptMethod((*Intercepter).Panic, revel.PANIC) // panic実行後
}
設定はControllerで行う。
package controllers
import "github.com/revel/revel"
type App struct {
*revel.Controller
Intercepter // 構造体に追加
}
func (c App) Index() revel.Result {
return c.Render()
}
Filters
revelのフィルターは、アプリケーションのミドルウェアのことを指す。
revel new
で作った場合いくつかapp/init.go
に書かれている
revel.Filters = []revel.Filter{
revel.PanicFilter, // Recover from panics and display an error page instead.
revel.RouterFilter, // Use the routing table to select the right Action
revel.FilterConfiguringFilter, // A hook for adding or removing per-Action filters.
revel.ParamsFilter, // Parse parameters into Controller.Params.
revel.SessionFilter, // Restore and write the session cookie.
revel.FlashFilter, // Restore and write the flash cookie.
revel.ValidationFilter, // Restore kept validation errors and save new ones from cookie.
revel.I18nFilter, // Resolve the requested language
HeaderFilter, // Add some security based headers
revel.InterceptorFilter, // Run interceptors around the action.
revel.CompressFilter, // Compress the result.
revel.ActionInvoker, // Invoke the action.
}
以下の図のFilters部分をここで定義していく
http://revel.github.io/manual/concepts.html
例えば、一つ目のPanicFilterはこんなように書かれている。
// PanicFilter wraps the action invocation in a protective defer blanket that
// converts panics into 500 error pages.
func PanicFilter(c *Controller, fc []Filter) {
defer func() {
if err := recover(); err != nil {
handleInvocationPanic(c, err)
}
}()
fc[0](c, fc[1:])
}
Filterの定義は type Filter func(c *Controller, filterChain []Filter)
最後に fc[0](c, fc[1:])
で次のフィルターに実行を移している。
(続きます)