mirror of
https://github.com/astaxie/beego.git
synced 2024-11-22 07:50:54 +00:00
Update: clean and fix docs markdown
This commit is contained in:
parent
fdb94aeba0
commit
541d7f71b9
@ -1,10 +1,15 @@
|
||||
##What is hot update?
|
||||
## What is hot update?
|
||||
|
||||
If you have used nginx, you may know that nginx supports hot update, which means you can update your nginx without stopping and restarting it. It serves old connections with old version, and accepts new connections with new version. Notice that hot compiling is different from hot update, where hot compiling is monitoring your source files and recompile them when the content changes, it requires stop and restart your applications, `bee start` is a tool for hot compiling.
|
||||
|
||||
##Is hot update necessary?
|
||||
|
||||
## Is hot update necessary?
|
||||
|
||||
Some people says that hot update is not as useful as its cool name. In my opinion, this is absolutely necessary because zero-down server is our goal for our services. Even though sometimes some errors or hardware problems may occur, but it belongs to design of high availability, don't mix them up. Service update is a known issue, so we need to fix this problem.
|
||||
|
||||
##How Beego support hot update?
|
||||
|
||||
## How Beego support hot update?
|
||||
|
||||
The basic principle of hot update: main process fork a process, and child process execute corresponding programs. So what happens? We know that after forked a process, main process will have all handles, data and stack, etc, but all handles are saved in `CloseOnExec`, so all copied handles will be closed when you execute it unless you clarify this, and we need child process to reuse the handle of `net.Listener`. Once a process calls exec functions, it is "dead", system replaces it with new code. The only thing it left is the process ID, which is the same number but it is a new program after executed.
|
||||
|
||||
Therefore, the first thing we need to do is that let child process fork main process and through `os.StartProcess` to append files that contains handle that is going to be inherited.
|
||||
@ -15,7 +20,8 @@ The final step is that we want to serve old connections with old version of appl
|
||||
|
||||
Above are three problems that we need to solve, you can see my code logic for specific implementation.
|
||||
|
||||
##Show time
|
||||
|
||||
## Show time
|
||||
|
||||
1. Write code in your Get method:
|
||||
|
||||
@ -26,15 +32,15 @@ Above are three problems that we need to solve, you can see my code logic for sp
|
||||
}
|
||||
|
||||
2. Open two terminals:
|
||||
|
||||
|
||||
One execute: ` ps -ef|grep <application name>`
|
||||
|
||||
Another one execute:`curl "http://127.0.0.1:8080/?sleep=20"`
|
||||
|
||||
|
||||
Another one execute: `curl "http://127.0.0.1:8080/?sleep=20"`
|
||||
|
||||
3. Hot update
|
||||
|
||||
`kill -HUP <PID>`
|
||||
|
||||
4. Open a terminal to request connection: `curl "http://127.0.0.1:8080/?sleep=0"`
|
||||
|
||||
As you will see, the first request will wait for 20 seconds, but it's served by old process; after hot update, the first request will print old process ID, but the second request will print new process ID.
|
||||
4. Open a terminal to request connection: `curl "http://127.0.0.1:8080/?sleep=0"`
|
||||
|
||||
As you will see, the first request will wait for 20 seconds, but it's served by old process; after hot update, the first request will print old process ID, but the second request will print new process ID.
|
||||
|
@ -1,16 +1,17 @@
|
||||
#Installation
|
||||
# Installation
|
||||
|
||||
Beego is a simple web framework, but it uses many third-party packages, so you have to install all dependency packages also.
|
||||
|
||||
- Before anything you do, you have to check that you installed Go in your computer, see more detail about Go installation in my book: [Chapter 1](https://github.com/Unknwon/build-web-application-with-golang_EN/blob/master/eBook/01.1.md)
|
||||
- Use `go get ` to install Beego:
|
||||
- Use `go get ` to install Beego:
|
||||
|
||||
go get github.com/astaxie/beego
|
||||
|
||||
- Install bee tools for fast-develop Beego applications:
|
||||
|
||||
go get github.com/astaxie/bee
|
||||
- Install bee tools for fast-develop Beego applications:
|
||||
|
||||
Good job, you're ready to Beego with powerful bee tools!
|
||||
go get github.com/astaxie/bee
|
||||
|
||||
Good job, you're ready to Beego with powerful bee tools!
|
||||
|
||||
![](images/bee.png)
|
||||
|
||||
@ -22,4 +23,4 @@ Beego has following dependency packages:
|
||||
- To support markdown as template function: [github.com/russross/blackfriday](https://github.com/russross/blackfriday)
|
||||
|
||||
- [Introduction](README.md)
|
||||
- [Quick start](Quickstart.md)
|
||||
- [Quick start](Quickstart.md)
|
||||
|
@ -1,4 +1,5 @@
|
||||
# Quick start
|
||||
|
||||
Hey, you say you've never heard about Beego and don't know how to use it? Don't worry, after you read this section, you will know a lot about Beego. Before you start reading, make sure you installed Beego in your computer, if not, check this tutorial: [Installation](Install.md)
|
||||
|
||||
**Navigation**
|
||||
@ -23,11 +24,13 @@ Hey, you say you've never heard about Beego and don't know how to use it? Don't
|
||||
- [Integrated third-party applications](#integrated-third-party-applications)
|
||||
- [Deployment](#deployment)
|
||||
|
||||
|
||||
## Hello world
|
||||
|
||||
This is an example of "Hello world" in Beego:
|
||||
|
||||
package main
|
||||
|
||||
|
||||
import (
|
||||
"github.com/astaxie/beego"
|
||||
)
|
||||
@ -54,18 +57,25 @@ Open address [http://127.0.0.1:8080](http://127.0.0.1:8080) in your browser and
|
||||
|
||||
What happened in behind above example?
|
||||
|
||||
1. We import package `github.com/astaxie/beego`. As we know that Go initialize packages and runs init() function in every package(more detail [here](https://github.com/Unknwon/build-web-application-with-golang_EN/blob/master/eBook/02.3.md#main-function-and-init-function)), so Beego initializes the BeeApp application at this time.
|
||||
1. We import package `github.com/astaxie/beego`. As we know that Go initialize packages and runs init() function in every package ([more details](https://github.com/Unknwon/build-web-application-with-golang_EN/blob/master/eBook/02.3.md#main-function-and-init-function)), so Beego initializes the BeeApp application at this time.
|
||||
|
||||
2. Define controller. We define a struct called `MainController` with a anonymous field `beego.Controller`, so the `MainController` has all methods that `beego.Controller` has.
|
||||
|
||||
3. Define RESTful methods. Once we use anonymous combination, `MainController` has already had `Get`, `Post`, `Delete`, `Put` and other methods, these methods will be called when user sends corresponding request, like `Post` method for requests that are using POST method. Therefore, after we overloaded `Get` method in `MainController`, all GET requests will use `Get` method in `MainController` instead of in `beego.Controller`.
|
||||
|
||||
4. Define main function. All applications in Go use main function as entry point as C does.
|
||||
|
||||
5. Register routers, it tells Beego which controller is responsibility for specific requests. Here we register `/` for `MainController`, so all requests in `/` will be handed to `MainController`. Be aware that the first argument is the path and the second one is pointer of controller that you want to register.
|
||||
|
||||
6. Run application in port 8080 as default, press `Ctrl+c` to exit.
|
||||
|
||||
|
||||
## New project
|
||||
|
||||
Get into your $GOPATH, then use following command to setup Beego project:
|
||||
|
||||
bee create hello
|
||||
|
||||
|
||||
It generates folders and files for your project, directory structure as follows:
|
||||
|
||||
.
|
||||
@ -82,7 +92,9 @@ It generates folders and files for your project, directory structure as follows:
|
||||
└── views
|
||||
└── index.tpl
|
||||
|
||||
|
||||
## Development mode
|
||||
|
||||
Beego uses development mode as default, you can use following code to change mode in your application:
|
||||
|
||||
beego.RunMode = "pro"
|
||||
@ -95,7 +107,7 @@ No differences between two ways.
|
||||
|
||||
In development mode, you have following effects:
|
||||
|
||||
- If you don't have directory `views`, it prints following error prompt:
|
||||
- If you don't have directory `views`, it prints following error prompt:
|
||||
|
||||
2013/04/13 19:36:17 [W] [stat views: no such file or directory]
|
||||
|
||||
@ -104,7 +116,9 @@ In development mode, you have following effects:
|
||||
|
||||
![](images/dev.png)
|
||||
|
||||
|
||||
## Router
|
||||
|
||||
The main function of router is to connect request URL and handler. Beego wrapped `Controller`, so it connects request URL and `ControllerInterface`. The `ControllerInterface` has following methods:
|
||||
|
||||
type ControllerInterface interface {
|
||||
@ -132,39 +146,41 @@ Users can use following ways to register route rules:
|
||||
|
||||
For more convenient configure route rules, Beego references the idea from sinatra, so it supports more kinds of route rules as follows:
|
||||
|
||||
- beego.Router("/api/:id([0-9]+)", &controllers.RController{})
|
||||
- beego.Router("/api/:id([0-9]+)", &controllers.RController{})
|
||||
|
||||
Customized regular expression match // match /api/123 :id= 123
|
||||
Customized regular expression match // match /api/123 :id= 123
|
||||
|
||||
- beego.Router("/news/:all", &controllers.RController{})
|
||||
|
||||
- beego.Router("/news/:all", &controllers.RController{})
|
||||
|
||||
Match rest of all // match /news/path/to/123.html :all= path/to/123.html
|
||||
|
||||
- beego.Router("/user/:username([\w]+)", &controllers.RController{})
|
||||
|
||||
- beego.Router("/user/:username([\w]+)", &controllers.RController{})
|
||||
|
||||
Regular expression // match /user/astaxie :username = astaxie
|
||||
|
||||
- beego.Router("/download/`*`.`*`", &controllers.RController{})
|
||||
|
||||
- beego.Router("/download/`*`.`*`", &controllers.RController{})
|
||||
|
||||
Wildcard character // match /download/file/api.xml :path= file/api :ext=xml
|
||||
|
||||
- beego.Router("/download/ceshi/`*`", &controllers.RController{})
|
||||
|
||||
- beego.Router("/download/ceshi/`*`", &controllers.RController{})
|
||||
|
||||
wildcard character match rest of all // match /download/ceshi/file/api.json :splat=file/api.json
|
||||
|
||||
- beego.Router("/:id:int", &controllers.RController{})
|
||||
|
||||
- beego.Router("/:id:int", &controllers.RController{})
|
||||
|
||||
Match type int // match :id is int type, Beego uses regular expression ([0-9]+) automatically
|
||||
|
||||
- beego.Router("/:hi:string", &controllers.RController{})
|
||||
|
||||
- beego.Router("/:hi:string", &controllers.RController{})
|
||||
|
||||
Match type string // match :hi is string type, Beego uses regular expression ([\w]+) automatically
|
||||
|
||||
##Static files
|
||||
|
||||
## Static files
|
||||
|
||||
Go provides `http.ServeFile` for static files, Beego wrapped this function and use following way to register static file folder:
|
||||
|
||||
beego.SetStaticPath("/static","public")
|
||||
|
||||
|
||||
- The first argument is the path of your URL.
|
||||
- The second argument is the directory in your application path.
|
||||
|
||||
@ -176,37 +192,41 @@ Beego supports multiple static file directories as follows:
|
||||
|
||||
After you setting static directory, when users visit `/images/login/login.png`,Beego accesses `images/login/login.png` in related to your application directory. One more example, if users visit `/static/img/logo.png`, Beego accesses file `public/img/logo.png`.
|
||||
|
||||
##Filter and middleware
|
||||
|
||||
## Filter and middleware
|
||||
|
||||
Beego supports customized filter and middleware, such as security verification, force redirect, etc.
|
||||
|
||||
Here is an example of verify user name of all requests, check if it's admin.
|
||||
|
||||
var FilterUser = func(w http.ResponseWriter, r *http.Request) {
|
||||
if r.URL.User == nil || r.URL.User.Username() != "admin" {
|
||||
http.Error(w, "", http.StatusUnauthorized)
|
||||
}
|
||||
if r.URL.User == nil || r.URL.User.Username() != "admin" {
|
||||
http.Error(w, "", http.StatusUnauthorized)
|
||||
}
|
||||
}
|
||||
|
||||
beego.Filter(FilterUser)
|
||||
|
||||
beego.Filter(FilterUser)
|
||||
|
||||
You can also filter by arguments:
|
||||
|
||||
beego.Router("/:id([0-9]+)", &admin.EditController{})
|
||||
beego.FilterParam("id", func(rw http.ResponseWriter, r *http.Request) {
|
||||
dosomething()
|
||||
dosomething()
|
||||
})
|
||||
|
||||
|
||||
Filter by prefix is also available:
|
||||
|
||||
beego.FilterPrefixPath("/admin", func(rw http.ResponseWriter, r *http.Request) {
|
||||
dosomething()
|
||||
dosomething()
|
||||
})
|
||||
|
||||
##Controller
|
||||
|
||||
## Controller
|
||||
|
||||
Use `beego.controller` as anonymous in your controller struct to implement the interface in Beego:
|
||||
|
||||
type xxxController struct {
|
||||
beego.Controller
|
||||
beego.Controller
|
||||
}
|
||||
|
||||
`beego.Controller` implemented`beego.ControllerInterface`, `beego.ControllerInterface` defined following methods:
|
||||
@ -214,15 +234,15 @@ Use `beego.controller` as anonymous in your controller struct to implement the i
|
||||
- Init(ct `*`Context, cn string)
|
||||
|
||||
Initialize context, controller's name, template's name, and container of template arguments
|
||||
|
||||
|
||||
- Prepare()
|
||||
|
||||
This is for expend usages, it executes before all the following methods. Users can overload this method for verification for example.
|
||||
|
||||
|
||||
- Get()
|
||||
|
||||
This method executes when client sends request as GET method, 403 as default status code. Users overload this method for customized handle process of GET method.
|
||||
|
||||
|
||||
- Post()
|
||||
|
||||
This method executes when client sends request as POST method, 403 as default status code. Users overload this method for customized handle process of POST method.
|
||||
@ -258,7 +278,7 @@ Use `beego.controller` as anonymous in your controller struct to implement the i
|
||||
Overload all methods for all customized logic processes, let's see an example:
|
||||
|
||||
type AddController struct {
|
||||
beego.Controller
|
||||
beego.Controller
|
||||
}
|
||||
|
||||
func (this *AddController) Prepare() {
|
||||
@ -266,54 +286,64 @@ Overload all methods for all customized logic processes, let's see an example:
|
||||
}
|
||||
|
||||
func (this *AddController) Get() {
|
||||
this.Data["content"] ="value"
|
||||
this.Layout = "admin/layout.html"
|
||||
this.TplNames = "admin/add.tpl"
|
||||
this.Data["content"] = "value"
|
||||
this.Layout = "admin/layout.html"
|
||||
this.TplNames = "admin/add.tpl"
|
||||
}
|
||||
|
||||
func (this *AddController) Post() {
|
||||
pkgname := this.GetString("pkgname")
|
||||
content := this.GetString("content")
|
||||
pk := models.GetCruPkg(pkgname)
|
||||
if pk.Id == 0 {
|
||||
var pp models.PkgEntity
|
||||
pp.Pid = 0
|
||||
pp.Pathname = pkgname
|
||||
pp.Intro = pkgname
|
||||
models.InsertPkg(pp)
|
||||
pk = models.GetCruPkg(pkgname)
|
||||
}
|
||||
var at models.Article
|
||||
at.Pkgid = pk.Id
|
||||
at.Content = content
|
||||
models.InsertArticle(at)
|
||||
this.Ctx.Redirect(302, "/admin/index")
|
||||
}
|
||||
pkgname := this.GetString("pkgname")
|
||||
content := this.GetString("content")
|
||||
pk := models.GetCruPkg(pkgname)
|
||||
if pk.Id == 0 {
|
||||
var pp models.PkgEntity
|
||||
pp.Pid = 0
|
||||
pp.Pathname = pkgname
|
||||
pp.Intro = pkgname
|
||||
models.InsertPkg(pp)
|
||||
pk = models.GetCruPkg(pkgname)
|
||||
}
|
||||
var at models.Article
|
||||
at.Pkgid = pk.Id
|
||||
at.Content = content
|
||||
models.InsertArticle(at)
|
||||
this.Ctx.Redirect(302, "/admin/index")
|
||||
}
|
||||
|
||||
|
||||
## Template
|
||||
|
||||
|
||||
### Template directory
|
||||
|
||||
##Template
|
||||
###Template directory
|
||||
Beego uses `views` as the default directory for template files, parses and caches them as needed(cache is not enable in develop mode), but you can **change**(because only one directory can be used for template files) its directory using following code:
|
||||
|
||||
beego.ViewsPath = "/myviewpath"
|
||||
|
||||
###Auto-render
|
||||
|
||||
### Auto-render
|
||||
|
||||
You don't need to call render function manually, Beego calls it automatically after corresponding methods executed. If your application is somehow doesn't need templates, you can disable this feature either in code of `main.go` or configuration file.
|
||||
|
||||
To disable auto-render in configuration file:
|
||||
|
||||
|
||||
autorender = false
|
||||
|
||||
To disable auto-render in `main.go`(before you call `beego.Run()` to run the application):
|
||||
|
||||
beego.AutoRender = false
|
||||
|
||||
###Template data
|
||||
|
||||
|
||||
### Template data
|
||||
|
||||
You can use `this.Data` in controller methods to access the data in templates. Suppose you want to get content of `{{.Content}}`, you can use following code to do this:
|
||||
|
||||
|
||||
this.Data["Context"] = "value"
|
||||
|
||||
###Template name
|
||||
Beego uses built-in template engine of Go, so there is no different in syntax. As for how to write template file, please visit [Template tutorial](https://github.com/Unknwon/build-web-application-with-golang_EN/blob/master/eBook/07.4.md)。
|
||||
|
||||
|
||||
### Template name
|
||||
|
||||
Beego uses built-in template engine of Go, so there is no different in syntax. As for how to write template file, please visit [Template tutorial](https://github.com/Unknwon/build-web-application-with-golang_EN/blob/master/eBook/07.4.md).
|
||||
|
||||
Beego parses template files in `viewpath` and render it after you set the name of the template file in controller methods. For example, Beego finds the file `add.tpl` in directory `admin` in following code:
|
||||
|
||||
@ -329,16 +359,18 @@ If you enabled auto-render and you don't tell Beego which template file you are
|
||||
|
||||
Which is `<corresponding controller name>/<request method name>.<template extension>`. For example, your controller name is `AddController` and the request method is POST, and the default file extension is `tpl`, so Beego will try to find file `/<viewpath>/AddController/POST.tpl`.
|
||||
|
||||
###Layout design
|
||||
|
||||
### Layout design
|
||||
|
||||
Beego supports layout design, which means if you are working on an administration application, and some part of its user interface is exactly same all the time, then you can make this part as a layout.
|
||||
|
||||
|
||||
this.Layout = "admin/layout.html"
|
||||
this.TplNames = "admin/add.tpl"
|
||||
|
||||
You have to set following variable in order to make Beego possible to insert your dynamic content:
|
||||
|
||||
{{.LayoutContent}}
|
||||
|
||||
|
||||
Beego parses template file and assign content to `LayoutContent`, and render them together.
|
||||
|
||||
Right now, Beego caches all template files, so you can use following way to implement another kind of layout:
|
||||
@ -347,12 +379,14 @@ Right now, Beego caches all template files, so you can use following way to impl
|
||||
Handle logic
|
||||
{{template "footer.html"}}
|
||||
|
||||
###Template function
|
||||
|
||||
### Template function
|
||||
|
||||
Beego supports customized template functions that are registered before you call `beego.Run()`.
|
||||
|
||||
func hello(in string)(out string){
|
||||
out = in + "world"
|
||||
return
|
||||
out = in + "world"
|
||||
return
|
||||
}
|
||||
|
||||
beego.AddFuncMap("hi",hello)
|
||||
@ -363,35 +397,45 @@ Then you can use this function in your template files:
|
||||
|
||||
There are some built-in template functions:
|
||||
|
||||
* markdown
|
||||
|
||||
* markdown
|
||||
|
||||
This function converts markdown content to HTML format, use {{markdown .Content}} in template files.
|
||||
* dateformat
|
||||
|
||||
* dateformat
|
||||
|
||||
This function converts time to formatted string, use {{dateformat .Time "2006-01-02T15:04:05Z07:00"}} in template files.
|
||||
* date
|
||||
|
||||
* date
|
||||
|
||||
This function implements date function like in PHP, use formatted string to get corresponding time, use {{date .T "Y-m-d H:i:s"}} in template files.
|
||||
* compare
|
||||
|
||||
* compare
|
||||
|
||||
This functions compares two objects, returns true if they are same, false otherwise, use {{compare .A .B}} in template files.
|
||||
* substr
|
||||
|
||||
* substr
|
||||
|
||||
This function cuts out string from another string by index, it supports UTF-8 characters, use {{substr .Str 0 30}} in template files.
|
||||
* html2str
|
||||
|
||||
* html2str
|
||||
|
||||
This function escapes HTML to raw string, use {{html2str .Htmlinfo}} in template files.
|
||||
* str2html
|
||||
|
||||
* str2html
|
||||
|
||||
This function outputs string in HTML format without escaping, use {{str2html .Strhtml}} in template files.
|
||||
* htmlquote
|
||||
|
||||
* htmlquote
|
||||
|
||||
This functions implements basic HTML escape, use {{htmlquote .quote}} in template files.
|
||||
* htmlunquote
|
||||
|
||||
* htmlunquote
|
||||
|
||||
This functions implements basic invert-escape of HTML, use {{htmlunquote .unquote}} in template files.
|
||||
|
||||
##Handle request
|
||||
|
||||
|
||||
## Handle request
|
||||
|
||||
We always need to get data from users, including methods like GET, POST, etc. Beego parses these data automatically, and you can access them by following code:
|
||||
|
||||
- GetString(key string) string
|
||||
@ -413,18 +457,20 @@ If you need other types that are not included above, like you need int64 instead
|
||||
func (this *MainController) Post() {
|
||||
id := this.Input().Get("id")
|
||||
intid, err := strconv.Atoi(id)
|
||||
}
|
||||
}
|
||||
|
||||
To use `this.Ctx.Request` for more information about request, and object properties and method please read [Request](http://golang.org/pkg/net/http/#Request)
|
||||
|
||||
###File upload
|
||||
|
||||
### File upload
|
||||
|
||||
It's very easy to upload file through Beego, but don't forget to add `enctype="multipart/form-data"` in your form, otherwise the browser will not upload anything.
|
||||
|
||||
Files will be saved in memory, if the size is greater than cache memory, the rest part will be saved as temporary file. The default cache memory is 64 MB, and you can using following ways to change this size.
|
||||
Files will be saved in memory, if the size is greater than cache memory, the rest part will be saved as temporary file. The default cache memory is 64 MB, and you can use following ways to change this size.
|
||||
|
||||
In code:
|
||||
|
||||
beego.MaxMemory = 1<<22
|
||||
beego.MaxMemory = 1<<22
|
||||
|
||||
In configuration file:
|
||||
|
||||
@ -435,56 +481,60 @@ Beego provides two convenient functions to upload files:
|
||||
- GetFile(key string) (multipart.File, `*`multipart.FileHeader, error)
|
||||
|
||||
This function is mainly used to read file name element `the_file` in form and returns corresponding information. You can use this information either filter or save files.
|
||||
|
||||
|
||||
- SaveToFile(fromfile, tofile string) error
|
||||
|
||||
This function a wrapper of GetFile and gives ability to save file.
|
||||
|
||||
|
||||
This is an example to save file that is uploaded:
|
||||
|
||||
|
||||
func (this *MainController) Post() {
|
||||
this.SaveToFile("the_file","/var/www/uploads/uploaded_file.txt"")
|
||||
}
|
||||
|
||||
###Output Json and XML
|
||||
|
||||
### Output Json and XML
|
||||
|
||||
Beego considered API function design at the beginning, and we often use Json or XML format data as output. Therefore, it's no reason that Beego doesn't support it:
|
||||
|
||||
Set `content-type` to `application/json` for output raw Json format data:
|
||||
|
||||
func (this *AddController) Get() {
|
||||
mystruct := { ... }
|
||||
this.Data["json"] = &mystruct
|
||||
this.ServeJson()
|
||||
}
|
||||
mystruct := { ... }
|
||||
this.Data["json"] = &mystruct
|
||||
this.ServeJson()
|
||||
}
|
||||
|
||||
Set `content-type` to `application/xml` for output raw XML format data:
|
||||
|
||||
func (this *AddController) Get() {
|
||||
mystruct := { ... }
|
||||
this.Data["xml"]=&mystruct
|
||||
this.ServeXml()
|
||||
}
|
||||
|
||||
##Redirect and error
|
||||
mystruct := { ... }
|
||||
this.Data["xml"]=&mystruct
|
||||
this.ServeXml()
|
||||
}
|
||||
|
||||
|
||||
## Redirect and error
|
||||
|
||||
You can use following to redirect:
|
||||
|
||||
func (this *AddController) Get() {
|
||||
this.Redirect("/", 302)
|
||||
}
|
||||
this.Redirect("/", 302)
|
||||
}
|
||||
|
||||
You can also throw an exception in your controller as follows:
|
||||
|
||||
func (this *MainController) Get() {
|
||||
this.Abort("401")
|
||||
v := this.GetSession("asta")
|
||||
if v == nil {
|
||||
this.SetSession("asta", int(1))
|
||||
this.Data["Email"] = 0
|
||||
} else {
|
||||
this.SetSession("asta", v.(int)+1)
|
||||
this.Data["Email"] = v.(int)
|
||||
}
|
||||
this.TplNames = "index.tpl"
|
||||
this.Abort("401")
|
||||
v := this.GetSession("asta")
|
||||
if v == nil {
|
||||
this.SetSession("asta", int(1))
|
||||
this.Data["Email"] = 0
|
||||
} else {
|
||||
this.SetSession("asta", v.(int)+1)
|
||||
this.Data["Email"] = v.(int)
|
||||
}
|
||||
this.TplNames = "index.tpl"
|
||||
}
|
||||
|
||||
Then Beego will not execute rest code of the function body when you call `this.Abort("401")`, and gives following default page view to users:
|
||||
@ -493,56 +543,60 @@ Then Beego will not execute rest code of the function body when you call `this.A
|
||||
|
||||
Beego supports following error code: 404, 401, 403, 500 and 503, you can customize your error handle, for example, use following code to replace 404 error handle process:
|
||||
|
||||
func page_not_found(rw http.ResponseWriter, r *http.Request){
|
||||
t,_:= template.New("beegoerrortemp").ParseFiles(beego.ViewsPath+"/404.html")
|
||||
data :=make(map[string]interface{})
|
||||
data["content"] = "page not found"
|
||||
t.Execute(rw, data)
|
||||
func page_not_found(rw http.ResponseWriter, r *http.Request) {
|
||||
t, _ := template.New("beegoerrortemp").ParseFiles(beego.ViewsPath + "/404.html")
|
||||
data := make(map[string]interface{})
|
||||
data["content"] = "page not found"
|
||||
t.Execute(rw, data)
|
||||
}
|
||||
|
||||
func main() {
|
||||
beego.Errorhandler("404",page_not_found)
|
||||
beego.Router("/", &controllers.MainController{})
|
||||
beego.Run()
|
||||
}
|
||||
beego.Errorhandler("404", page_not_found)
|
||||
beego.Router("/", &controllers.MainController{})
|
||||
beego.Run()
|
||||
}
|
||||
|
||||
You may be able to use your own `404.html` for your 404 error.
|
||||
|
||||
Beego also gives you ability to modify error message that shows on the error page, the following example shows how to set more meaningful error message when database has problems:
|
||||
|
||||
func dbError(rw http.ResponseWriter, r *http.Request){
|
||||
t,_:= template.New("beegoerrortemp").ParseFiles(beego.ViewsPath+"/dberror.html")
|
||||
data :=make(map[string]interface{})
|
||||
data["content"] = "database is now down"
|
||||
t.Execute(rw, data)
|
||||
func dbError(rw http.ResponseWriter, r *http.Request) {
|
||||
t, _ := template.New("beegoerrortemp").ParseFiles(beego.ViewsPath + "/dberror.html")
|
||||
data := make(map[string]interface{})
|
||||
data["content"] = "database is now down"
|
||||
t.Execute(rw, data)
|
||||
}
|
||||
|
||||
func main() {
|
||||
beego.Errorhandler("dbError",dbError)
|
||||
beego.Router("/", &controllers.MainController{})
|
||||
beego.Run()
|
||||
}
|
||||
beego.Errorhandler("dbError", dbError)
|
||||
beego.Router("/", &controllers.MainController{})
|
||||
beego.Run()
|
||||
}
|
||||
|
||||
After you registered this customized error, you can use `this.Abort("dbError")` for any database error in your applications.
|
||||
|
||||
##Handle response
|
||||
|
||||
## Handle response
|
||||
|
||||
There are some situations that you may have in response:
|
||||
|
||||
1. Output template
|
||||
|
||||
I've already talked about template above, Beego outputs template after corresponding method executed.
|
||||
|
||||
|
||||
2. Redirect
|
||||
|
||||
You can use this.Redirect("/", 302) to redirect page.
|
||||
|
||||
|
||||
3. Output string
|
||||
|
||||
Sometimes we just need to print string on the screen:
|
||||
|
||||
this.Ctx.WriteString("ok")
|
||||
|
||||
|
||||
## Sessions
|
||||
|
||||
Beego has a built-in session module and supports four engines, including memory, file, MySQL and redis. You can implement your own engine based on the interface.
|
||||
|
||||
It's easy to use session in Beego, use following code in your main() function:
|
||||
@ -594,21 +648,21 @@ There are some arguments you can use in session module:
|
||||
- SessionOn
|
||||
|
||||
Whether enable session or not, default is false, corresponding arguments in configuration file: sessionon.
|
||||
|
||||
|
||||
- SessionProvider
|
||||
|
||||
Setting session engine, default is memory, other options are file, MySQL and redis, corresponding arguments in configuration file: sessionprovider.
|
||||
|
||||
|
||||
- SessionName
|
||||
|
||||
Setting name of cookies, it saves in users' browser with name beegosessionID, corresponding arguments in configuration file: sessionname.
|
||||
|
||||
|
||||
- SessionGCMaxLifetime
|
||||
|
||||
Setting session expired time, default is 3600 seconds, corresponding arguments in configuration: sessiongcmaxlifetime
|
||||
|
||||
|
||||
- SessionSavePath
|
||||
|
||||
|
||||
Setting save path or link address of corresponding file, MySQL and redis engines, default is empty, corresponding arguments in configuration file: sessionsavepath
|
||||
|
||||
When the SessionProvider is file, SessionSavePath saves file path:
|
||||
@ -620,13 +674,15 @@ When the SessionProvider is mysql, SessionSavePath is link address, it uses driv
|
||||
|
||||
beego.SessionProvider = "mysql"
|
||||
beego.SessionSavePath = "username:password@protocol(address)/dbname?param=value"
|
||||
|
||||
|
||||
When the SessionProvider is redis, SessionSavePath is link address of redis, it uses driver [redigo](https://github.com/garyburd/redigo):
|
||||
|
||||
beego.SessionProvider = "redis"
|
||||
beego.SessionSavePath = "127.0.0.1:6379"
|
||||
beego.SessionSavePath = "127.0.0.1:6379"
|
||||
|
||||
|
||||
## Cache
|
||||
|
||||
Beego has a built-in cache module, it's like memcache, which caches data in memory. Here is an example of using cache module in Beego:
|
||||
|
||||
var (
|
||||
@ -638,7 +694,7 @@ Beego has a built-in cache module, it's like memcache, which caches data in memo
|
||||
urllist.Every = 0 // Not expired
|
||||
urllist.Start()
|
||||
}
|
||||
|
||||
|
||||
func (this *ShortController) Post() {
|
||||
var result ShortResult
|
||||
longurl := this.Input().Get("longurl")
|
||||
@ -661,8 +717,8 @@ Beego has a built-in cache module, it's like memcache, which caches data in memo
|
||||
}
|
||||
this.Data["json"] = result
|
||||
this.ServeJson()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
To use cache, you need to initialize a `beego.NewBeeCache` object and set expired time, and enable expired check. Then you can use following methods to achieve other operations:
|
||||
|
||||
- Get(name string) interface{}
|
||||
@ -670,7 +726,9 @@ To use cache, you need to initialize a `beego.NewBeeCache` object and set expire
|
||||
- Delete(name string) (ok bool, err error)
|
||||
- IsExist(name string) bool
|
||||
|
||||
##Safe map
|
||||
|
||||
## Safe map
|
||||
|
||||
We know that map is not thread safe in Go, if you don't know it, this article may be helpful for you: [atomic_maps](http://golang.org/doc/faq#atomic_maps). However, we need a kind of thread safe map in practice, especially when we are using goroutines. Therefore, Beego provides a simple built-in thread safe map implementation.
|
||||
|
||||
bm := NewBeeMap()
|
||||
@ -680,16 +738,16 @@ We know that map is not thread safe in Go, if you don't know it, this article ma
|
||||
if !bm.Check("astaxie") {
|
||||
t.Error("check err")
|
||||
}
|
||||
|
||||
|
||||
if v := bm.Get("astaxie"); v.(int) != 1 {
|
||||
t.Error("get err")
|
||||
}
|
||||
|
||||
|
||||
bm.Delete("astaxie")
|
||||
if bm.Check("astaxie") {
|
||||
t.Error("delete err")
|
||||
}
|
||||
|
||||
|
||||
This map has following interfaces:
|
||||
|
||||
- Get(k interface{}) interface{}
|
||||
@ -697,7 +755,9 @@ This map has following interfaces:
|
||||
- Check(k interface{}) bool
|
||||
- Delete(k interface{})
|
||||
|
||||
##Log
|
||||
|
||||
## Log
|
||||
|
||||
Beego has a default BeeLogger object that outputs log into stdout, and you can use your own logger as well:
|
||||
|
||||
beego.SetLogger(*log.Logger)
|
||||
@ -706,13 +766,14 @@ You can output everything that implemented `*log.Logger`, for example, write to
|
||||
|
||||
fd,err := os.OpenFile("/var/log/beeapp/beeapp.log", os.O_RDWR|os.O_APPEND, 0644)
|
||||
if err != nil {
|
||||
beego.Critical("openfile beeapp.log:", err)
|
||||
return
|
||||
beego.Critical("openfile beeapp.log:", err)
|
||||
return
|
||||
}
|
||||
lg := log.New(fd, "", log.Ldate|log.Ltime)
|
||||
beego.SetLogger(lg)
|
||||
|
||||
###Different levels of log
|
||||
|
||||
### Different levels of log
|
||||
|
||||
* Trace(v ...interface{})
|
||||
* Debug(v ...interface{})
|
||||
@ -724,43 +785,55 @@ You can output everything that implemented `*log.Logger`, for example, write to
|
||||
You can use following code to set log level:
|
||||
|
||||
beego.SetLevel(beego.LevelError)
|
||||
|
||||
|
||||
Your project may have a lot of log outputs, but you don't want to output everything after your application is running on the internet, for example, you want to ignore Trace, Debug and Info level log outputs, you can use following setting:
|
||||
|
||||
beego.SetLevel(beego.LevelWarning)
|
||||
|
||||
Then Beego will not output log that has lower level of LevelWarning. Here is the list of all log levels, order from lower to higher:
|
||||
|
||||
LevelTrace、LevelDebug、LevelInfo、LevelWarning、 LevelError、LevelCritical
|
||||
LevelTrace, LevelDebug, LevelInfo, LevelWarning, LevelError, LevelCritical
|
||||
|
||||
You can use different log level to output different error messages, it's based on how critical the error you think it is:
|
||||
|
||||
|
||||
### Examples of log messages
|
||||
|
||||
- Trace
|
||||
|
||||
* "Entered parse function validation block"
|
||||
* "Validation: entered second 'if'"
|
||||
* "Dictionary 'Dict' is empty. Using default value"
|
||||
|
||||
- Debug
|
||||
|
||||
* "Web page requested: http://somesite.com Params='...'"
|
||||
* "Response generated. Response size: 10000. Sending."
|
||||
* "New file received. Type:PNG Size:20000"
|
||||
|
||||
- Info
|
||||
|
||||
* "Web server restarted"
|
||||
* "Hourly statistics: Requested pages: 12345 Errors: 123 ..."
|
||||
* "Service paused. Waiting for 'resume' call"
|
||||
|
||||
- Warn
|
||||
|
||||
* "Cache corrupted for file='test.file'. Reading from back-end"
|
||||
* "Database 192.168.0.7/DB not responding. Using backup 192.168.0.8/DB"
|
||||
* "No response from statistics server. Statistics not sent"
|
||||
|
||||
- Error
|
||||
|
||||
* "Internal error. Cannot process request #12345 Error:...."
|
||||
* "Cannot perform login: credentials DB not responding"
|
||||
|
||||
- Critical
|
||||
|
||||
* "Critical panic received: .... Shutting down"
|
||||
* "Fatal error: ... App is shutting down to prevent data corruption or loss"
|
||||
|
||||
|
||||
|
||||
### Example
|
||||
|
||||
func internalCalculationFunc(x, y int) (result int, err error) {
|
||||
@ -782,26 +855,26 @@ You can use different log level to output different error messages, it's based o
|
||||
}
|
||||
retVal := z-3
|
||||
beego.Debug("Returning ", retVal)
|
||||
|
||||
|
||||
return retVal, nil
|
||||
}
|
||||
|
||||
func processInput(input inputData) {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
beego.Error("Unexpected error occurred: ", r)
|
||||
beego.Error("Unexpected error occurred: ", r)
|
||||
outputs <- outputData{result : 0, error : true}
|
||||
}
|
||||
}
|
||||
}()
|
||||
beego.Info("Received input signal. x:",input.x," y:", input.y)
|
||||
beego.Info("Received input signal. x:",input.x," y:", input.y)
|
||||
|
||||
res, err := internalCalculationFunc(input.x, input.y)
|
||||
res, err := internalCalculationFunc(input.x, input.y)
|
||||
if err != nil {
|
||||
beego.Warn("Error in calculation:", err.Error())
|
||||
}
|
||||
|
||||
beego.Info("Returning result: ",res," error: ",err)
|
||||
outputs <- outputData{result : res, error : err != nil}
|
||||
beego.Info("Returning result: ",res," error: ",err)
|
||||
outputs <- outputData{result : res, error : err != nil}
|
||||
}
|
||||
|
||||
func main() {
|
||||
@ -827,7 +900,9 @@ You can use different log level to output different error messages, it's based o
|
||||
}
|
||||
}
|
||||
|
||||
##Configuration
|
||||
|
||||
## Configuration
|
||||
|
||||
Beego supports to parse .ini file in path `conf/app.conf`, and you have following options:
|
||||
|
||||
appname = beepkg
|
||||
@ -837,7 +912,7 @@ Beego supports to parse .ini file in path `conf/app.conf`, and you have followin
|
||||
autorender = false
|
||||
autorecover = false
|
||||
viewspath = "myview"
|
||||
|
||||
|
||||
If you set value in configuration file, Beego uses it to replace default value.
|
||||
|
||||
You can also have other values for your application, for example, database connection information:
|
||||
@ -846,7 +921,7 @@ You can also have other values for your application, for example, database conne
|
||||
mysqlpass = "rootpass"
|
||||
mysqlurls = "127.0.0.1"
|
||||
mysqldb = "beego"
|
||||
|
||||
|
||||
Then use following code to load your settings:
|
||||
|
||||
beego.AppConfig.String("mysqluser")
|
||||
@ -862,33 +937,35 @@ AppConfig supports following methods:
|
||||
- Float(key string) (float64, error)
|
||||
- String(key string) string
|
||||
|
||||
##Beego arguments
|
||||
|
||||
## Beego arguments
|
||||
|
||||
Beego has many configurable arguments, let me introduce to you all of them, so you can use them for more usage in your application:
|
||||
|
||||
* BeeApp
|
||||
|
||||
Entry point of Beego, it initialized in init() function when you import Beego package.
|
||||
|
||||
|
||||
* AppConfig
|
||||
|
||||
It stores values from file `conf/app.conf` and initialized in init() function.
|
||||
|
||||
|
||||
* HttpAddr
|
||||
|
||||
Application listening address, default is empty for listening all IP.
|
||||
|
||||
|
||||
* HttpPort
|
||||
|
||||
Application listening port, default is 8080.
|
||||
|
||||
|
||||
* AppName
|
||||
|
||||
Application name, default is "beego".
|
||||
|
||||
* RunMode
|
||||
|
||||
* RunMode
|
||||
|
||||
Application mode, default is "dev" develop mode and gives friendly error messages.
|
||||
|
||||
|
||||
* AutoRender
|
||||
|
||||
This value indicates whether auto-render or not, default is true, you should set to false for API usage applications.
|
||||
@ -905,37 +982,37 @@ Beego has many configurable arguments, let me introduce to you all of them, so y
|
||||
/debug/pprof/cmdline
|
||||
/debug/pprof/profile
|
||||
/debug/pprof/symbol
|
||||
|
||||
For more information about pprof, please read [pprof](http://golang.org/pkg/net/http/pprof/)
|
||||
|
||||
|
||||
For more information about pprof, please read [pprof](http://golang.org/pkg/net/http/pprof/)
|
||||
|
||||
* ViewsPath
|
||||
|
||||
Template path, default is "views".
|
||||
|
||||
|
||||
* SessionOn
|
||||
|
||||
This value indicate whether enable session or not, default is false.
|
||||
|
||||
|
||||
* SessionProvider
|
||||
|
||||
Session engine, default is memory.
|
||||
|
||||
|
||||
* SessionName
|
||||
|
||||
Name for cookie that save in client browser, default is "beegosessionID".
|
||||
|
||||
|
||||
* SessionGCMaxLifetime
|
||||
|
||||
Session expired time, default is 3600 seconds.
|
||||
|
||||
|
||||
* SessionSavePath
|
||||
|
||||
Save path of session, default is empty.
|
||||
|
||||
|
||||
* UseFcgi
|
||||
|
||||
This value indicates whether enable fastcgi or not, default is false.
|
||||
|
||||
|
||||
* MaxMemory
|
||||
|
||||
Maximum memory size for file upload, default is `1 << 26`(64M).
|
||||
@ -944,11 +1021,13 @@ Beego has many configurable arguments, let me introduce to you all of them, so y
|
||||
|
||||
This value indicate whether enable gzip or not, default is false.
|
||||
|
||||
##Integrated third-party applications
|
||||
|
||||
## Integrated third-party applications
|
||||
|
||||
Beego supports to integrate third-party application, you can customized `http.Handler` as follows:
|
||||
|
||||
beego.RouterHandler("/chat/:info(.*)", sockjshandler)
|
||||
|
||||
|
||||
sockjshandler implemented interface `http.Handler`.
|
||||
|
||||
Beego has an example for supporting chat of sockjs, here is the code:
|
||||
@ -967,7 +1046,7 @@ Beego has an example for supporting chat of sockjs, here is the code:
|
||||
func chatHandler(s sockjs.Session) {
|
||||
users.Add(s)
|
||||
defer users.Remove(s)
|
||||
|
||||
|
||||
for {
|
||||
m := s.Receive()
|
||||
if m == nil {
|
||||
@ -998,7 +1077,9 @@ Beego has an example for supporting chat of sockjs, here is the code:
|
||||
|
||||
The above example implemented a simple chat room for sockjs, and you can use `http.Handler` for more extensions.
|
||||
|
||||
##Deployment
|
||||
|
||||
## Deployment
|
||||
|
||||
Go compiles program to binary file, you only need to copy this binary to your server and run it. Because Beego uses MVC model, so you may have folders for static files, configuration files and template files, so you have to copy those files as well. Here is a real example for deployment.
|
||||
|
||||
$ mkdir /opt/app/beepkg
|
||||
@ -1006,7 +1087,7 @@ Go compiles program to binary file, you only need to copy this binary to your se
|
||||
$ cp -fr views /opt/app/beepkg
|
||||
$ cp -fr static /opt/app/beepkg
|
||||
$ cp -fr conf /opt/app/beepkg
|
||||
|
||||
|
||||
Here is the directory structure pf `/opt/app/beepkg`.
|
||||
|
||||
.
|
||||
@ -1018,12 +1099,12 @@ Here is the directory structure pf `/opt/app/beepkg`.
|
||||
│ └── js
|
||||
└── views
|
||||
└── index.tpl
|
||||
├── beepkg
|
||||
├── beepkg
|
||||
|
||||
Now you can run your application in server, here are two good ways to manage your applications, and I recommend the first one.
|
||||
|
||||
- Supervisord
|
||||
|
||||
|
||||
More information: [Supervisord](Supervisord.md)
|
||||
|
||||
- nohup
|
||||
@ -1031,4 +1112,4 @@ Now you can run your application in server, here are two good ways to manage you
|
||||
nohup ./beepkg &
|
||||
|
||||
- [Introduction](README.md)
|
||||
- [Step by step](Tutorial.md)
|
||||
- [Step by step](Tutorial.md)
|
||||
|
@ -1,4 +1,5 @@
|
||||
#Beego
|
||||
# Beego
|
||||
|
||||
Beego is a lightweight, open source, non-blocking and scalable web framework for the Go programming language. It's like tornado in Python. This web framework has already been using for building web server and tools in SNDA's CDN system. Documentation and downloads available at [http://astaxie.github.com/beego](http://astaxie.github.com/beego)
|
||||
|
||||
It has following main features:
|
||||
@ -19,29 +20,33 @@ The working principles of Beego as follows:
|
||||
Beego is licensed under the Apache Licence, Version 2.0
|
||||
(http://www.apache.org/licenses/LICENSE-2.0.html).
|
||||
|
||||
#Simple example
|
||||
|
||||
# Simple example
|
||||
|
||||
The following example prints string "Hello world" to your browser, it shows how easy to build a web application with Beego.
|
||||
|
||||
package main
|
||||
|
||||
|
||||
import (
|
||||
"github.com/astaxie/beego"
|
||||
"github.com/astaxie/beego"
|
||||
)
|
||||
|
||||
|
||||
type MainController struct {
|
||||
beego.Controller
|
||||
beego.Controller
|
||||
}
|
||||
|
||||
|
||||
func (this *MainController) Get() {
|
||||
this.Ctx.WriteString("hello world")
|
||||
this.Ctx.WriteString("hello world")
|
||||
}
|
||||
|
||||
|
||||
func main() {
|
||||
beego.Router("/", &MainController{})
|
||||
beego.Run()
|
||||
beego.Router("/", &MainController{})
|
||||
beego.Run()
|
||||
}
|
||||
|
||||
#Handbook
|
||||
|
||||
# Handbook
|
||||
|
||||
- [Purposes](Why.md)
|
||||
- [Installation](Install.md)
|
||||
- [Quick start](Quickstart.md)
|
||||
@ -49,5 +54,7 @@ The following example prints string "Hello world" to your browser, it shows how
|
||||
- [Real world usage](Application.md)
|
||||
- [Hot update](HotUpdate.md)
|
||||
|
||||
#Documentation
|
||||
[Go Walker](http://gowalker.org/github.com/astaxie/beego)
|
||||
|
||||
# Documentation
|
||||
|
||||
[Go Walker](http://gowalker.org/github.com/astaxie/beego)
|
||||
|
@ -1,22 +1,22 @@
|
||||
##supervisord
|
||||
## supervisord
|
||||
|
||||
1. Installation
|
||||
|
||||
wget http://pypi.python.org/packages/2.7/s/setuptools/setuptools-0.6c11-py2.7.egg
|
||||
|
||||
sh setuptools-0.6c11-py2.7.egg
|
||||
|
||||
|
||||
sh setuptools-0.6c11-py2.7.egg
|
||||
|
||||
easy_install supervisor
|
||||
|
||||
|
||||
echo_supervisord_conf >/etc/supervisord.conf
|
||||
|
||||
|
||||
mkdir /etc/supervisord.conf.d
|
||||
|
||||
2. Configure /etc/supervisord.conf
|
||||
|
||||
2. Configure /etc/supervisord.conf
|
||||
|
||||
[include]
|
||||
files = /etc/supervisord.conf.d/*.conf
|
||||
|
||||
|
||||
3. Add new application
|
||||
|
||||
cd /etc/supervisord.conf.d
|
||||
@ -31,4 +31,4 @@
|
||||
startsecs = 5
|
||||
user = root
|
||||
redirect_stderr = true
|
||||
stdout_logfile = /var/log/supervisord/beepkg.log
|
||||
stdout_logfile = /var/log/supervisord/beepkg.log
|
||||
|
@ -1,13 +1,19 @@
|
||||
# 一步一步跟我写博客
|
||||
|
||||
|
||||
## 创建项目
|
||||
|
||||
|
||||
## 数据库结构设计
|
||||
|
||||
|
||||
## 控制器设计
|
||||
|
||||
|
||||
## 模板设计
|
||||
|
||||
|
||||
## 用户登陆退出
|
||||
|
||||
## 数据库操作
|
||||
|
||||
## 数据库操作
|
||||
|
@ -1,4 +1,5 @@
|
||||
# Design purposes and ideas
|
||||
|
||||
People may ask me why I want to build a new web framework rather than use other good ones. I know there are many excellent web frameworks on the internet and almost all of them are open source, and I have my reasons to do this.
|
||||
|
||||
Remember when I was writing the book about how to build web applications with Go, I just wanted to tell people what were my valuable experiences with Go in web development, especially I have been working with PHP and Python for almost ten years. At first, I didn't realize that a small web framework can give great help to web developers when they are learning to build web applications in a new programming language, and it also helps people more by studying its source code. Finally, I decided to write a open source web framework called Beego as supporting materiel for my book.
|
||||
@ -9,11 +10,11 @@ I used to use CI in PHP and tornado in Python, there are both lightweight, so th
|
||||
2. Learn more about languages by studying their source code, it's not hard to read and understand them because they are both lightweight frameworks.
|
||||
3. It's quite easy to make secondary development of these frameworks for specific purposes.
|
||||
|
||||
Those reasons are my original intention of implementing Beego, and used two chapters in my book to introduce and design this lightweight web framework in GO.
|
||||
Those reasons are my original intention of implementing Beego, and used two chapters in my book to introduce and design this lightweight web framework in Go.
|
||||
|
||||
Then I started to design logic execution of Beego. Because Go and Python have somewhat similar, I referenced some ideas from tornado to design Beego. As you can see, there is no different between Beego and tornado in RESTful processing; they both use GET, POST or some other methods to implement RESTful. I took some ideas from [https://github.com/drone/routes](https://github.com/drone/routes) at the beginning of designing routes. It uses regular expression in route rules processing, which is an excellent idea that to make up for the default Mux router function in Go. However, I have to design my own interface in order to implement RESTful and use inherited ideas in Python.
|
||||
|
||||
The controller is the most important part of whole MVC model, and Beego uses the interface and ideas I said above for the controller. Although I haven't decided to have to design the model part, everyone is welcome to implement data management by referencing Beedb, my another open source project. I simply adopt Go built-in template engine for the view part, but add more commonly used functions as template functions. This is how a simple web framework looks like, but I'll keep working on form processing, session handling, log recording, configuration, automated operation, etc, to build a simple but complete web framework.
|
||||
|
||||
- [Introduction](README.md)
|
||||
- [Installation](Install.md)
|
||||
- [Installation](Install.md)
|
||||
|
@ -2,10 +2,12 @@
|
||||
|
||||
热升级是什么呢?了解nginx的同学都知道,nginx是支持热升级的,可以用老进程服务先前链接的链接,使用新进程服务新的链接,即在不停止服务的情况下完成系统的升级与运行参数修改。那么热升级和热编译是不同的概念,热编译是通过监控文件的变化重新编译,然后重启进程,例如bee start就是这样的工具
|
||||
|
||||
|
||||
## 热升级有必要吗?
|
||||
|
||||
很多人认为HTTP的应用有必要支持热升级吗?那么我可以很负责的说非常有必要,不中断服务始终是我们所追求的目标,虽然很多人说可能服务器会坏掉等等,这个是属于高可用的设计范畴,不要搞混了,这个是可预知的问题,所以我们需要避免这样的升级带来的用户不可用。你还在为以前升级搞到凌晨升级而烦恼嘛?那么现在就赶紧拥抱热升级吧。
|
||||
|
||||
|
||||
## beego如何支持热升级
|
||||
热升级的原理基本上就是:主进程fork一个进程,然后子进程exec相应的程序。那么这个过程中发生了什么呢?我们知道进程fork之后会把主进程的所有句柄、数据和堆栈继承过来、但是里面所有的句柄存在一个叫做CloseOnExec,也就是执行exec的时候,copy的所有的句柄都被关闭了,除非特别申明,而我们期望的是子进程能够复用主进程的net.Listener的句柄。一个进程一旦调用exec类函数,它本身就"死亡"了,系统把代码段替换成新的程序的代码,废弃原有的数据段和堆栈段,并为新程序分配新的数据段与堆栈段,唯一留下的,就是进程号,也就是说,对系统而言,还是同一个进程,不过已经是另一个程序了。
|
||||
|
||||
@ -17,6 +19,7 @@
|
||||
|
||||
上面是我们需要解决的三个方面的问题,具体的实现大家可以看我实现的代码逻辑。
|
||||
|
||||
|
||||
## 如何演示热升级
|
||||
|
||||
1. 编写代码,在beego应用的控制器中Get方法实现大概如下:
|
||||
@ -28,15 +31,15 @@
|
||||
}
|
||||
|
||||
2. 打开两个终端
|
||||
|
||||
|
||||
一个终端输入:` ps -ef|grep 应用名`
|
||||
|
||||
|
||||
一个终端输入请求:`curl "http://127.0.0.1:8080/?sleep=20"`
|
||||
|
||||
3. 热升级
|
||||
|
||||
3. 热升级
|
||||
|
||||
`kill -HUP 进程ID`
|
||||
|
||||
4. 打开一个终端输入请求:`curl "http://127.0.0.1:8080/?sleep=0"`
|
||||
|
||||
我们可以看到这样的结果,第一个请求等待20s,但是处理他的是老的进程,热升级之后,第一个请求还在执行,最后会输出老的进程ID,而第二次请求,输出的是新的进程ID
|
||||
4. 打开一个终端输入请求:`curl "http://127.0.0.1:8080/?sleep=0"`
|
||||
|
||||
我们可以看到这样的结果,第一个请求等待20s,但是处理他的是老的进程,热升级之后,第一个请求还在执行,最后会输出老的进程ID,而第二次请求,输出的是新的进程ID
|
||||
|
@ -1,4 +1,5 @@
|
||||
# 安装入门
|
||||
|
||||
beego虽然是一个简单的框架,但是其中用到了很多第三方的包,所以在你安装beego的过程中Go会自动安装其他关联的包。
|
||||
|
||||
- 当然第一步你需要安装Go,如何安装Go请参考我的书[第一章](https://github.com/astaxie/build-web-application-with-golang/blob/master/ebook/01.1.md)
|
||||
@ -6,10 +7,10 @@ beego虽然是一个简单的框架,但是其中用到了很多第三方的包
|
||||
- 安装beego
|
||||
|
||||
go get github.com/astaxie/beego
|
||||
|
||||
|
||||
- 安装bee工具,这个工具可以用来快速的建立beego的应用
|
||||
|
||||
go get github.com/astaxie/bee
|
||||
go get github.com/astaxie/bee
|
||||
|
||||
这样就完成了beego的安装,你就可以开始开发了,可以通过bee工具来创建beego项目
|
||||
|
||||
@ -19,6 +20,7 @@ beego虽然是一个简单的框架,但是其中用到了很多第三方的包
|
||||
|
||||
> - session模块:github.com/astaxie/beego/session
|
||||
|
||||
|
||||
> - session模块中支持redis引擎:github.com/garyburd/redigo/redis
|
||||
|
||||
> - session模块中支持mysql引擎:github.com/go-sql-driver/mysql
|
||||
@ -27,4 +29,4 @@ beego虽然是一个简单的框架,但是其中用到了很多第三方的包
|
||||
|
||||
|
||||
- [beego介绍](README.md)
|
||||
- [快速入门](Quickstart.md)
|
||||
- [快速入门](Quickstart.md)
|
||||
|
@ -1,4 +1,5 @@
|
||||
# 快速入门
|
||||
|
||||
你对beego一无所知?没关系,这篇文档会很好的详细介绍beego的各个方面,看这个文档之前首先确认你已经安装了beego,如果你没有安装的话,请看这篇[安装指南](Install.md)
|
||||
|
||||
**导航**
|
||||
@ -23,11 +24,13 @@
|
||||
- [第三方应用集成](#-19)
|
||||
- [部署编译应用](#-20)
|
||||
|
||||
|
||||
## 最小应用
|
||||
|
||||
一个最小最简单的应用如下代码所示:
|
||||
|
||||
package main
|
||||
|
||||
|
||||
import (
|
||||
"github.com/astaxie/beego"
|
||||
)
|
||||
@ -59,7 +62,7 @@
|
||||
2、定义Controller,这里我们定义了一个struct为`MainController`,充分利用了Go语言的组合的概念,匿名包含了`beego.Controller`,这样我们的`MainController`就拥有了`beego.Controller`的所有方法。
|
||||
|
||||
3、定义RESTFul方法,通过匿名组合之后,其实目前的`MainController`已经拥有了`Get`、`Post`、`Delete`、`Put`等方法,这些方法是分别用来对应用户请求的Method函数,如果用户发起的是`POST`请求,那么就执行`Post`函数。所以这里我们定义了`MainController`的`Get`方法用来重写继承的`Get`函数,这样当用户`GET`请求的时候就会执行该函数。
|
||||
|
||||
|
||||
4、定义main函数,所有的Go应用程序和C语言一样都是Main函数作为入口,所以我们这里定义了我们应用的入口。
|
||||
|
||||
5、Router注册路由,路由就是告诉beego,当用户来请求的时候,该如何去调用相应的Controller,这里我们注册了请求`/`的时候,请求到`MainController`。这里我们需要知道,Router函数的两个参数函数,第一个是路径,第二个是Controller的指针。
|
||||
@ -68,12 +71,13 @@
|
||||
|
||||
停止服务的话,请按`ctrl+c`
|
||||
|
||||
|
||||
## 新建项目
|
||||
|
||||
通过如下命令创建beego项目,首先进入gopath目录
|
||||
|
||||
bee create hello
|
||||
|
||||
|
||||
这样就建立了一个项目hello,目录结构如下所示
|
||||
|
||||
.
|
||||
@ -90,10 +94,11 @@
|
||||
└── views
|
||||
└── index.tpl
|
||||
|
||||
|
||||
## 开发模式
|
||||
|
||||
通过bee创建的项目,beego默认情况下是开发模式。
|
||||
|
||||
|
||||
我们可以通过如下的方式改变我们的模式:
|
||||
|
||||
beego.RunMode = "pro"
|
||||
@ -115,6 +120,7 @@
|
||||
|
||||
![](images/dev.png)
|
||||
|
||||
|
||||
## 路由设置
|
||||
|
||||
路由的主要功能是实现从请求地址到实现方法,beego中封装了`Controller`,所以路由是从路径到`ControllerInterface`的过程,`ControllerInterface`的方法有如下:
|
||||
@ -144,40 +150,42 @@
|
||||
|
||||
为了用户更加方便的路由设置,beego参考了sinatra的路由实现,支持多种方式的路由:
|
||||
|
||||
- beego.Router("/api/:id([0-9]+)", &controllers.RController{})
|
||||
自定义正则匹配 //匹配 /api/123 :id= 123
|
||||
- beego.Router("/api/:id([0-9]+)", &controllers.RController{})
|
||||
自定义正则匹配 //匹配 /api/123 :id= 123
|
||||
|
||||
- beego.Router("/news/:all", &controllers.RController{})
|
||||
- beego.Router("/news/:all", &controllers.RController{})
|
||||
全匹配方式 //匹配 /news/path/to/123.html :all= path/to/123.html
|
||||
|
||||
- beego.Router(\`/user/:username([\w]+)\`, &controllers.RController{})
|
||||
|
||||
- beego.Router(\`/user/:username([\w]+)\`, &controllers.RController{})
|
||||
正则字符串匹配 //匹配 /user/astaxie :username = astaxie
|
||||
|
||||
- beego.Router("/download/*.*", &controllers.RController{})
|
||||
- beego.Router("/download/*.*", &controllers.RController{})
|
||||
*匹配方式 //匹配 /download/file/api.xml :path= file/api :ext=xml
|
||||
|
||||
|
||||
- beego.Router("/download/ceshi/*", &controllers.RController{})
|
||||
*全匹配方式 //匹配 /download/ceshi/file/api.json :splat=file/api.json
|
||||
|
||||
|
||||
- beego.Router("/:id:int", &controllers.RController{})
|
||||
int类型设置方式 //匹配 :id为int类型,框架帮你实现了正则([0-9]+)
|
||||
|
||||
|
||||
- beego.Router("/:hi:string", &controllers.RController{})
|
||||
string类型设置方式 //匹配 :hi为string类型。框架帮你实现了正则([\w]+)
|
||||
|
||||
|
||||
如何在Controller中获取,上面的变量可以通过如下方式获取
|
||||
|
||||
this.Ctx.Params[":id"]
|
||||
this.Ctx.Params[":username"]
|
||||
this.Ctx.Params[":splat"]
|
||||
this.Ctx.Params[":path"]
|
||||
this.Ctx.Params[":ext"]
|
||||
this.Ctx.Params[":id"]
|
||||
this.Ctx.Params[":username"]
|
||||
this.Ctx.Params[":splat"]
|
||||
this.Ctx.Params[":path"]
|
||||
this.Ctx.Params[":ext"]
|
||||
|
||||
|
||||
## 静态文件
|
||||
|
||||
Go语言内部其实已经提供了`http.ServeFile`,通过这个函数可以实现静态文件的服务。beego针对这个功能进行了一层封装,通过下面的方式进行静态文件注册:
|
||||
|
||||
beego.SetStaticPath("/static","public")
|
||||
|
||||
|
||||
- 第一个参数是路径,url路径信息
|
||||
- 第二个参数是静态文件目录(相对应用所在的目录)
|
||||
|
||||
@ -189,37 +197,41 @@ beego支持多个目录的静态文件注册,用户可以注册如下的静态
|
||||
|
||||
设置了如上的静态目录之后,用户访问`/images/login/login.png`,那么就会访问应用对应的目录下面的`images/login/login.png`文件。如果是访问`/static/img/logo.png`,那么就访问`public/img/logo.png`文件。
|
||||
|
||||
|
||||
## 过滤和中间件
|
||||
|
||||
beego支持自定义过滤中间件,例如安全验证,强制跳转等
|
||||
|
||||
如下例子所示,验证用户名是否是admin,应用于全部的请求:
|
||||
|
||||
var FilterUser = func(w http.ResponseWriter, r *http.Request) {
|
||||
if r.URL.User == nil || r.URL.User.Username() != "admin" {
|
||||
http.Error(w, "", http.StatusUnauthorized)
|
||||
}
|
||||
if r.URL.User == nil || r.URL.User.Username() != "admin" {
|
||||
http.Error(w, "", http.StatusUnauthorized)
|
||||
}
|
||||
}
|
||||
|
||||
beego.Filter(FilterUser)
|
||||
|
||||
beego.Filter(FilterUser)
|
||||
|
||||
还可以通过参数进行过滤,如果匹配参数就执行
|
||||
|
||||
beego.Router("/:id([0-9]+)", &admin.EditController{})
|
||||
beego.FilterParam("id", func(rw http.ResponseWriter, r *http.Request) {
|
||||
dosomething()
|
||||
dosomething()
|
||||
})
|
||||
|
||||
|
||||
当然你还可以通过前缀过滤
|
||||
|
||||
beego.FilterPrefixPath("/admin", func(rw http.ResponseWriter, r *http.Request) {
|
||||
dosomething()
|
||||
dosomething()
|
||||
})
|
||||
|
||||
|
||||
## 控制器设计
|
||||
|
||||
基于beego的Controller设计,只需要匿名组合`beego.Controller`就可以了,如下所示:
|
||||
|
||||
type xxxController struct {
|
||||
beego.Controller
|
||||
beego.Controller
|
||||
}
|
||||
|
||||
`beego.Controller`实现了接口`beego.ControllerInterface`,`beego.ControllerInterface`定义了如下函数:
|
||||
@ -227,15 +239,15 @@ beego支持自定义过滤中间件,例如安全验证,强制跳转等
|
||||
- Init(ct *Context, cn string)
|
||||
|
||||
这个函数主要初始化了Context、相应的Controller名称,模板名,初始化模板参数的容器Data
|
||||
|
||||
|
||||
- Prepare()
|
||||
|
||||
这个函数主要是为了用户扩展用的,这个函数会在下面定义的这些Method方法之前执行,用户可以重写这个函数实现类似用户验证之类。
|
||||
|
||||
|
||||
- Get()
|
||||
|
||||
如果用户请求的HTTP Method是GET, 那么就执行该函数,默认是403,用户继承的子struct中可以实现了该方法以处理Get请求.
|
||||
|
||||
|
||||
- Post()
|
||||
|
||||
如果用户请求的HTTP Method是POST, 那么就执行该函数,默认是403,用户继承的子struct中可以实现了该方法以处理Post请求.
|
||||
@ -271,60 +283,71 @@ beego支持自定义过滤中间件,例如安全验证,强制跳转等
|
||||
所以通过子struct的方法重写,用户就可以实现自己的逻辑,接下来我们看一个实际的例子:
|
||||
|
||||
type AddController struct {
|
||||
beego.Controller
|
||||
beego.Controller
|
||||
}
|
||||
|
||||
func (this *AddController) Prepare() {
|
||||
|
||||
}
|
||||
|
||||
func (this *AddController) Get() {
|
||||
this.Data["content"] ="value"
|
||||
this.Layout = "admin/layout.html"
|
||||
this.TplNames = "admin/add.tpl"
|
||||
}
|
||||
|
||||
func (this *AddController) Post() {
|
||||
pkgname := this.GetString("pkgname")
|
||||
content := this.GetString("content")
|
||||
pk := models.GetCruPkg(pkgname)
|
||||
if pk.Id == 0 {
|
||||
var pp models.PkgEntity
|
||||
pp.Pid = 0
|
||||
pp.Pathname = pkgname
|
||||
pp.Intro = pkgname
|
||||
models.InsertPkg(pp)
|
||||
pk = models.GetCruPkg(pkgname)
|
||||
}
|
||||
var at models.Article
|
||||
at.Pkgid = pk.Id
|
||||
at.Content = content
|
||||
models.InsertArticle(at)
|
||||
this.Ctx.Redirect(302, "/admin/index")
|
||||
}
|
||||
|
||||
func (this *AddController) Prepare() {
|
||||
|
||||
}
|
||||
|
||||
func (this *AddController) Get() {
|
||||
this.Data["content"] = "value"
|
||||
this.Layout = "admin/layout.html"
|
||||
this.TplNames = "admin/add.tpl"
|
||||
}
|
||||
|
||||
func (this *AddController) Post() {
|
||||
pkgname := this.GetString("pkgname")
|
||||
content := this.GetString("content")
|
||||
pk := models.GetCruPkg(pkgname)
|
||||
if pk.Id == 0 {
|
||||
var pp models.PkgEntity
|
||||
pp.Pid = 0
|
||||
pp.Pathname = pkgname
|
||||
pp.Intro = pkgname
|
||||
models.InsertPkg(pp)
|
||||
pk = models.GetCruPkg(pkgname)
|
||||
}
|
||||
var at models.Article
|
||||
at.Pkgid = pk.Id
|
||||
at.Content = content
|
||||
models.InsertArticle(at)
|
||||
this.Ctx.Redirect(302, "/admin/index")
|
||||
}
|
||||
|
||||
|
||||
## 模板处理
|
||||
|
||||
|
||||
### 模板目录
|
||||
|
||||
beego中默认的模板目录是`views`,用户可以把你的模板文件放到该目录下,beego会自动在该目录下的所有模板文件进行解析并缓存,开发模式下会每次重新解析,不做缓存。当然用户可以通过如下的方式改变模板的目录:
|
||||
|
||||
beego.ViewsPath = "/myviewpath"
|
||||
|
||||
|
||||
### 自动渲染
|
||||
|
||||
beego中用户无需手动的调用渲染输出模板,beego会自动的在调用完相应的method方法之后调用Render函数,当然如果你的应用是不需要模板输出的,那么你可以在配置文件或者在main.go中设置关闭自动渲染。
|
||||
|
||||
配置文件配置如下:
|
||||
|
||||
|
||||
autorender = false
|
||||
|
||||
main.go文件中设置如下:
|
||||
|
||||
beego.AutoRender = false
|
||||
|
||||
|
||||
|
||||
### 模板数据
|
||||
|
||||
模板中的数据是通过在Controller中`this.Data`获取的,所以如果你想在模板中获取内容`{{.Content}}`,那么你需要在Controller中如下设置:
|
||||
|
||||
|
||||
this.Data["Context"] = "value"
|
||||
|
||||
|
||||
|
||||
### 模板名称
|
||||
|
||||
beego采用了Go语言内置的模板引擎,所有模板的语法和Go的一模一样,至于如何写模板文件,详细的请参考[模板教程](https://github.com/astaxie/build-web-application-with-golang/blob/master/ebook/07.4.md)。
|
||||
|
||||
用户通过在Controller的对应方法中设置相应的模板名称,beego会自动的在viewpath目录下查询该文件并渲染,例如下面的设置,beego会在admin下面找add.tpl文件进行渲染:
|
||||
@ -341,16 +364,18 @@ beego采用了Go语言内置的模板引擎,所有模板的语法和Go的一
|
||||
|
||||
也就是你对应的Controller名字+请求方法名.模板后缀,也就是如果你的Controller名是`AddController`,请求方法是`POST`,默认的文件后缀是`tpl`,那么就会默认请求`/viewpath/AddController/POST.tpl`文件。
|
||||
|
||||
|
||||
### layout设计
|
||||
|
||||
beego支持layout设计,例如你在管理系统中,其实整个的管理界面是固定的,只会变化中间的部分,那么你可以通过如下的设置:
|
||||
|
||||
|
||||
this.Layout = "admin/layout.html"
|
||||
this.TplNames = "admin/add.tpl"
|
||||
|
||||
在layout.html中你必须设置如下的变量:
|
||||
|
||||
{{.LayoutContent}}
|
||||
|
||||
|
||||
beego就会首先解析TplNames指定的文件,获取内容赋值给LayoutContent,然后最后渲染layout.html文件。
|
||||
|
||||
目前采用首先把目录下所有的文件进行缓存,所以用户还可以通过类似这样的方式实现layout:
|
||||
@ -359,12 +384,14 @@ beego就会首先解析TplNames指定的文件,获取内容赋值给LayoutCont
|
||||
处理逻辑
|
||||
{{template "footer.html"}}
|
||||
|
||||
|
||||
### 模板函数
|
||||
|
||||
beego支持用户定义模板函数,但是必须在`beego.Run()`调用之前,设置如下:
|
||||
|
||||
func hello(in string)(out string){
|
||||
out = in + "world"
|
||||
return
|
||||
out = in + "world"
|
||||
return
|
||||
}
|
||||
|
||||
beego.AddFuncMap("hi",hello)
|
||||
@ -375,35 +402,45 @@ beego支持用户定义模板函数,但是必须在`beego.Run()`调用之前
|
||||
|
||||
目前beego内置的模板函数有如下:
|
||||
|
||||
* markdown
|
||||
|
||||
* markdown
|
||||
|
||||
实现了把markdown文本转化为html信息,使用方法{{markdown .Content}}
|
||||
* dateformat
|
||||
|
||||
* dateformat
|
||||
|
||||
实现了时间的格式化,返回字符串,使用方法{{dateformat .Time "2006-01-02T15:04:05Z07:00"}}
|
||||
* date
|
||||
|
||||
* date
|
||||
|
||||
实现了类似PHP的date函数,可以很方便的根据字符串返回时间,使用方法{{date .T "Y-m-d H:i:s"}}
|
||||
* compare
|
||||
|
||||
* compare
|
||||
|
||||
实现了比较两个对象的比较,如果相同返回true,否者false,使用方法{{compare .A .B}}
|
||||
* substr
|
||||
|
||||
* substr
|
||||
|
||||
实现了字符串的截取,支持中文截取的完美截取,使用方法{{substr .Str 0 30}}
|
||||
* html2str
|
||||
|
||||
* html2str
|
||||
|
||||
实现了把html转化为字符串,剔除一些script、css之类的元素,返回纯文本信息,使用方法{{html2str .Htmlinfo}}
|
||||
* str2html
|
||||
|
||||
* str2html
|
||||
|
||||
实现了把相应的字符串当作HTML来输出,不转义,使用方法{{str2html .Strhtml}}
|
||||
* htmlquote
|
||||
|
||||
* htmlquote
|
||||
|
||||
实现了基本的html字符转义,使用方法{{htmlquote .quote}}
|
||||
* htmlunquote
|
||||
|
||||
* htmlunquote
|
||||
|
||||
实现了基本的反转移字符,使用方法{{htmlunquote .unquote}}
|
||||
|
||||
|
||||
|
||||
## request处理
|
||||
|
||||
我们经常需要获取用户传递的数据,包括Get、POST等方式的请求,beego里面会自动解析这些数据,你可以通过如下方式获取数据
|
||||
|
||||
- GetString(key string) string
|
||||
@ -425,16 +462,18 @@ beego支持用户定义模板函数,但是必须在`beego.Run()`调用之前
|
||||
func (this *MainController) Post() {
|
||||
id := this.Input().Get("id")
|
||||
intid, err := strconv.Atoi(id)
|
||||
}
|
||||
}
|
||||
|
||||
更多其他的request的信息,用户可以通过`this.Ctx.Request`获取信息,关于该对象的属性和方法参考手册[Request](http://golang.org/pkg/net/http/#Request)
|
||||
|
||||
|
||||
### 文件上传
|
||||
|
||||
在beego中你可以很容易的处理文件上传,就是别忘记在你的form表单中增加这个属性`enctype="multipart/form-data"`,否者你的浏览器不会传输你的上传文件。
|
||||
|
||||
文件上传之后一般是放在系统的内存里面,如果文件的size大于设置的缓存内存大小,那么就放在临时文件中,默认的缓存内存是64M,你可以通过如下来调整这个缓存内存大小:
|
||||
|
||||
beego.MaxMemory = 1<<22
|
||||
beego.MaxMemory = 1<<22
|
||||
|
||||
或者在配置文件中通过如下设置
|
||||
|
||||
@ -445,42 +484,46 @@ beego提供了两个很方便的方法来处理文件上传:
|
||||
- GetFile(key string) (multipart.File, *multipart.FileHeader, error)
|
||||
|
||||
该方法主要用于用户读取表单中的文件名`the_file`,然后返回相应的信息,用户根据这些变量来处理文件上传:过滤、保存文件等。
|
||||
|
||||
|
||||
- SaveToFile(fromfile, tofile string) error
|
||||
|
||||
该方法是在GetFile的基础上实现了快速保存的功能
|
||||
|
||||
|
||||
保存的代码例子如下:
|
||||
|
||||
|
||||
func (this *MainController) Post() {
|
||||
this.SaveToFile("the_file","/var/www/uploads/uploaded_file.txt"")
|
||||
}
|
||||
|
||||
|
||||
### JSON和XML输出
|
||||
|
||||
beego当初设计的时候就考虑了API功能的设计,而我们在设计API的时候经常是输出JSON或者XML数据,那么beego提供了这样的方式直接输出:
|
||||
|
||||
JSON数据直接输出,设置`content-type`为`application/json`:
|
||||
|
||||
func (this *AddController) Get() {
|
||||
mystruct := { ... }
|
||||
this.Data["json"] = &mystruct
|
||||
this.ServeJson()
|
||||
}
|
||||
mystruct := { ... }
|
||||
this.Data["json"] = &mystruct
|
||||
this.ServeJson()
|
||||
}
|
||||
|
||||
XML数据直接输出,设置`content-type`为`application/xml`:
|
||||
|
||||
func (this *AddController) Get() {
|
||||
mystruct := { ... }
|
||||
this.Data["xml"]=&mystruct
|
||||
this.ServeXml()
|
||||
}
|
||||
|
||||
mystruct := { ... }
|
||||
this.Data["xml"]=&mystruct
|
||||
this.ServeXml()
|
||||
}
|
||||
|
||||
|
||||
## 跳转和错误
|
||||
|
||||
我们在做Web开发的时候,经常会遇到页面调整和错误处理,beego这这方面也进行了考虑,通过`Redirect`方法来进行跳转:
|
||||
|
||||
func (this *AddController) Get() {
|
||||
this.Redirect("/", 302)
|
||||
}
|
||||
this.Redirect("/", 302)
|
||||
}
|
||||
|
||||
如何中止此次请求并抛出异常,beego可以在控制器中这操作
|
||||
|
||||
@ -494,12 +537,12 @@ XML数据直接输出,设置`content-type`为`application/xml`:
|
||||
this.SetSession("asta", v.(int)+1)
|
||||
this.Data["Email"] = v.(int)
|
||||
}
|
||||
this.TplNames = "index.tpl"
|
||||
this.TplNames = "index.tpl"
|
||||
}
|
||||
|
||||
这样`this.Abort("401")`之后的代码不会再执行,而且会默认显示给用户如下页面
|
||||
|
||||
![](images/401.png)
|
||||
![](images/401.png)
|
||||
|
||||
beego框架默认支持404、401、403、500、503这几种错误的处理。用户可以自定义相应的错误处理,例如下面重新定义404页面:
|
||||
|
||||
@ -514,7 +557,7 @@ beego框架默认支持404、401、403、500、503这几种错误的处理。用
|
||||
beego.Errorhandler("404",page_not_found)
|
||||
beego.Router("/", &controllers.MainController{})
|
||||
beego.Run()
|
||||
}
|
||||
}
|
||||
|
||||
我们可以通过自定义错误页面`404.html`来处理404错误。
|
||||
|
||||
@ -526,33 +569,37 @@ beego更加人性化的还有一个设计就是支持用户自定义字符串错
|
||||
data["content"] = "database is now down"
|
||||
t.Execute(rw, data)
|
||||
}
|
||||
|
||||
|
||||
func main() {
|
||||
beego.Errorhandler("dbError",dbError)
|
||||
beego.Router("/", &controllers.MainController{})
|
||||
beego.Run()
|
||||
}
|
||||
}
|
||||
|
||||
一旦在入口注册该错误处理代码,那么你可以在任何你的逻辑中遇到数据库错误调用`this.Abort("dbError")`来进行异常页面处理。
|
||||
|
||||
|
||||
## response处理
|
||||
|
||||
response可能会有集中情况:
|
||||
|
||||
1. 模板输出
|
||||
|
||||
模板输出上面模板介绍里面已经介绍,beego会在执行完相应的Controller里面的对应的Method之后输出到模板。
|
||||
|
||||
|
||||
2. 跳转
|
||||
|
||||
上一节介绍的跳转就是我们经常用到的页面之间的跳转
|
||||
|
||||
|
||||
3. 字符串输出
|
||||
|
||||
有些时候我们只是想输出相应的一个字符串,那么我们可以通过如下的代码实现
|
||||
|
||||
this.Ctx.WriteString("ok")
|
||||
|
||||
|
||||
## Sessions
|
||||
|
||||
beego内置了session模块,目前session模块支持的后端引擎包括memory、file、mysql、redis四中,用户也可以根据相应的interface实现自己的引擎。
|
||||
|
||||
beego中使用session相当方便,只要在main入口函数中设置如下:
|
||||
@ -604,21 +651,21 @@ sess对象具有如下方法:
|
||||
- SessionOn
|
||||
|
||||
设置是否开启Session,默认是false,配置文件对应的参数名:sessionon
|
||||
|
||||
|
||||
- SessionProvider
|
||||
|
||||
设置Session的引擎,默认是memory,目前支持还有file、mysql、redis等,配置文件对应的参数名:sessionprovider
|
||||
|
||||
|
||||
- SessionName
|
||||
|
||||
设置cookies的名字,Session默认是保存在用户的浏览器cookies里面的,默认名是beegosessionID,配置文件对应的参数名是:sessionname
|
||||
|
||||
|
||||
- SessionGCMaxLifetime
|
||||
|
||||
设置Session过期的时间,默认值是3600秒,配置文件对应的参数:sessiongcmaxlifetime
|
||||
|
||||
|
||||
- SessionSavePath
|
||||
|
||||
|
||||
设置对应file、mysql、redis引擎的保存路径或者链接地址,默认值是空,配置文件对应的参数:sessionsavepath
|
||||
|
||||
|
||||
@ -631,13 +678,15 @@ sess对象具有如下方法:
|
||||
|
||||
beego.SessionProvider = "mysql"
|
||||
beego.SessionSavePath = "username:password@protocol(address)/dbname?param=value"
|
||||
|
||||
|
||||
当SessionProvider为redis时,SessionSavePath是redis的链接地址,采用了[redigo](https://github.com/garyburd/redigo),如下所示:
|
||||
|
||||
beego.SessionProvider = "redis"
|
||||
beego.SessionSavePath = "127.0.0.1:6379"
|
||||
beego.SessionSavePath = "127.0.0.1:6379"
|
||||
|
||||
|
||||
## Cache设置
|
||||
|
||||
beego内置了一个cache模块,实现了类似memcache的功能,缓存数据在内存中,主要的使用方法如下:
|
||||
|
||||
var (
|
||||
@ -649,7 +698,7 @@ beego内置了一个cache模块,实现了类似memcache的功能,缓存数
|
||||
urllist.Every = 0 //不过期
|
||||
urllist.Start()
|
||||
}
|
||||
|
||||
|
||||
func (this *ShortController) Post() {
|
||||
var result ShortResult
|
||||
longurl := this.Input().Get("longurl")
|
||||
@ -672,8 +721,8 @@ beego内置了一个cache模块,实现了类似memcache的功能,缓存数
|
||||
}
|
||||
this.Data["json"] = result
|
||||
this.ServeJson()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
上面这个例子演示了如何使用beego的Cache模块,主要是通过`beego.NewBeeCache`初始化一个对象,然后设置过期时间,开启过期检测,在业务逻辑中就可以通过如下的接口进行增删改的操作:
|
||||
|
||||
- Get(name string) interface{}
|
||||
@ -681,7 +730,9 @@ beego内置了一个cache模块,实现了类似memcache的功能,缓存数
|
||||
- Delete(name string) (ok bool, err error)
|
||||
- IsExist(name string) bool
|
||||
|
||||
|
||||
## 安全的Map
|
||||
|
||||
我们知道在Go语言里面map是非线程安全的,详细的[atomic_maps](http://golang.org/doc/faq#atomic_maps)。但是我们在平常的业务中经常需要用到线程安全的map,特别是在goroutine的情况下,所以beego内置了一个简单的线程安全的map:
|
||||
|
||||
bm := NewBeeMap()
|
||||
@ -691,16 +742,16 @@ beego内置了一个cache模块,实现了类似memcache的功能,缓存数
|
||||
if !bm.Check("astaxie") {
|
||||
t.Error("check err")
|
||||
}
|
||||
|
||||
|
||||
if v := bm.Get("astaxie"); v.(int) != 1 {
|
||||
t.Error("get err")
|
||||
}
|
||||
|
||||
|
||||
bm.Delete("astaxie")
|
||||
if bm.Check("astaxie") {
|
||||
t.Error("delete err")
|
||||
}
|
||||
|
||||
|
||||
上面演示了如何使用线程安全的Map,主要的接口有:
|
||||
|
||||
- Get(k interface{}) interface{}
|
||||
@ -708,7 +759,9 @@ beego内置了一个cache模块,实现了类似memcache的功能,缓存数
|
||||
- Check(k interface{}) bool
|
||||
- Delete(k interface{})
|
||||
|
||||
|
||||
## 日志处理
|
||||
|
||||
beego默认有一个初始化的BeeLogger对象输出内容到stdout中,你可以通过如下的方式设置自己的输出:
|
||||
|
||||
beego.SetLogger(*log.Logger)
|
||||
@ -717,11 +770,13 @@ beego默认有一个初始化的BeeLogger对象输出内容到stdout中,你可
|
||||
|
||||
fd,err := os.OpenFile("/var/log/beeapp/beeapp.log", os.O_RDWR|os.O_APPEND, 0644)
|
||||
if err != nil {
|
||||
beego.Critical("openfile beeapp.log:", err)
|
||||
return
|
||||
beego.Critical("openfile beeapp.log:", err)
|
||||
return
|
||||
}
|
||||
lg := log.New(fd, "", log.Ldate|log.Ltime)
|
||||
beego.SetLogger(lg)
|
||||
|
||||
|
||||
### 不同级别的log日志函数
|
||||
|
||||
* Trace(v ...interface{})
|
||||
@ -734,84 +789,96 @@ beego默认有一个初始化的BeeLogger对象输出内容到stdout中,你可
|
||||
你可以通过下面的方式设置不同的日志分级:
|
||||
|
||||
beego.SetLevel(beego.LevelError)
|
||||
|
||||
|
||||
当你代码中有很多日志输出之后,如果想上线,但是你不想输出Trace、Debug、Info等信息,那么你可以设置如下:
|
||||
|
||||
beego.SetLevel(beego.LevelWarning)
|
||||
|
||||
这样的话就不会输出小于这个level的日志,日志的排序如下:
|
||||
|
||||
LevelTrace、LevelDebug、LevelInfo、LevelWarning、 LevelError、LevelCritical
|
||||
LevelTrace、LevelDebug、LevelInfo、LevelWarning、LevelError、LevelCritical
|
||||
|
||||
用户可以根据不同的级别输出不同的错误信息,如下例子所示:
|
||||
|
||||
|
||||
### Examples of log messages
|
||||
|
||||
- Trace
|
||||
|
||||
* "Entered parse function validation block"
|
||||
* "Validation: entered second 'if'"
|
||||
* "Dictionary 'Dict' is empty. Using default value"
|
||||
|
||||
- Debug
|
||||
|
||||
* "Web page requested: http://somesite.com Params='...'"
|
||||
* "Response generated. Response size: 10000. Sending."
|
||||
* "New file received. Type:PNG Size:20000"
|
||||
|
||||
- Info
|
||||
|
||||
* "Web server restarted"
|
||||
* "Hourly statistics: Requested pages: 12345 Errors: 123 ..."
|
||||
* "Service paused. Waiting for 'resume' call"
|
||||
|
||||
- Warn
|
||||
|
||||
* "Cache corrupted for file='test.file'. Reading from back-end"
|
||||
* "Database 192.168.0.7/DB not responding. Using backup 192.168.0.8/DB"
|
||||
* "No response from statistics server. Statistics not sent"
|
||||
|
||||
- Error
|
||||
|
||||
* "Internal error. Cannot process request #12345 Error:...."
|
||||
* "Cannot perform login: credentials DB not responding"
|
||||
|
||||
- Critical
|
||||
|
||||
* "Critical panic received: .... Shutting down"
|
||||
* "Fatal error: ... App is shutting down to prevent data corruption or loss"
|
||||
|
||||
|
||||
|
||||
### Example
|
||||
|
||||
func internalCalculationFunc(x, y int) (result int, err error) {
|
||||
beego.Debug("calculating z. x:",x," y:",y)
|
||||
beego.Debug("calculating z. x:", x, " y:", y)
|
||||
z := y
|
||||
switch {
|
||||
case x == 3 :
|
||||
case x == 3:
|
||||
beego.Trace("x == 3")
|
||||
panic("Failure.")
|
||||
case y == 1 :
|
||||
case y == 1:
|
||||
beego.Trace("y == 1")
|
||||
return 0, errors.New("Error!")
|
||||
case y == 2 :
|
||||
case y == 2:
|
||||
beego.Trace("y == 2")
|
||||
z = x
|
||||
default :
|
||||
default:
|
||||
beego.Trace("default")
|
||||
z += x
|
||||
}
|
||||
retVal := z-3
|
||||
retVal := z - 3
|
||||
beego.Debug("Returning ", retVal)
|
||||
|
||||
|
||||
return retVal, nil
|
||||
}
|
||||
}
|
||||
|
||||
func processInput(input inputData) {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
beego.Error("Unexpected error occurred: ", r)
|
||||
outputs <- outputData{result : 0, error : true}
|
||||
}
|
||||
beego.Error("Unexpected error occurred: ", r)
|
||||
outputs <- outputData{result: 0, error: true}
|
||||
}
|
||||
}()
|
||||
beego.Info("Received input signal. x:",input.x," y:", input.y)
|
||||
beego.Info("Received input signal. x:", input.x, " y:", input.y)
|
||||
|
||||
res, err := internalCalculationFunc(input.x, input.y)
|
||||
res, err := internalCalculationFunc(input.x, input.y)
|
||||
if err != nil {
|
||||
beego.Warn("Error in calculation:", err.Error())
|
||||
}
|
||||
|
||||
beego.Info("Returning result: ",res," error: ",err)
|
||||
outputs <- outputData{result : res, error : err != nil}
|
||||
beego.Info("Returning result: ", res, " error: ", err)
|
||||
outputs <- outputData{result: res, error: err != nil}
|
||||
}
|
||||
|
||||
func main() {
|
||||
@ -828,16 +895,18 @@ LevelTrace、LevelDebug、LevelInfo、LevelWarning、 LevelError、LevelCritical
|
||||
|
||||
for {
|
||||
select {
|
||||
case input := <- inputs:
|
||||
processInput(input)
|
||||
case <- criticalChan:
|
||||
beego.Critical("Caught value from criticalChan: Go shut down.")
|
||||
panic("Shut down due to critical fault.")
|
||||
}
|
||||
case input := <-inputs:
|
||||
processInput(input)
|
||||
case <-criticalChan:
|
||||
beego.Critical("Caught value from criticalChan: Go shut down.")
|
||||
panic("Shut down due to critical fault.")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
## 配置管理
|
||||
|
||||
beego支持解析ini文件, beego默认会解析当前应用下的`conf/app.conf`文件
|
||||
|
||||
通过这个文件你可以初始化很多beego的默认参数
|
||||
@ -849,7 +918,7 @@ beego支持解析ini文件, beego默认会解析当前应用下的`conf/app.conf
|
||||
autorender = false
|
||||
autorecover = false
|
||||
viewspath = "myview"
|
||||
|
||||
|
||||
上面这些参数会替换beego默认的一些参数。
|
||||
|
||||
你可以在配置文件中配置应用需要用的一些配置信息,例如下面所示的数据库信息:
|
||||
@ -858,7 +927,7 @@ beego支持解析ini文件, beego默认会解析当前应用下的`conf/app.conf
|
||||
mysqlpass = "rootpass"
|
||||
mysqlurls = "127.0.0.1"
|
||||
mysqldb = "beego"
|
||||
|
||||
|
||||
那么你就可以通过如下的方式获取设置的配置信息:
|
||||
|
||||
beego.AppConfig.String("mysqluser")
|
||||
@ -874,45 +943,47 @@ AppConfig支持如下方法
|
||||
- Float(key string) (float64, error)
|
||||
- String(key string) string
|
||||
|
||||
|
||||
## 系统默认参数
|
||||
|
||||
beego中带有很多可配置的参数,我们来一一认识一下它们,这样有利于我们在接下来的beego开发中可以充分的发挥他们的作用:
|
||||
|
||||
* BeeApp
|
||||
|
||||
beego默认启动的一个应用器入口,在应用import beego的时候,在init中已经初始化的。
|
||||
|
||||
|
||||
* AppConfig
|
||||
|
||||
beego的配置文件解析之后的对象,也是在init的时候初始化的,里面保存有解析`conf/app.conf`下面所有的参数数据
|
||||
|
||||
|
||||
* AppConfigPath
|
||||
|
||||
配置文件所在的路径,默认是应用程序对应的目录下的`conf/app.conf`,用户可以修改该值配置自己的配置文件
|
||||
|
||||
配置文件所在的路径,默认是应用程序对应的目录下的`conf/app.conf`,用户可以修改该值配置自己的配置文件
|
||||
|
||||
* HttpAddr
|
||||
|
||||
应用监听地址,默认为空,监听所有的网卡IP
|
||||
|
||||
|
||||
* HttpPort
|
||||
|
||||
应用监听端口,默认为8080
|
||||
|
||||
|
||||
* AppName
|
||||
|
||||
应用名称,默认是beego
|
||||
|
||||
* RunMode
|
||||
|
||||
* RunMode
|
||||
|
||||
应用的模式,默认是dev,为开发模式,在开发模式下出错会提示友好的出错页面,如前面错误描述中所述。
|
||||
|
||||
|
||||
* AutoRender
|
||||
|
||||
是否模板自动渲染,默认值为true,对于API类型的应用,应用需要把该选项设置为false,不需要渲染模板。
|
||||
|
||||
|
||||
* RecoverPanic
|
||||
|
||||
是否异常恢复,默认值为true,即当应用出现异常的情况,通过recover恢复回来,而不会导致应用异常退出。
|
||||
|
||||
|
||||
* PprofOn
|
||||
|
||||
是否启用pprof,默认是false,当开启之后,用户可以通过如下地址查看相应的goroutine执行情况
|
||||
@ -922,48 +993,50 @@ beego中带有很多可配置的参数,我们来一一认识一下它们,这
|
||||
/debug/pprof/profile
|
||||
/debug/pprof/symbol
|
||||
关于pprof的信息,请参考官方的描述[pprof](http://golang.org/pkg/net/http/pprof/)
|
||||
|
||||
|
||||
* ViewsPath
|
||||
|
||||
模板路径,默认值是views
|
||||
|
||||
|
||||
* SessionOn
|
||||
|
||||
session是否开启,默认是false
|
||||
|
||||
|
||||
* SessionProvider
|
||||
|
||||
session的引擎,默认是memory
|
||||
|
||||
|
||||
* SessionName
|
||||
|
||||
存在客户端的cookie名称,默认值是beegosessionID
|
||||
|
||||
|
||||
* SessionGCMaxLifetime
|
||||
|
||||
session过期时间,默认值是3600秒
|
||||
|
||||
|
||||
* SessionSavePath
|
||||
|
||||
session保存路径,默认是空
|
||||
|
||||
|
||||
* UseFcgi
|
||||
|
||||
是否启用fastcgi,默认是false
|
||||
|
||||
|
||||
* MaxMemory
|
||||
|
||||
文件上传默认内存缓存大小,默认值是`1 << 26`(64M)
|
||||
|
||||
|
||||
* EnableGzip
|
||||
|
||||
是否开启gzip支持,默认为false不支持gzip,一旦开启了gzip,那么在模板输出的内容会进行gzip或者zlib压缩,根据用户的Accept-Encoding来判断。
|
||||
是否开启gzip支持,默认为false不支持gzip,一旦开启了gzip,那么在模板输出的内容会进行gzip或者zlib压缩,根据用户的Accept-Encoding来判断。
|
||||
|
||||
|
||||
## 第三方应用集成
|
||||
|
||||
beego支持第三方应用的集成,用户可以自定义`http.Handler`,用户可以通过如下方式进行注册路由:
|
||||
|
||||
beego.RouterHandler("/chat/:info(.*)", sockjshandler)
|
||||
|
||||
|
||||
sockjshandler实现了接口`http.Handler`。
|
||||
|
||||
目前在beego的example中有支持sockjs的chat例子,示例代码如下:
|
||||
@ -982,7 +1055,7 @@ sockjshandler实现了接口`http.Handler`。
|
||||
func chatHandler(s sockjs.Session) {
|
||||
users.Add(s)
|
||||
defer users.Remove(s)
|
||||
|
||||
|
||||
for {
|
||||
m := s.Receive()
|
||||
if m == nil {
|
||||
@ -1013,7 +1086,9 @@ sockjshandler实现了接口`http.Handler`。
|
||||
|
||||
通过上面的代码很简单的实现了一个多人的聊天室。上面这个只是一个sockjs的例子,我想通过大家自定义`http.Handler`,可以有很多种方式来进行扩展beego应用。
|
||||
|
||||
|
||||
## 部署编译应用
|
||||
|
||||
Go语言的应用最后编译之后是一个二进制文件,你只需要copy这个应用到服务器上,运行起来就行。beego由于带有几个静态文件、配置文件、模板文件三个目录,所以用户部署的时候需要同时copy这三个目录到相应的部署应用之下,下面以我实际的应用部署为例:
|
||||
|
||||
$ mkdir /opt/app/beepkg
|
||||
@ -1021,7 +1096,7 @@ Go语言的应用最后编译之后是一个二进制文件,你只需要copy
|
||||
$ cp -fr views /opt/app/beepkg
|
||||
$ cp -fr static /opt/app/beepkg
|
||||
$ cp -fr conf /opt/app/beepkg
|
||||
|
||||
|
||||
这样在`/opt/app/beepkg`目录下面就会显示如下的目录结构:
|
||||
|
||||
.
|
||||
@ -1033,12 +1108,12 @@ Go语言的应用最后编译之后是一个二进制文件,你只需要copy
|
||||
│ └── js
|
||||
└── views
|
||||
└── index.tpl
|
||||
├── beepkg
|
||||
├── beepkg
|
||||
|
||||
这样我们就已经把我们需要的应用搬到服务器了,那么接下来就可以开始部署了,我现在服务器端用两种方式来run,
|
||||
|
||||
- Supervisord
|
||||
|
||||
|
||||
安装和配置见[Supervisord](Supervisord.md)
|
||||
|
||||
- nohup方式
|
||||
|
@ -18,22 +18,23 @@ beego是一个类似tornado的Go应用框架,采用了RESTFul的方式来实
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/astaxie/beego"
|
||||
"github.com/astaxie/beego"
|
||||
)
|
||||
|
||||
type MainController struct {
|
||||
beego.Controller
|
||||
beego.Controller
|
||||
}
|
||||
|
||||
func (this *MainController) Get() {
|
||||
this.Ctx.WriteString("hello world")
|
||||
this.Ctx.WriteString("hello world")
|
||||
}
|
||||
|
||||
func main() {
|
||||
beego.Router("/", &MainController{})
|
||||
beego.Run()
|
||||
beego.Router("/", &MainController{})
|
||||
beego.Run()
|
||||
}
|
||||
|
||||
|
||||
# beego 指南
|
||||
|
||||
* [为什么设计beego](Why.md)
|
||||
@ -43,8 +44,9 @@ beego是一个类似tornado的Go应用框架,采用了RESTFul的方式来实
|
||||
* [beego案例](Application.md)
|
||||
* [热升级](HotUpdate.md)
|
||||
|
||||
|
||||
# API接口
|
||||
|
||||
API对于我们平时开发应用非常有用,用于查询一些开发的函数,godoc做的非常好了
|
||||
|
||||
[Go Walker](http://gowalker.org/github.com/astaxie/beego)
|
||||
[Go Walker](http://gowalker.org/github.com/astaxie/beego)
|
||||
|
@ -3,20 +3,20 @@
|
||||
1. setuptools安装
|
||||
|
||||
wget http://pypi.python.org/packages/2.7/s/setuptools/setuptools-0.6c11-py2.7.egg
|
||||
|
||||
|
||||
sh setuptools-0.6c11-py2.7.egg
|
||||
|
||||
|
||||
easy_install supervisor
|
||||
|
||||
|
||||
echo_supervisord_conf >/etc/supervisord.conf
|
||||
|
||||
|
||||
mkdir /etc/supervisord.conf.d
|
||||
|
||||
|
||||
2. 修改配置/etc/supervisord.conf
|
||||
|
||||
[include]
|
||||
files = /etc/supervisord.conf.d/*.conf
|
||||
|
||||
|
||||
3. 新建管理的应用
|
||||
|
||||
cd /etc/supervisord.conf.d
|
||||
@ -31,4 +31,4 @@
|
||||
startsecs = 5
|
||||
user = root
|
||||
redirect_stderr = true
|
||||
stdout_logfile = /var/log/supervisord/beepkg.log
|
||||
stdout_logfile = /var/log/supervisord/beepkg.log
|
||||
|
@ -1,13 +1,19 @@
|
||||
# 一步一步跟我写博客
|
||||
|
||||
|
||||
## 创建项目
|
||||
|
||||
|
||||
## 数据库结构设计
|
||||
|
||||
|
||||
## 控制器设计
|
||||
|
||||
|
||||
## 模板设计
|
||||
|
||||
|
||||
## 用户登陆退出
|
||||
|
||||
## 数据库操作
|
||||
|
||||
## 数据库操作
|
||||
|
@ -17,4 +17,4 @@
|
||||
整个的MVC逻辑中C是最重要的部分,这一块采用了我上面说的接口方式,M模块目前我还没想好怎么做,但是大家可以参考我的另一个开源项目beedb来实现数据的管理,V这一块目前采用了Go语言自带的模板引擎,但是实现了很多方便的模板函数。这样一个简易的框架就完成了,然后我就不断的完善周边的功能,包括表单处理、session处理、日志处理、配置处理、自动化运行等功能。
|
||||
|
||||
- [beego介绍](README.md)
|
||||
- [安装入门](Install.md)
|
||||
- [安装入门](Install.md)
|
||||
|
Loading…
Reference in New Issue
Block a user