GF Framework Service Registration-framework core components, more powerful than you think

Source: Internet
Author: User
This is a creation in Article, where the information may have evolved or changed.


Article Source: http://gf.johng.cn/494368



When a user accesses a URI, the Web server can precisely invoke a specific service interface to provide the service, which is achieved through "service registration". Web server provides services that require callback functions/methods/object/controller support, and the Ghttp package supports a variety of service registration modes, providing developers with very powerful and flexible interface capabilities. Service registration is the most central part of the entire Web server and is one of the most well-designed modules in the GF framework. This section will be described in detail.



Service registration management is provided by Ghttp package, API document address: HTTPS://GODOC.ORG/GITHUB.COM/JOHNG-CN/GF.



Service Registration Introduction



Before starting this chapter, let's look at the Hello World program at the beginning of this manual:


package main

import "gitee.com/johng/gf/g/net/ghttp"

func init () {
    ghttp.GetServer (). BindHandler ("/", func (r * ghttp.Request) {
        r.Response.WriteString ("Hello World!")
    })
}
Among them, the service registration method using the BindHandler method is called "callback function registration", which is the simplest service registration method. By registering an executable method for the corresponding URI on the specified Web Server, when the client accesses the URI, the Web Server automatically calls the corresponding registered callback function to perform processing. In the callback function registration, each registration function will have a ghttp.Request object parameter pointer, which represents a specific independent request processing object for each request. The callback function can obtain the submission request parameters through this object, and it can also return the processing result data.

Comparison of service registration methods
Before explaining each registration method in detail, first look at the advantages and disadvantages of each registration method in order to choose a more suitable registration method in different business scenarios. If you don't understand this form for the time being, it doesn't matter, you can look back after understanding each registration method, it may be clearer.

Registration method Difficulty of use Safety factor Execution performance Memory consumption
Controller registration Low High Low High
Execution object registration
Callback function registration high low high low
Comparative indicator description:

Difficulty of use: mainly refers to the complexity of the execution process and data management and maintenance;
Safety factor: mainly refers to data security management and maintenance under asynchronous multi-coroutines;
Execution performance: execution performance, the result of relative comparison;
Memory consumption: memory consumption, the result of relative comparison;
List of service registration methods
func (s * Server) BindController (pattern string, c Controller) error
func (s * Server) BindControllerMethod (pattern string, c Controller, methods string) error
func (s * Server) BindControllerRest (pattern string, c Controller) error

func (s * Server) BindObject (pattern string, obj interface ()) error
func (s * Server) BindObjectMethod (pattern string, obj interface (), methods string) error
func (s * Server) BindObjectRest (pattern string, obj interface ()) error

func (s * Server) BindHandler (pattern string, handler HandlerFunc) error
The BindController * method is used for controller-related registration, the BindObject * method is used for object-related registration, and the BindHandler method is used for specific callback function registration.

The format of the pattern parameter used for service registration is as follows:

[HttpMethod:] URI [@domain]
The HttpMethod and the domain name are optional parameters. Generally speaking, the URI parameters can be directly given. Because most of the cases that need to be registered with HttpMethod are RESTful controllers, it is sufficient to register directly with RESTful related methods, and domain name support can also be bound using the Domain method.

In addition, the second parameter of BindController * series methods is the controller interface. The given parameters must implement the ghttp.Controller interface. The simple way is that the user-defined controller can directly inherit the gmvc.Controller base class, and gmvc.Controller has implemented the corresponding interface method.

Domain name service registration method
Service registration supports binding domain names. The following is a list of corresponding methods:

func (d * Domain) BindController (pattern string, c Controller) error
func (d * Domain) BindControllerMethod (pattern string, c Controller, methods string) error
func (d * Domain) BindControllerRest (pattern string, c Controller) error

func (d * Domain) BindObject (pattern string, obj interface ()) error
func (d * Domain) BindObjectMethod (pattern string, obj interface (), methods string) error
func (d * Domain) BindObjectRest (pattern string, obj interface ()) error

