update docs
Showing
1 changed file
with
363 additions
and
5 deletions
| ... | @@ -301,27 +301,385 @@ beego支持用户定义模板函数,但是必须在`beego.Run()`调用之前 | ... | @@ -301,27 +301,385 @@ beego支持用户定义模板函数,但是必须在`beego.Run()`调用之前 |
| 301 | ## request处理 | 301 | ## request处理 |
| 302 | 我们经常需要获取用户传递的数据,包括Get、POST等方式的请求,beego里面会自动解析这些数据,你可以通过如下方式获取数据 | 302 | 我们经常需要获取用户传递的数据,包括Get、POST等方式的请求,beego里面会自动解析这些数据,你可以通过如下方式获取数据 |
| 303 | 303 | ||
| 304 | - GetString | 304 | - GetString(key string) string |
| 305 | - GetInt | 305 | - GetInt(key string) (int64, error) |
| 306 | - GetBool | 306 | - GetBool(key string) (bool, error) |
| 307 | 307 | ||
| 308 | 使用例子如下: | ||
| 309 | |||
| 310 | func (this *MainController) Post() { | ||
| 311 | jsoninfo := this.GetString("jsoninfo") | ||
| 312 | if jsoninfo == "" { | ||
| 313 | this.Ctx.WriteString("jsoninfo is empty") | ||
| 314 | return | ||
| 315 | } | ||
| 316 | } | ||
| 317 | |||
| 318 | 如果你需要的数据可能是其他类型的,例如是int类型而不是int64,那么你需要这样处理: | ||
| 319 | |||
| 320 | func (this *MainController) Post() { | ||
| 321 | id := this.Input().Get("id") | ||
| 322 | intid, err := strconv.Atoi(id) | ||
| 323 | } | ||
| 324 | |||
| 325 | 更多其他的request的信息,用户可以通过`this.Ctx.Request`获取信息,关于该对象的属性和方法参考手册[Request](http://golang.org/pkg/net/http/#Request) | ||
| 308 | 326 | ||
| 309 | ### 文件上传 | 327 | ### 文件上传 |
| 328 | 在beego中你可以很容易的处理文件上传,就是别忘记在你的form表单中增加这个属性`enctype="multipart/form-data"`,否者你的浏览器不会传输你的上传文件。 | ||
| 329 | |||
| 330 | 文件上传之后一般是放在系统的内存里面,如果文件的size大于设置的缓存内存大小,那么就放在临时文件中,默认的缓存内存是64M,你可以通过如下来调整这个缓存内存大小: | ||
| 331 | |||
| 332 | beego.MaxMemory = 1<<22 | ||
| 333 | |||
| 334 | 或者在配置文件中通过如下设置 | ||
| 335 | |||
| 336 | maxmemory = 1<<22 | ||
| 337 | |||
| 338 | beego提供了两个很方便的方法来处理文件上传: | ||
| 339 | |||
| 340 | - GetFile(key string) (multipart.File, *multipart.FileHeader, error) | ||
| 310 | 341 | ||
| 311 | - GetFile | 342 | 该方法主要用于用户读取表单中的文件名`the_file`,然后返回相应的信息,用户根据这些变量来处理文件上传:过滤、保存文件等。 |
| 312 | - SaveToFile | 343 | |
| 344 | - SaveToFile(fromfile, tofile string) error | ||
| 345 | |||
| 346 | 该方法是在GetFile的基础上实现了快速保存的功能 | ||
| 347 | |||
| 348 | 保存的代码例子如下: | ||
| 349 | |||
| 350 | func (this *MainController) Post() { | ||
| 351 | this.SaveToFile("the_file","/var/www/uploads/uploaded_file.txt"") | ||
| 352 | } | ||
| 353 | |||
| 354 | ### JSON和XML输出 | ||
| 355 | beego当初设计的时候就考虑了API功能的设计,而我们在设计API的时候经常是输出JSON或者XML数据,那么beego提供了这样的方式直接输出: | ||
| 356 | |||
| 357 | JSON数据直接输出,设置`content-type`为`application/json`: | ||
| 358 | |||
| 359 | func (this *AddController) Get() { | ||
| 360 | mystruct := { ... } | ||
| 361 | this.Data["json"] = &mystruct | ||
| 362 | this.ServeJson() | ||
| 363 | } | ||
| 364 | |||
| 365 | XML数据直接输出,设置`content-type`为`application/xml`: | ||
| 366 | |||
| 367 | func (this *AddController) Get() { | ||
| 368 | mystruct := { ... } | ||
| 369 | this.Data["xml"]=&mystruct | ||
| 370 | this.ServeXml() | ||
| 371 | } | ||
| 313 | 372 | ||
| 314 | ## 跳转和错误 | 373 | ## 跳转和错误 |
| 374 | 我们在做Web开发的时候,经常会遇到页面调整和错误处理,beego这这方面也进行了考虑,通过`Redirect`方法来进行跳转: | ||
| 375 | |||
| 376 | func (this *AddController) Get() { | ||
| 377 | this.Redirect("/", 302) | ||
| 378 | } | ||
| 379 | |||
| 380 | @todo 错误处理还需要后期改进 | ||
| 315 | 381 | ||
| 316 | ## response处理 | 382 | ## response处理 |
| 383 | response可能会有集中情况: | ||
| 384 | |||
| 385 | 1. 模板输出 | ||
| 386 | |||
| 387 | 模板输出上面模板介绍里面已经介绍,beego会在执行完相应的Controller里面的对应的Method之后输出到模板。 | ||
| 388 | |||
| 389 | 2. 跳转 | ||
| 390 | |||
| 391 | 上一节介绍的跳转就是我们经常用到的页面之间的跳转 | ||
| 392 | |||
| 393 | 3. 字符串输出 | ||
| 394 | |||
| 395 | 有些时候我们只是想输出相应的一个字符串,那么我们可以通过如下的代码实现 | ||
| 396 | |||
| 397 | this.Ctx.WriteString("ok") | ||
| 317 | 398 | ||
| 318 | ## Sessions | 399 | ## Sessions |
| 400 | beego内置了session模块,目前session模块支持的后端引擎包括memory、file、mysql、redis四中,用户也可以根据相应的interface实现自己的引擎。 | ||
| 401 | |||
| 402 | beego中使用session相当方便,只要在main入口函数中设置如下: | ||
| 403 | |||
| 404 | beego.SessionOn = true | ||
| 405 | |||
| 406 | 或者通过配置文件配置如下: | ||
| 407 | |||
| 408 | sessionon = true | ||
| 409 | |||
| 410 | 通过这种方式就可以开启session,如何使用session,请看下面的例子: | ||
| 411 | |||
| 412 | func (this *MainController) Get() { | ||
| 413 | v := this.GetSession("asta") | ||
| 414 | if v == nil { | ||
| 415 | this.SetSession("asta", int(1)) | ||
| 416 | this.Data["num"] = 0 | ||
| 417 | } else { | ||
| 418 | this.SetSession("asta", v.(int)+1) | ||
| 419 | this.Data["num"] = v.(int) | ||
| 420 | } | ||
| 421 | this.TplNames = "index.tpl" | ||
| 422 | } | ||
| 423 | |||
| 424 | 上面的例子中我们知道session有几个方便的方法: | ||
| 425 | |||
| 426 | - SetSession(name string, value interface{}) | ||
| 427 | - GetSession(name string) interface{} | ||
| 428 | - DelSession(name string) | ||
| 429 | |||
| 430 | session操作主要有设置session、获取session、删除session | ||
| 431 | |||
| 432 | 当然你要可以通过下面的方式自己控制相应的逻辑这些逻辑: | ||
| 433 | |||
| 434 | sess:=this.StartSession() | ||
| 435 | defer sess.SessionRelease() | ||
| 436 | |||
| 437 | sess对象具有如下方法: | ||
| 438 | |||
| 439 | * sess.Set() | ||
| 440 | * sess.Get() | ||
| 441 | * sess.Delete() | ||
| 442 | * sess.SessionID() | ||
| 443 | |||
| 444 | 但是我还是建议大家采用SetSession、GetSession、DelSession三个方法来操作,避免自己在操作的过程中资源没释放的问题。 | ||
| 445 | |||
| 446 | 关于Session模块使用中的一些参数设置: | ||
| 447 | |||
| 448 | - SessionOn | ||
| 449 | |||
| 450 | 设置是否开启Session,默认是false,配置文件对应的参数名:sessionon | ||
| 451 | |||
| 452 | - SessionProvider | ||
| 453 | |||
| 454 | 设置Session的引擎,默认是memory,目前支持还有file、mysql、redis等,配置文件对应的参数名:sessionprovider | ||
| 455 | |||
| 456 | - SessionName | ||
| 457 | |||
| 458 | 设置cookies的名字,Session默认是保存在用户的浏览器cookies里面的,默认名是beegosessionID,配置文件对应的参数名是:sessionname | ||
| 459 | |||
| 460 | - SessionGCMaxLifetime | ||
| 461 | |||
| 462 | 设置Session过期的时间,默认值是3600秒,配置文件对应的参数:sessiongcmaxlifetime | ||
| 463 | |||
| 464 | - SessionSavePath | ||
| 465 | |||
| 466 | 设置对应file、mysql、redis引擎的保存路径或者链接地址,默认值是空,配置文件对应的参数:sessionsavepath | ||
| 467 | |||
| 468 | |||
| 469 | 当SessionProvider为file时,SessionSavePath是只保存文件的目录,如下所示: | ||
| 470 | |||
| 471 | beego.SessionProvider = "file" | ||
| 472 | beego.SessionSavePath = "./tmp" | ||
| 473 | |||
| 474 | 当SessionProvider为mysql时,SessionSavePath是链接地址,采用[go-sql-driver](https://github.com/go-sql-driver/mysql),如下所示: | ||
| 475 | |||
| 476 | beego.SessionProvider = "mysql" | ||
| 477 | beego.SessionSavePath = "username:password@protocol(address)/dbname?param=value" | ||
| 478 | |||
| 479 | 当SessionProvider为redis时,SessionSavePath是redis的链接地址,采用了[redigo](https://github.com/garyburd/redigo),如下所示: | ||
| 480 | |||
| 481 | beego.SessionProvider = "redis" | ||
| 482 | beego.SessionSavePath = "127.0.0.1:6379" | ||
| 319 | 483 | ||
| 320 | ## Cache设置 | 484 | ## Cache设置 |
| 485 | beego内置了一个cache模块,实现了类似memcache的功能,缓存数据在内存中,主要的使用方法如下: | ||
| 486 | |||
| 487 | var ( | ||
| 488 | urllist *beego.BeeCache | ||
| 489 | ) | ||
| 490 | |||
| 491 | func init() { | ||
| 492 | urllist = beego.NewBeeCache() | ||
| 493 | urllist.Every = 0 //不过期 | ||
| 494 | urllist.Start() | ||
| 495 | } | ||
| 496 | |||
| 497 | func (this *ShortController) Post() { | ||
| 498 | var result ShortResult | ||
| 499 | longurl := this.Input().Get("longurl") | ||
| 500 | beego.Info(longurl) | ||
| 501 | result.UrlLong = longurl | ||
| 502 | urlmd5 := models.GetMD5(longurl) | ||
| 503 | beego.Info(urlmd5) | ||
| 504 | if urllist.IsExist(urlmd5) { | ||
| 505 | result.UrlShort = urllist.Get(urlmd5).(string) | ||
| 506 | } else { | ||
| 507 | result.UrlShort = models.Generate() | ||
| 508 | err := urllist.Put(urlmd5, result.UrlShort, 0) | ||
| 509 | if err != nil { | ||
| 510 | beego.Info(err) | ||
| 511 | } | ||
| 512 | err = urllist.Put(result.UrlShort, longurl, 0) | ||
| 513 | if err != nil { | ||
| 514 | beego.Info(err) | ||
| 515 | } | ||
| 516 | } | ||
| 517 | this.Data["json"] = result | ||
| 518 | this.ServeJson() | ||
| 519 | } | ||
| 520 | |||
| 521 | 上面这个例子演示了如何使用beego的Cache模块,主要是通过`beego.NewBeeCache`初始化一个对象,然后设置过期时间,开启过期检测,在业务逻辑中就可以通过如下的接口进行增删改的操作: | ||
| 522 | |||
| 523 | - Get(name string) interface{} | ||
| 524 | - Put(name string, value interface{}, expired int) error | ||
| 525 | - Delete(name string) (ok bool, err error) | ||
| 526 | - IsExist(name string) bool | ||
| 321 | 527 | ||
| 322 | ## 安全的Map | 528 | ## 安全的Map |
| 529 | 我们知道在Go语言里面map是非线程安全的,详细的[atomic_maps](http://golang.org/doc/faq#atomic_maps)。但是我们在平常的业务中经常需要用到线程安全的map,特别是在goroutine的情况下,所以beego内置了一个简单的线程安全的map: | ||
| 530 | |||
| 531 | bm := NewBeeMap() | ||
| 532 | if !bm.Set("astaxie", 1) { | ||
| 533 | t.Error("set Error") | ||
| 534 | } | ||
| 535 | if !bm.Check("astaxie") { | ||
| 536 | t.Error("check err") | ||
| 537 | } | ||
| 538 | |||
| 539 | if v := bm.Get("astaxie"); v.(int) != 1 { | ||
| 540 | t.Error("get err") | ||
| 541 | } | ||
| 542 | |||
| 543 | bm.Delete("astaxie") | ||
| 544 | if bm.Check("astaxie") { | ||
| 545 | t.Error("delete err") | ||
| 546 | } | ||
| 547 | |||
| 548 | 上面演示了如何使用线程安全的Map,主要的接口有: | ||
| 549 | |||
| 550 | - Get(k interface{}) interface{} | ||
| 551 | - Set(k interface{}, v interface{}) bool | ||
| 552 | - Check(k interface{}) bool | ||
| 553 | - Delete(k interface{}) | ||
| 323 | 554 | ||
| 324 | ## 日志处理 | 555 | ## 日志处理 |
| 556 | beego默认有一个初始化的BeeLogger对象输出内容到stdout中,你可以通过如下的方式设置自己的输出: | ||
| 557 | |||
| 558 | beego.SetLogger(*log.Logger) | ||
| 559 | |||
| 560 | 只要你的输出符合`*log.Logger`就可以,例如输出到文件: | ||
| 561 | |||
| 562 | fd,err := os.OpenFile("/var/log/beeapp/beeapp.log", os.O_RDWR|os.O_APPEND, 0644) | ||
| 563 | if err != nil { | ||
| 564 | beego.Critical("openfile beeapp.log:", err) | ||
| 565 | return | ||
| 566 | } | ||
| 567 | lg := log.New(fd, "", log.Ldate|log.Ltime) | ||
| 568 | beego.SetLogger(lg) | ||
| 569 | ### 不同级别的log日志函数 | ||
| 570 | |||
| 571 | * Trace(v ...interface{}) | ||
| 572 | * Debug(v ...interface{}) | ||
| 573 | * Info(v ...interface{}) | ||
| 574 | * Warn(v ...interface{}) | ||
| 575 | * Error(v ...interface{}) | ||
| 576 | * Critical(v ...interface{}) | ||
| 577 | |||
| 578 | 你可以通过下面的方式设置不同的日志分级: | ||
| 579 | |||
| 580 | beego.SetLevel(beego.LevelError) | ||
| 581 | |||
| 582 | 当你代码中有很多日志输出之后,如果想上线,但是你不想输出Trace、Debug、Info等信息,那么你可以设置如下: | ||
| 583 | |||
| 584 | beego.SetLevel(beego.LevelWarning) | ||
| 585 | |||
| 586 | 这样的话就不会输出小于这个level的日志,日志的排序如下: | ||
| 587 | |||
| 588 | LevelTrace、LevelDebug、LevelInfo、LevelWarning、 LevelError、LevelCritical | ||
| 589 | |||
| 590 | 用户可以根据不同的级别输出不同的错误信息,如下例子所示: | ||
| 591 | |||
| 592 | ### Examples of log messages | ||
| 593 | - Trace | ||
| 594 | |||
| 595 | * "Entered parse function validation block" | ||
| 596 | * "Validation: entered second 'if'" | ||
| 597 | * "Dictionary 'Dict' is empty. Using default value" | ||
| 598 | - Debug | ||
| 599 | |||
| 600 | * "Web page requested: http://somesite.com Params='...'" | ||
| 601 | * "Response generated. Response size: 10000. Sending." | ||
| 602 | * "New file received. Type:PNG Size:20000" | ||
| 603 | - Info | ||
| 604 | * "Web server restarted" | ||
| 605 | * "Hourly statistics: Requested pages: 12345 Errors: 123 ..." | ||
| 606 | * "Service paused. Waiting for 'resume' call" | ||
| 607 | - Warn | ||
| 608 | * "Cache corrupted for file='test.file'. Reading from back-end" | ||
| 609 | * "Database 192.168.0.7/DB not responding. Using backup 192.168.0.8/DB" | ||
| 610 | * "No response from statistics server. Statistics not sent" | ||
| 611 | - Error | ||
| 612 | * "Internal error. Cannot process request #12345 Error:...." | ||
| 613 | * "Cannot perform login: credentials DB not responding" | ||
| 614 | - Critical | ||
| 615 | * "Critical panic received: .... Shutting down" | ||
| 616 | * "Fatal error: ... App is shutting down to prevent data corruption or loss" | ||
| 617 | |||
| 618 | ### Example | ||
| 619 | |||
| 620 | func internalCalculationFunc(x, y int) (result int, err error) { | ||
| 621 | beego.Debug("calculating z. x:",x," y:",y) | ||
| 622 | z := y | ||
| 623 | switch { | ||
| 624 | case x == 3 : | ||
| 625 | beego.Trace("x == 3") | ||
| 626 | panic("Failure.") | ||
| 627 | case y == 1 : | ||
| 628 | beego.Trace("y == 1") | ||
| 629 | return 0, errors.New("Error!") | ||
| 630 | case y == 2 : | ||
| 631 | beego.Trace("y == 2") | ||
| 632 | z = x | ||
| 633 | default : | ||
| 634 | beego.Trace("default") | ||
| 635 | z += x | ||
| 636 | } | ||
| 637 | retVal := z-3 | ||
| 638 | beego.Debug("Returning ", retVal) | ||
| 639 | |||
| 640 | return retVal, nil | ||
| 641 | } | ||
| 642 | |||
| 643 | func processInput(input inputData) { | ||
| 644 | defer func() { | ||
| 645 | if r := recover(); r != nil { | ||
| 646 | beego.Error("Unexpected error occurred: ", r) | ||
| 647 | outputs <- outputData{result : 0, error : true} | ||
| 648 | } | ||
| 649 | }() | ||
| 650 | beego.Info("Received input signal. x:",input.x," y:", input.y) | ||
| 651 | |||
| 652 | res, err := internalCalculationFunc(input.x, input.y) | ||
| 653 | if err != nil { | ||
| 654 | beego.Warn("Error in calculation:", err.Error()) | ||
| 655 | } | ||
| 656 | |||
| 657 | beego.Info("Returning result: ",res," error: ",err) | ||
| 658 | outputs <- outputData{result : res, error : err != nil} | ||
| 659 | } | ||
| 660 | |||
| 661 | func main() { | ||
| 662 | inputs = make(chan inputData) | ||
| 663 | outputs = make(chan outputData) | ||
| 664 | criticalChan = make(chan int) | ||
| 665 | beego.Info("App started.") | ||
| 666 | |||
| 667 | go consumeResults(outputs) | ||
| 668 | beego.Info("Started receiving results.") | ||
| 669 | |||
| 670 | go generateInputs(inputs) | ||
| 671 | beego.Info("Started sending signals.") | ||
| 672 | |||
| 673 | for { | ||
| 674 | select { | ||
| 675 | case input := <- inputs: | ||
| 676 | processInput(input) | ||
| 677 | case <- criticalChan: | ||
| 678 | beego.Critical("Caught value from criticalChan: Go shut down.") | ||
| 679 | panic("Shut down due to critical fault.") | ||
| 680 | } | ||
| 681 | } | ||
| 682 | } | ||
| 325 | 683 | ||
| 326 | ## 第三方应用集成 | 684 | ## 第三方应用集成 |
| 327 | 685 | ... | ... |
-
Please register or sign in to post a comment