mirror of
https://gitee.com/johng/gf
synced 2026-06-27 01:43:33 +08:00
完善ghttp,gcache功能
This commit is contained in:
@ -1,107 +1,2 @@
|
||||
package ghttp
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"time"
|
||||
"crypto/tls"
|
||||
"log"
|
||||
"net/url"
|
||||
)
|
||||
|
||||
// http客户端
|
||||
type Client struct {
|
||||
http.Client
|
||||
}
|
||||
|
||||
// http server结构体
|
||||
type Server struct {
|
||||
server http.Server
|
||||
config ServerConfig
|
||||
handlerMap HandlerMap
|
||||
}
|
||||
|
||||
// 请求对象
|
||||
type ClientRequest struct {
|
||||
http.Request
|
||||
getvals *url.Values
|
||||
}
|
||||
|
||||
// 客户端请求结果对象
|
||||
type ClientResponse struct {
|
||||
http.Response
|
||||
}
|
||||
|
||||
// 服务端请求返回对象
|
||||
type ServerResponse struct {
|
||||
http.ResponseWriter
|
||||
}
|
||||
|
||||
// http回调函数
|
||||
type HandlerFunc func(*ClientRequest, *ServerResponse)
|
||||
|
||||
// uri与回调函数的绑定记录表
|
||||
type HandlerMap map[string]HandlerFunc
|
||||
|
||||
// HTTP Server 设置结构体
|
||||
type ServerConfig struct {
|
||||
// HTTP Server基础字段
|
||||
Addr string // 监听IP和端口,监听本地所有IP使用":端口"
|
||||
Handler http.Handler // 默认的处理函数
|
||||
TLSConfig *tls.Config // TLS配置
|
||||
ReadTimeout time.Duration
|
||||
WriteTimeout time.Duration
|
||||
IdleTimeout time.Duration
|
||||
MaxHeaderBytes int // 最大的header长度
|
||||
ErrorLog *log.Logger // 错误日志的处理接口
|
||||
// gf 扩展信息字段
|
||||
IndexFiles []string // 默认访问的文件列表
|
||||
IndexFolder bool // 如果访问目录是否显示目录列表
|
||||
ServerAgent string // server agent
|
||||
ServerRoot string // 服务器服务的本地目录根路径
|
||||
}
|
||||
|
||||
// 默认HTTP Server
|
||||
var defaultServerConfig = ServerConfig {
|
||||
Addr : ":80",
|
||||
Handler : nil,
|
||||
ReadTimeout : 60 * time.Second,
|
||||
WriteTimeout : 60 * time.Second,
|
||||
IdleTimeout : 60 * time.Second,
|
||||
MaxHeaderBytes : 1024,
|
||||
IndexFiles : []string{"index.html", "index.htm"},
|
||||
IndexFolder : false,
|
||||
ServerAgent : "gf",
|
||||
ServerRoot : "",
|
||||
}
|
||||
|
||||
// 修改默认的http server配置
|
||||
func SetDefaultServerConfig (c ServerConfig) {
|
||||
defaultServerConfig = c
|
||||
}
|
||||
|
||||
// 创建一个默认配置的HTTP Server(默认监听端口是80)
|
||||
func NewServer() (*Server) {
|
||||
return NewServerByConfig(defaultServerConfig)
|
||||
}
|
||||
|
||||
// 创建一个HTTP Server,返回指针
|
||||
func NewServerByAddr(addr string) (*Server) {
|
||||
config := defaultServerConfig
|
||||
config.Addr = addr
|
||||
return NewServerByConfig(config)
|
||||
}
|
||||
|
||||
// 创建一个HTTP Server
|
||||
func NewServerByAddrRoot(addr string, root string) (*Server) {
|
||||
config := defaultServerConfig
|
||||
config.Addr = addr
|
||||
config.ServerRoot = root
|
||||
return NewServerByConfig(config)
|
||||
}
|
||||
|
||||
// 根据输入配置创建一个http server对象
|
||||
func NewServerByConfig(s ServerConfig) (*Server) {
|
||||
var server Server
|
||||
server.SetConfig(s)
|
||||
return &server
|
||||
}
|
||||
@ -4,8 +4,26 @@ import (
|
||||
"net/http"
|
||||
"strings"
|
||||
"time"
|
||||
"net/url"
|
||||
"bytes"
|
||||
)
|
||||
|
||||
// http客户端
|
||||
type Client struct {
|
||||
http.Client
|
||||
}
|
||||
|
||||
// 请求对象
|
||||
type ClientRequest struct {
|
||||
http.Request
|
||||
getvals *url.Values // GET参数
|
||||
}
|
||||
|
||||
// 客户端请求结果对象
|
||||
type ClientResponse struct {
|
||||
http.Response
|
||||
}
|
||||
|
||||
// http客户端对象指针
|
||||
func NewClient() (*Client) {
|
||||
return &Client{}
|
||||
@ -17,106 +35,104 @@ func (c *Client) SetTimeOut(t time.Duration) {
|
||||
}
|
||||
|
||||
// GET请求
|
||||
func (c *Client) Get(url string) *ClientResponse {
|
||||
return c.Request("GET", url, "")
|
||||
func (c *Client) Get(url string) (*ClientResponse, error) {
|
||||
return c.Request("GET", url, []byte(""))
|
||||
}
|
||||
|
||||
// PUT请求
|
||||
func (c *Client) Put(url, data string) *ClientResponse {
|
||||
return c.Request("PUT", url, data)
|
||||
func (c *Client) Put(url, data string) (*ClientResponse, error) {
|
||||
return c.Request("PUT", url, []byte(data))
|
||||
}
|
||||
|
||||
// POST请求提交数据
|
||||
func (c *Client) Post(url, data string) *ClientResponse {
|
||||
func (c *Client) Post(url, data string) (*ClientResponse, error) {
|
||||
resp, err := http.Post(url, "application/x-www-form-urlencoded", strings.NewReader(data))
|
||||
if err != nil {
|
||||
//glog.Println(err)
|
||||
return nil
|
||||
return nil, err
|
||||
}
|
||||
r := &ClientResponse{}
|
||||
r.Response = *resp
|
||||
return r
|
||||
return r, nil
|
||||
}
|
||||
|
||||
// DELETE请求
|
||||
func (c *Client) Delete(url, data string) *ClientResponse {
|
||||
return c.Request("DELETE", url, data)
|
||||
func (c *Client) Delete(url, data string) (*ClientResponse, error) {
|
||||
return c.Request("DELETE", url, []byte(data))
|
||||
}
|
||||
|
||||
func (c *Client) Head(url, data string) *ClientResponse {
|
||||
return c.Request("HEAD", url, data)
|
||||
func (c *Client) Head(url, data string) (*ClientResponse, error) {
|
||||
return c.Request("HEAD", url, []byte(data))
|
||||
}
|
||||
|
||||
func (c *Client) Patch(url, data string) *ClientResponse {
|
||||
return c.Request("PATCH", url, data)
|
||||
func (c *Client) Patch(url, data string) (*ClientResponse, error) {
|
||||
return c.Request("PATCH", url, []byte(data))
|
||||
}
|
||||
|
||||
func (c *Client) Connect(url, data string) *ClientResponse{
|
||||
return c.Request("CONNECT", url, data)
|
||||
func (c *Client) Connect(url, data string) (*ClientResponse, error) {
|
||||
return c.Request("CONNECT", url, []byte(data))
|
||||
}
|
||||
|
||||
func (c *Client) Options(url, data string) *ClientResponse{
|
||||
return c.Request("OPTIONS", url, data)
|
||||
func (c *Client) Options(url, data string) (*ClientResponse, error) {
|
||||
return c.Request("OPTIONS", url, []byte(data))
|
||||
}
|
||||
|
||||
func (c *Client) Trace(url, data string) *ClientResponse {
|
||||
return c.Request("TRACE", url, data)
|
||||
func (c *Client) Trace(url, data string) (*ClientResponse, error) {
|
||||
return c.Request("TRACE", url, []byte(data))
|
||||
}
|
||||
|
||||
// 请求并返回response对象
|
||||
func (c *Client) Request(method, url, data string) *ClientResponse {
|
||||
req, err := http.NewRequest(strings.ToUpper(method), url, strings.NewReader(data))
|
||||
// 请求并返回response对象,该方法支持二进制提交数据
|
||||
func (c *Client) Request(method, url string, data []byte) (*ClientResponse, error) {
|
||||
req, err := http.NewRequest(strings.ToUpper(method), url, bytes.NewReader(data))
|
||||
if err != nil {
|
||||
//glog.Println("creating request failed: " + err.Error())
|
||||
return nil
|
||||
return nil, err
|
||||
}
|
||||
resp, err := c.Do(req)
|
||||
if err != nil {
|
||||
//glog.Println("sending request failed: " + err.Error())
|
||||
return nil
|
||||
return nil, err
|
||||
}
|
||||
r := &ClientResponse{}
|
||||
r.Response = *resp
|
||||
return r
|
||||
return r, nil
|
||||
}
|
||||
|
||||
|
||||
func Get(url string) *ClientResponse {
|
||||
return Request("GET", url, "")
|
||||
func Get(url string) (*ClientResponse, error) {
|
||||
return Request("GET", url, []byte(""))
|
||||
}
|
||||
|
||||
func Put(url, data string) *ClientResponse {
|
||||
return Request("PUT", url, data)
|
||||
func Put(url, data string) (*ClientResponse, error) {
|
||||
return Request("PUT", url, []byte(data))
|
||||
}
|
||||
|
||||
func Post(url, data string) *ClientResponse {
|
||||
return Request("PUT", url, data)
|
||||
func Post(url, data string) (*ClientResponse, error) {
|
||||
return Request("PUT", url, []byte(data))
|
||||
}
|
||||
|
||||
func Delete(url, data string) *ClientResponse {
|
||||
return Request("DELETE", url, data)
|
||||
func Delete(url, data string) (*ClientResponse, error) {
|
||||
return Request("DELETE", url, []byte(data))
|
||||
}
|
||||
|
||||
func Head(url, data string) *ClientResponse {
|
||||
return Request("HEAD", url, data)
|
||||
func Head(url, data string) (*ClientResponse, error) {
|
||||
return Request("HEAD", url, []byte(data))
|
||||
}
|
||||
|
||||
func Patch(url, data string) *ClientResponse {
|
||||
return Request("PATCH", url, data)
|
||||
func Patch(url, data string) (*ClientResponse, error) {
|
||||
return Request("PATCH", url, []byte(data))
|
||||
}
|
||||
|
||||
func Connect(url, data string) *ClientResponse{
|
||||
return Request("CONNECT", url, data)
|
||||
func Connect(url, data string) (*ClientResponse, error) {
|
||||
return Request("CONNECT", url, []byte(data))
|
||||
}
|
||||
|
||||
func Options(url, data string) *ClientResponse{
|
||||
return Request("OPTIONS", url, data)
|
||||
func Options(url, data string) (*ClientResponse, error) {
|
||||
return Request("OPTIONS", url, []byte(data))
|
||||
}
|
||||
|
||||
func Trace(url, data string) *ClientResponse {
|
||||
return Request("TRACE", url, data)
|
||||
func Trace(url, data string) (*ClientResponse, error) {
|
||||
return Request("TRACE", url, []byte(data))
|
||||
}
|
||||
|
||||
func Request(method, url, data string) *ClientResponse {
|
||||
// 该方法支持二进制提交数据
|
||||
func Request(method, url string, data []byte) (*ClientResponse, error) {
|
||||
return NewClient().Request(method, url, data)
|
||||
}
|
||||
|
||||
20
g/net/ghttp/http_client_response.go
Normal file
20
g/net/ghttp/http_client_response.go
Normal file
@ -0,0 +1,20 @@
|
||||
package ghttp
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
)
|
||||
|
||||
// 获取返回的数据
|
||||
func (r *ClientResponse) ReadAll() []byte {
|
||||
body, err := ioutil.ReadAll(r.Body)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
return body
|
||||
}
|
||||
|
||||
// 关闭返回的HTTP链接
|
||||
func (r *ClientResponse) Close() {
|
||||
r.Response.Close = true
|
||||
r.Body.Close()
|
||||
}
|
||||
@ -5,25 +5,12 @@ type Controller struct {
|
||||
Server *Server
|
||||
}
|
||||
|
||||
// 控制器接口
|
||||
type ControllerApi interface {
|
||||
Get(r *ClientRequest, w *ServerResponse)
|
||||
Put(r *ClientRequest, w *ServerResponse)
|
||||
Post(r *ClientRequest, w *ServerResponse)
|
||||
Delete(r *ClientRequest, w *ServerResponse)
|
||||
Head(r *ClientRequest, w *ServerResponse)
|
||||
Patch(r *ClientRequest, w *ServerResponse)
|
||||
Connect(r *ClientRequest, w *ServerResponse)
|
||||
Options(r *ClientRequest, w *ServerResponse)
|
||||
Trace(r *ClientRequest, w *ServerResponse)
|
||||
}
|
||||
|
||||
func (c *Controller) Get(r *ClientRequest, w *ServerResponse) {}
|
||||
func (c *Controller) Put(r *ClientRequest, w *ServerResponse) {}
|
||||
func (c *Controller) Post(r *ClientRequest, w *ServerResponse) {}
|
||||
func (c *Controller) Delete(r *ClientRequest, w *ServerResponse) {}
|
||||
func (c *Controller) Head(r *ClientRequest, w *ServerResponse) {}
|
||||
func (c *Controller) Patch(r *ClientRequest, w *ServerResponse) {}
|
||||
func (c *Controller) Connect(r *ClientRequest, w *ServerResponse) {}
|
||||
func (c *Controller) Options(r *ClientRequest, w *ServerResponse) {}
|
||||
func (c *Controller) Trace(r *ClientRequest, w *ServerResponse) {}
|
||||
func (c *Controller) Get(*ClientRequest, *ServerResponse) {}
|
||||
func (c *Controller) Put(*ClientRequest, *ServerResponse) {}
|
||||
func (c *Controller) Post(*ClientRequest, *ServerResponse) {}
|
||||
func (c *Controller) Delete(*ClientRequest, *ServerResponse) {}
|
||||
func (c *Controller) Head(*ClientRequest, *ServerResponse) {}
|
||||
func (c *Controller) Patch(*ClientRequest, *ServerResponse) {}
|
||||
func (c *Controller) Connect(*ClientRequest, *ServerResponse) {}
|
||||
func (c *Controller) Options(*ClientRequest, *ServerResponse) {}
|
||||
func (c *Controller) Trace(*ClientRequest, *ServerResponse) {}
|
||||
14
g/net/ghttp/http_controller_rest.go
Normal file
14
g/net/ghttp/http_controller_rest.go
Normal file
@ -0,0 +1,14 @@
|
||||
package ghttp
|
||||
|
||||
// RESTful控制器接口
|
||||
type ControllerRest interface {
|
||||
Get(*ClientRequest, *ServerResponse)
|
||||
Put(*ClientRequest, *ServerResponse)
|
||||
Post(*ClientRequest, *ServerResponse)
|
||||
Delete(*ClientRequest, *ServerResponse)
|
||||
Head(*ClientRequest, *ServerResponse)
|
||||
Patch(*ClientRequest, *ServerResponse)
|
||||
Connect(*ClientRequest, *ServerResponse)
|
||||
Options(*ClientRequest, *ServerResponse)
|
||||
Trace(*ClientRequest, *ServerResponse)
|
||||
}
|
||||
@ -1,35 +0,0 @@
|
||||
package ghttp
|
||||
|
||||
import (
|
||||
"gitee.com/johng/gf/g/encoding/gjson"
|
||||
"io/ioutil"
|
||||
"gitee.com/johng/gf/g/os/glog"
|
||||
)
|
||||
|
||||
type ResponseJson struct {
|
||||
Result int `json:"result"`
|
||||
Message string `json:"message"`
|
||||
Data interface{} `json:"data"`
|
||||
}
|
||||
|
||||
// 关闭返回的HTTP链接
|
||||
func (r *ClientResponse) Close() {
|
||||
r.Response.Close = true
|
||||
r.Body.Close()
|
||||
}
|
||||
|
||||
// 返回固定格式的json
|
||||
func (r *ServerResponse) ResponseJson(result int, message string, data interface{}) {
|
||||
r.Header().Set("Content-type", "application/json")
|
||||
r.Write([]byte(gjson.Encode(ResponseJson{ result, message, data })))
|
||||
}
|
||||
|
||||
// 获取返回的数据
|
||||
func (r *ClientResponse) ReadAll() string {
|
||||
body, err := ioutil.ReadAll(r.Body)
|
||||
if err != nil {
|
||||
glog.Println(err)
|
||||
return ""
|
||||
}
|
||||
return string(body)
|
||||
}
|
||||
@ -7,16 +7,38 @@ import (
|
||||
"crypto/tls"
|
||||
"time"
|
||||
"log"
|
||||
"regexp"
|
||||
"gitee.com/johng/gf/g/os/glog"
|
||||
"sync"
|
||||
"errors"
|
||||
)
|
||||
|
||||
// http server结构体
|
||||
type Server struct {
|
||||
hmu sync.RWMutex // handlerMap互斥锁
|
||||
server http.Server // 底层http server对象
|
||||
config ServerConfig // 配置对象
|
||||
handlerMap HandlerMap // 回调函数
|
||||
}
|
||||
|
||||
// http回调函数
|
||||
type HandlerFunc func(*ClientRequest, *ServerResponse)
|
||||
|
||||
// uri与回调函数的绑定记录表
|
||||
type HandlerMap map[string]HandlerFunc
|
||||
|
||||
// 创建一个默认配置的HTTP Server(默认监听端口是80)
|
||||
func NewServer() (*Server) {
|
||||
server := Server{}
|
||||
server.SetConfig(defaultServerConfig)
|
||||
return &server
|
||||
}
|
||||
|
||||
// 执行
|
||||
func (s *Server)Run() error {
|
||||
// 底层http server配置
|
||||
if s.config.Handler == nil {
|
||||
s.config.Handler = http.HandlerFunc(s.defaultHttpHandle)
|
||||
}
|
||||
// 底层http server初始化
|
||||
s.server = http.Server {
|
||||
Addr : s.config.Addr,
|
||||
Handler : s.config.Handler,
|
||||
@ -26,16 +48,10 @@ func (s *Server)Run() error {
|
||||
MaxHeaderBytes : s.config.MaxHeaderBytes,
|
||||
}
|
||||
// 执行端口监听
|
||||
err := s.server.ListenAndServe()
|
||||
if err != nil {
|
||||
glog.Fatalln(err)
|
||||
if err := s.server.ListenAndServe(); err != nil {
|
||||
return err
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// 获取默认的http server设置
|
||||
func (h Server)GetDefaultSetting() ServerConfig {
|
||||
return defaultServerConfig
|
||||
return nil
|
||||
}
|
||||
|
||||
// http server setting设置
|
||||
@ -121,23 +137,25 @@ func (s *Server)SetServerRoot(root string) {
|
||||
// 绑定URI到操作函数/方法
|
||||
// pattern的格式形如:/user/list, put:/user, delete:/user
|
||||
// 支持RESTful的请求格式,具体业务逻辑由绑定的处理方法来执行
|
||||
func (s *Server)BindHandle(pattern string, handler HandlerFunc ) {
|
||||
func (s *Server)BindHandle(pattern string, handler HandlerFunc) error {
|
||||
s.hmu.Lock()
|
||||
defer s.hmu.Unlock()
|
||||
if s.handlerMap == nil {
|
||||
s.handlerMap = make(HandlerMap)
|
||||
}
|
||||
key := ""
|
||||
reg := regexp.MustCompile(`(\w+?)\s*:\s*(.+)`)
|
||||
result := reg.FindStringSubmatch(pattern)
|
||||
result := strings.Split(pattern, ":")
|
||||
if len(result) > 1 {
|
||||
key = strings.ToUpper(result[1]) + ":" + result[2]
|
||||
key = strings.ToUpper(result[0]) + ":" + result[1]
|
||||
} else {
|
||||
key = strings.TrimSpace(pattern)
|
||||
}
|
||||
if _, ok := s.handlerMap[key]; ok {
|
||||
panic("duplicated http server handler for: " + pattern)
|
||||
return errors.New("duplicated http server handler for: " + pattern)
|
||||
} else {
|
||||
s.handlerMap[key] = handler
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// 通过映射数组绑定URI到操作函数/方法
|
||||
@ -148,7 +166,7 @@ func (s *Server)BindHandleByMap(m HandlerMap) {
|
||||
}
|
||||
|
||||
// 绑定控制器,控制器需要继承gmvc.ControllerBase对象并实现需要的REST方法
|
||||
func (s *Server)BindController(uri string, c ControllerApi) {
|
||||
func (s *Server)BindController(uri string, c ControllerRest) {
|
||||
s.BindHandleByMap(HandlerMap{
|
||||
"GET:" + uri : c.Get,
|
||||
"PUT:" + uri : c.Put,
|
||||
|
||||
46
g/net/ghttp/http_server_config.go
Normal file
46
g/net/ghttp/http_server_config.go
Normal file
@ -0,0 +1,46 @@
|
||||
package ghttp
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"crypto/tls"
|
||||
"time"
|
||||
"log"
|
||||
"gitee.com/johng/gf/g/os/gfile"
|
||||
)
|
||||
|
||||
// HTTP Server 设置结构体
|
||||
type ServerConfig struct {
|
||||
// HTTP Server基础字段
|
||||
Addr string // 监听IP和端口,监听本地所有IP使用":端口"
|
||||
Handler http.Handler // 默认的处理函数
|
||||
TLSConfig *tls.Config // TLS配置
|
||||
ReadTimeout time.Duration
|
||||
WriteTimeout time.Duration
|
||||
IdleTimeout time.Duration
|
||||
MaxHeaderBytes int // 最大的header长度
|
||||
ErrorLog *log.Logger // 错误日志的处理接口
|
||||
// gf 扩展信息字段
|
||||
IndexFiles []string // 默认访问的文件列表
|
||||
IndexFolder bool // 如果访问目录是否显示目录列表
|
||||
ServerAgent string // server agent
|
||||
ServerRoot string // 服务器服务的本地目录根路径
|
||||
}
|
||||
|
||||
// 默认HTTP Server
|
||||
var defaultServerConfig = ServerConfig {
|
||||
Addr : ":80",
|
||||
Handler : nil,
|
||||
ReadTimeout : 60 * time.Second,
|
||||
WriteTimeout : 60 * time.Second,
|
||||
IdleTimeout : 60 * time.Second,
|
||||
MaxHeaderBytes : 1024,
|
||||
IndexFiles : []string{"index.html", "index.htm"},
|
||||
IndexFolder : false,
|
||||
ServerAgent : "gf",
|
||||
ServerRoot : gfile.SelfDir(),
|
||||
}
|
||||
|
||||
// 获取默认的http server设置
|
||||
func DefaultSetting() ServerConfig {
|
||||
return defaultServerConfig
|
||||
}
|
||||
@ -15,8 +15,8 @@ import (
|
||||
// 默认HTTP Server处理入口,底层默认使用了gorutine调用该接口
|
||||
func (s *Server)defaultHttpHandle(w http.ResponseWriter, r *http.Request) {
|
||||
request := ClientRequest{}
|
||||
response := ServerResponse {}
|
||||
request.Request = *r
|
||||
response := ServerResponse {server : s}
|
||||
request.Request = *r
|
||||
response.ResponseWriter = w
|
||||
if f, ok := s.handlerMap[r.URL.Path]; ok {
|
||||
f(&request, &response)
|
||||
@ -93,8 +93,7 @@ func (s *Server)listDir(w http.ResponseWriter, f http.File) {
|
||||
if d.IsDir() {
|
||||
name += "/"
|
||||
}
|
||||
url := url.URL{Path: name}
|
||||
fmt.Fprintf(w, "<a href=\"%s\">%s</a>\n", url.String(), ghtml.SpecialChars(name))
|
||||
fmt.Fprintf(w, "<a href=\"%s\">%s</a>\n", url.URL{Path: name}.String(), ghtml.SpecialChars(name))
|
||||
}
|
||||
fmt.Fprintf(w, "</pre>\n")
|
||||
}
|
||||
|
||||
36
g/net/ghttp/http_server_response.go
Normal file
36
g/net/ghttp/http_server_response.go
Normal file
@ -0,0 +1,36 @@
|
||||
package ghttp
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"gitee.com/johng/gf/g/encoding/gjson"
|
||||
)
|
||||
|
||||
// 服务端请求返回对象
|
||||
type ServerResponse struct {
|
||||
http.ResponseWriter
|
||||
server *Server // 所属Server对象
|
||||
}
|
||||
|
||||
// 返回的固定JSON数据结构
|
||||
type ResponseJson struct {
|
||||
Result int `json:"result"`
|
||||
Message string `json:"message"`
|
||||
Data interface{} `json:"data"`
|
||||
}
|
||||
|
||||
// 返回信息
|
||||
func (r *ServerResponse) Response(content []byte) {
|
||||
if r.Header().Get("Content-Type") == "" {
|
||||
r.Header().Set("Content-Type", "text/plain; charset=utf-8")
|
||||
}
|
||||
r.Write(content)
|
||||
}
|
||||
|
||||
// 返回固定格式的json
|
||||
func (r *ServerResponse) ResponseJson(result int, message string, data interface{}) {
|
||||
if r.Header().Get("Content-Type") == "" {
|
||||
r.Header().Set("Content-Type", "application/json")
|
||||
}
|
||||
r.Write([]byte(gjson.Encode(ResponseJson{ result, message, data })))
|
||||
}
|
||||
|
||||
@ -8,35 +8,41 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
gCACHE_GROUP_SIZE = 4 // 缓存分区大小,不能超过uint8的最大值
|
||||
gDEFAULT_CACHE_GROUP_SIZE = 4 // 默认缓存分区大小,不能超过uint8的最大值
|
||||
)
|
||||
|
||||
// 缓存对象
|
||||
type Cache struct {
|
||||
sync.RWMutex
|
||||
m map[uint8]*CacheMap // 以分区大小数字作为索引
|
||||
g uint8 // 分区大小
|
||||
m map[uint8]*CacheMap // 以分区大小数字作为索引
|
||||
}
|
||||
|
||||
// 缓存分区对象
|
||||
type CacheMap struct {
|
||||
sync.RWMutex
|
||||
deleted bool // 对象是否已删除,以便判断停止goroutine
|
||||
closed bool // 对象是否已删除,以便判断停止goroutine
|
||||
m map[string]CacheItem // 键值对
|
||||
}
|
||||
|
||||
// 缓存数据项
|
||||
type CacheItem struct {
|
||||
v interface{} // 缓存键值
|
||||
e int64 // 过期时间
|
||||
}
|
||||
|
||||
// 全局缓存管理对象
|
||||
var cache *Cache = New()
|
||||
var cache *Cache = New(gDEFAULT_CACHE_GROUP_SIZE)
|
||||
|
||||
// Cache对象按照缓存键名首字母做了分组
|
||||
func New() *Cache {
|
||||
func New(group uint8) *Cache {
|
||||
c := &Cache {
|
||||
g : group,
|
||||
m : make(map[uint8]*CacheMap),
|
||||
}
|
||||
// 初始化分区对象
|
||||
var i uint8 = 0
|
||||
for ; i < gCACHE_GROUP_SIZE; i++ {
|
||||
for ; i < group; i++ {
|
||||
m := &CacheMap {
|
||||
m : make(map[string]CacheItem),
|
||||
}
|
||||
@ -158,20 +164,14 @@ func (c *Cache) Size() int {
|
||||
func (c *Cache) Close() {
|
||||
c.RLock()
|
||||
for _, cm := range c.m {
|
||||
cm.Lock()
|
||||
cm.deleted = true
|
||||
cm.Unlock()
|
||||
cm.Close()
|
||||
}
|
||||
c.RUnlock()
|
||||
|
||||
c.Lock()
|
||||
c.m = nil
|
||||
c.Unlock()
|
||||
}
|
||||
|
||||
// 计算缓存的索引
|
||||
func (c *Cache) getIndex(k string) uint8 {
|
||||
return uint8(ghash.BKDRHash([]byte(k)) % gCACHE_GROUP_SIZE)
|
||||
return uint8(ghash.BKDRHash([]byte(k)) % uint32(c.g))
|
||||
}
|
||||
|
||||
// 设置kv缓存键值对,过期时间单位为毫秒
|
||||
@ -207,26 +207,32 @@ func (cm *CacheMap) Remove(k string) {
|
||||
cm.Unlock()
|
||||
}
|
||||
|
||||
// 自动清理过期键值对(每间隔60秒执行)
|
||||
// 关闭缓存分区
|
||||
func (cm *CacheMap) Close() {
|
||||
cm.Lock()
|
||||
cm.closed = true
|
||||
cm.Unlock()
|
||||
}
|
||||
|
||||
// 是否删除
|
||||
func (cm *CacheMap) isClosed() bool {
|
||||
cm.RLock()
|
||||
r := cm.closed
|
||||
cm.RUnlock()
|
||||
return r
|
||||
}
|
||||
|
||||
// 自动清理过期键值对(每间隔3秒执行)
|
||||
func (cm *CacheMap) autoClearLoop() {
|
||||
for !cm.deleted {
|
||||
expired := make([]string, 0)
|
||||
cm.RLock()
|
||||
for !cm.isClosed() {
|
||||
cm.Lock()
|
||||
for k, v := range cm.m {
|
||||
if v.e > 0 && v.e < gtime.Millisecond() {
|
||||
expired = append(expired, k)
|
||||
}
|
||||
}
|
||||
cm.RUnlock()
|
||||
|
||||
if len(expired) > 0 {
|
||||
cm.Lock()
|
||||
for _, k := range expired {
|
||||
delete(cm.m, k)
|
||||
}
|
||||
cm.Unlock()
|
||||
}
|
||||
time.Sleep(60 * time.Second)
|
||||
cm.Unlock()
|
||||
time.Sleep(3 * time.Second)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user