func (d * Domain) BindHandler (pattern string, handler HandlerFunc) error
The description of each parameter is the same as the corresponding method of Server, except that the method will be automatically bound to the list of domain names specified by Domain at the bottom of the Domain object. Only the corresponding domain name can provide access.

Let's look at a simple example. We change the previous Hello World program to the following form:

package main

import "gitee.com/johng/gf/g/net/ghttp"

func init () {
    ghttp.GetServer (). Domain ("localhost"). BindHandler ("/", func (r * ghttp.Request) {
        r.Response.WriteString ("Hello World!")
    })
}
We used http://127.0.0.1/ again to access and found that the Web Server returned a 404. Why? Because the callback function in this program is only registered to the localhost domain name, other domain names are naturally not accessible. Of course, as mentioned earlier, the domain method supports multiple domain name parameters, and custom domain name service registration is quite convenient.

Service registration initialization
All service registration is completed in the package's init initialization method (init is a package initialization method built in Go language, and multiple init methods are supported in a package). A package can contain multiple files, and each file can have The init initialization method can be registered separately. When it is used, it will be imported into the program through the same package, and the initialization method will be automatically called to complete the registration. You can refer to the sample file.

Let's see an example:

gitee.com/johng/gf/blob/master/geg/frame/mvc/main.go

package main

import (
    "gitee.com/johng/gf/g/net/ghttp"
    _ "gitee.com/johng/gf/geg/frame/mvc/controller/demo"
)

func main () {
    ghttp.GetServer (). SetPort (8199)
    ghttp.GetServer (). Run ()
}
Which passes:

import _ "gitee.com/johng/gf/geg/frame/mvc/controller/demo"
Such a statement similar to all in one completes the introduction and registration of all the controllers in the package (of course, init in the package should implement the registration method call), and contains multiple controllers and execution objects in the demo package. Registration of callback functions, specific controller registration of the demo package, and related logic will be introduced in subsequent chapters.

Controller registration
Controller registration
This method treats each request as a controller object, which is similar to the request execution mode of PHP. When a request comes in, a new controller object is initialized for processing immediately, and the controller is released after processing is completed. Resources. The advantages of this service registration method are simple, secure, and OOP design. The controller of each request is strictly data isolated, and member variables cannot be shared with each other.

We can complete the controller registration through the ghttp.BindController method.

gitee.com/johng/gf/blob/master/geg/frame/mvc/controller/demo/user.go

package demo

import (
    "gitee.com/johng/gf/g/net/ghttp"
    "gitee.com/johng/gf/g/frame/gmvc"
)

// Define business related controller objects,
// It is recommended that controllers use the Controller prefix uniformly in the naming convention, which is easy to distinguish during later code maintenance
type ControllerUser struct {
    gmvc.Controller
}

// Initialize the controller object and bind the operation to the Web Server
func init () {
    // bind the controller to the specified URI, all public methods of the controller will be mapped to the end of the specified URI
    // For example, after the method is executed, the effect can be accessed:
    // http://127.0.0.1:8199/user/name
    // http://127.0.0.1:8199/user/age
    ghttp.GetServer (). BindController ("/ user", & ControllerUser {})
}

// Define operation logic-display name
func (c * ControllerUser) Name () {
    c.Response.WriteString ("John")
}

// Define operation logic-display age
func (c * ControllerUser) Age () {
    c.Response.WriteString ("18")
}
Service registration must provide the registered URI. When registering, ghttp will map the public methods of all controllers to the end of the specified URI. For details, see the sample code description. The registered controller parameter is a ghttp.Controller interface, and the parameter can be directly passed a custom controller object pointer (& ControllerUser {}. In fact, as long as it inherits the gmvc.Controller base class, the controller pointer object has been automatically implemented ghttpController interface). ghttp obtains the corresponding controller method by parsing the object pointer, generates a reflection type, and automatically generates the corresponding controller object according to the reflection type when processing the request, processes the client request, and automatically destroys the controller object after processing.

Controller method registration
What if there are several public methods in the controller, but I only want to register a few of them, and I don't want to make the other methods public?

This scenario will inevitably be encountered in actual development, and of course ghttp also supports this demand. We can complete the registration of the specified method of the controller through the ghttp.BindControllerMethod method. Compared to the ghttp.BindController registration method, ghttp.BindControllerMetho only has one more method name parameter methods. The parameter supports the passing of multiple method names, and multiple names are separated by English "," (method parameters are case sensitive).

Look at the following example. After execution, the Name and Age methods of the ControllerMethod will be registered with the Web Server to provide services, but the Info method will not be made public.

gitee.com/johng/gf/blob/master/geg/frame/mvc/controller/demo/method.go

package demo

import (
    "gitee.com/johng/gf/g/net/ghttp"
    "gitee.com/johng/gf/g/frame/gmvc"
)

type ControllerMethod struct {
    gmvc.Controller
}

func init () {
    ghttp.GetServer (). BindControllerMethod ("/ method", & ControllerMethod {}, "Name, Age")
}

func (c * ControllerMethod) Name () {
    c.Response.WriteString ("John")
}

func (c * ControllerMethod) Age () {
    c.Response.WriteString ("18")
}

func (c * ControllerMethod) Info () {
    c.Response.WriteString ("Info")
}
Start the outer main.go, we try to visit http://127.0.0.1:8199/method/info, because the method is not registered, we will find that it returns 404; and http://127.0.0.1:8199 / method / name and http://127.0.0.1:8199/method/age can be accessed normally.

RESTful controller registration
Controllers in a RESTful design, usually used for API services. In this mode, the HTTP Method will be mapped to the controller's corresponding method name. For example, the POST method will be mapped to the controller's Post method, and the DELETE method will be mapped to the controller's Delete method. Other non-HTTP Method named methods, even defined package public methods, will not be able to complete automatic registration and will not be visible to the application side. Of course, if the controller does not define a method corresponding to the HTTP Method, the HTTP status 404 will be returned under the Method request. In addition, the controller method name needs to be guaranteed to be the same public method as the HTTP Method and the method name is capitalized.

The controller registered in this way has the same operation mode as the "controller registration" mode. We can complete the registration of the RESTful controller through the ghttp.BindControllerRest method.

Here is an example:

gitee.com/johng/gf/blob/master/geg/frame/mvc/controller/demo/rest.go

package demo

import (
    "gitee.com/johng/gf/g/net/ghttp"
    "gitee.com/johng/gf/g/frame/gmvc"
)

// test controller
type ControllerRest struct {
    gmvc.Controller
}

// Initialize the controller object and bind the operation to the Web Server
func init () {
    // In the public method of the controller, the method with the same name as the HTTP Method method will be automatically bound to the mapping
    ghttp.GetServer (). BindControllerRest ("/ user", & ControllerRest {})
}

// RESTFul-GET
func (c * ControllerUser) Get () {
    c.Response.WriteString ("RESTFul HTTP Method GET")
}

// RESTFul-POST
func (c * ControllerUser) Post () {
    c.Response.WriteString ("RESTFul HTTP Method POST")
}

// RESTFul-DELETE
func (c * ControllerUser) Delete () {
    c.Response.WriteString ("RESTFul HTTP Method DELETE")
}

// This method cannot be mapped and will not be accessible
func (c * ControllerUser) Hello () {
    c.Response.WriteString ("Hello")
}
Init and Shut callback methods
Init and Shut in the ghttp.Controller interface are two special methods (similar to functions and destructors) that are automatically called by the Web Server during the HTTP request process. These two methods have been implemented in the gmvc.Controller base class, and user-defined controller classes can directly inherit gmvc.Controller. If you need to customize the request initialization and some business logic operations at the end of the request, you can override these two methods in the custom controller.

ghttp.Controller interface

type Controller interface {
    Init (* Request)
    Shut (* Request)
}
gmvc.Controller base class

type Controller struct {
    Request * ghttp.Request // Request data object
    Response * ghttp.Response // Return data object (r.Response)
    Server * ghttp.Server // Web Server object (r.Server)
    Cookie * ghttp.Cookie // COOKIE operation object
    Session * ghttp.Session // SESSION operation object
    View * View // view object
}
Init callback method
Controller initialization method, the parameter is the object of the current request. The Init method in the gmvc.Controller base class is the initialization of its member objects.

Shut callback method
It is called automatically by the Web Server when the request ends, and can be used for some finishing operations of the controller. Do nothing by default.

[danger] # Perform object registration
[success] ## Perform object registration

The design pattern of controller registration is relatively simple and easy to manage, but since each request is a new controller object to be processed and the reflection mechanism is used, there will be a certain performance loss.

Execution object registration is a relatively efficient execution method, but the operating mechanism and design pattern are completely different from the controller registration. As the literal meaning is, the execution of object registration is given an instantiated object at the time of registration. Every subsequent request is given to the object (the same object) for processing. The resident memory of the object is not released. Compared with the controller registration, the execution object registration method does not need to constantly create / destroy the controller object when processing the request, so the request processing efficiency will be much higher.

The disadvantage of this registration method is also obvious. When the server process starts, it needs to initialize these execution objects, and these objects need to be responsible for the concurrent security maintenance of their own data. The definition of the execution object is not strictly required, nor is it mandatory to inherit the base class of gmvc.Controller controller, because there is no automatic initialization process when the request is entered, and internal member variables need to be maintained by themselves (including variable initialization, variable destruction, etc.)

We can complete the registration of the execution object through the ghttp.BindObject method.

gitee.com/johng/gf/blob/master/geg/frame/mvc/controller/demo/object.go

package demo

import "gitee.com/johng/gf/g/net/ghttp"

type Object struct {}

func init () {
    ghttp.GetServer (). BindObject ("/ object", & Object {})
}

func (o * Object) Show (r * ghttp.Request) {
    r.Response.WriteString ("It's show time bibi!")
}
It can be seen that when the execution object performs service registration, an object is generated (the execution object is generated when the Web Server starts). After that, no matter how many requests enter, the Web Server will forward the request to the corresponding method of the object for processing. It should be noted that the definition of the public method is different from the controller registration and must be in the following form:

func (r * ghttp.Request)
Otherwise, registration cannot be completed, and an error prompt will appear when calling the registration method, which looks like this:

panic: interface conversion: interface {} is xxx, not func (* ghttp.Request)
After the example is executed, you can view the effect through http://127.0.0.1:8199/object/show.

[success] ## Object method registration
The object method registration principle is similar to the controller method registration, only exposing specific methods in the execution object.

Let's see an example:

package demo

import (
    "gitee.com/johng/gf/g/net/ghttp"
)

type ObjectMethod struct {}

func init () {
    obj: = & ObjectMethod ()
    ghttp.GetServer (). BindObjectMethod ("/ object-method", obj, "Show1, Show2, Show3")
    ghttp.GetServer (). Domain ("localhost"). BindObjectMethod ("/ object-method", obj, "Show4")
}

func (o * ObjectMethod) Show1 (r * ghttp.Request) {
    r.Response.WriteString ("show 1")
}

func (o * ObjectMethod) Show2 (r * ghttp.Request) {
    r.Response.WriteString ("show 2")
}

func (o * ObjectMethod) Show3 (r * ghttp.Request) {
    r.Response.WriteString ("show 3")
}

func (o * ObjectMethod) Show4 (r * ghttp.Request) {
    r.Response.WriteString ("show 4")
}
This example is relatively simple, and also demonstrates the operation of the domain name binding execution object method. ObjectMethod
http://127.0.0.1:8199/object-method/show1
http://127.0.0.1:8199/object-method/show2
http://127.0.0.1:8199/object-method/show3
These 3 interfaces can only be accessed through the IP of 127.0.0.1, while the method of Show4 can only be accessed through
http: // localhost: 8199 / object-method / show4
access.

[success] ## RESTful object registration
Similar to REST controller registration, except that it is an instantiated object. We can complete the registration of REST objects through the ghttp.BindObjectRest method.

gitee.com/johng/gf/blob/master/geg/frame/mvc/controller/demo/object_rest.go

package demo

import "gitee.com/johng/gf/g/net/ghttp"

// test binding object
type ObjectRest struct {}

func init () {
    ghttp.GetServer (). BindObjectRest ("/ object-rest", & ObjectRest {})
}

// RESTFul-GET
func (o * ObjectRest) Get (r * ghttp.Request) {
    r.Response.WriteString ("RESTFul HTTP Method GET")
}

// RESTFul-POST
func (c * ObjectRest) Post (r * ghttp.Request) {
    r.Response.WriteString ("RESTFulHTTP Method POST ")
}

// RESTFul-DELETE
func (c * ObjectRest) Delete (r * ghttp.Request) {
    r.Response.WriteString ("RESTFul HTTP Method DELETE")
}

// This method cannot be mapped and will not be accessible
func (c * ObjectRest) Hello (r * ghttp.Request) {
    r.Response.WriteString ("Hello")
}
[danger] # callback function registration
The operation mechanism of this way is similar to performing object registration, but registering is a function / method. Compared to performing object registration, there is no additional object instantiation overhead during registration, and only a pointer address of a function / method is saved during registration. Service registration in this way is more flexible. The registered service can be a method address of an instantiated object or a package method address. The data required by the service can be managed in the form of package internal variables or object internal variables, and developers can flexibly control according to the actual situation.

We can complete the registration of the callback function through the ghttp.BindHandler method.

gitee.com/johng/gf/blob/master/geg/frame/mvc/controller/demo/apple_pen.go

package demo

import "gitee.com/johng/gf/g/net/ghttp"

func init () {
    ghttp.GetServer (). BindHandler ("/ apple", Apple)
    ghttp.GetServer (). BindHandler ("/ pen", Pen)
    ghttp.GetServer (). BindHandler ("/ apple-pen", ApplePen)
}

func Apple (r * ghttp.Request) {
    r.Response.WriteString ("Apple")
}

func Pen (r * ghttp.Request) {
    r.Response.WriteString ("Pen")
}

func ApplePen (r * ghttp.Request) {
    r.Response.WriteString ("Apple-Pen")
}
Event callback registration

ghttp.Server provides the event callback registration function, which supports users to perform custom listener processing on an event, and perform binding registration according to the URI pattern. Support multiple methods to listen for the same event, ghttp.Server will make callback method calls according to the registration order.
The relevant methods are as follows:

func (s * Server) BindHookHandler (pattern string, hook string, handler HandlerFunc) error
func (s * Server) BindHookHandlerByMap (pattern string, hookmap map [string] HandlerFunc) error
Of course, the domain name object also supports event callback registration:

func (d * Domain) BindHookHandler (pattern string, hook string, handler HandlerFunc) error
func (d * Domain) BindHookHandlerByMap (pattern string, hookmap map [string] HandlerFunc) error
List of supported events:

BeforeServe
Before entering / initializing the service object.
AfterServe
After completing the service execution process.
BeforePatch
Before Router packages the returned content.
AfterrPatch
After Router packages the returned content.
BeforeOutput
Output to the client before returning content.
AfterOutput
After the output is returned to the client.
BeforeClose
Before the http request is closed (note that the request close is an asynchronous processing operation and is not processed in the http execution process).
AfterClose
After the http request is closed (note that the request close is an asynchronous processing operation and is not processed in the http execution process).

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.