zoukankan      html  css  js  c++  java
  • 通过Beego将之前实现的短url项目实现

    正好通过这个小例子对之前了解的beego框架的基本内容进行一个简单的应用

    实现的完整代码地址:https://github.com/pythonsite/go_simple_code/tree/master/beego_short_url

    数据库没有什么变化,还是和之前一样,主要是把处理逻辑放到beego中就可以了

    代码的主要目录为:

    localhost:beego_short_url zhaofan$ tree
    .
    ├── beego_short_url
    ├── conf
    │   └── app.conf
    ├── controllers
    │   ├── default.go
    │   └── short_url.go
    ├── main.go
    ├── models
    │   └── data.go
    ├── routers
    │   └── router.go
    ├── static
    │   ├── css
    │   ├── img
    │   └── js
    │       └── reload.min.js
    ├── tests
    │   └── default_test.go
    └── views
        └── index.tpl
    
    10 directories, 10 files

    关于长短url相互转换的的请求和返回定义的struct在models下的data中,代码为:

    package models
    
    
    type Long2ShortRequest struct {
        OriginUrl string `json:"origin_url"`
    }
    
    type ResponseHeader struct {
        Code int `json:"code"`
        Message string `json:"message"`
    }
    
    type Long2ShortResponse struct {
        ResponseHeader
        ShortUrl string `json:"short_url"`
    }
    
    type Short2LongRequest struct {
        ShortUrl string `json:"short_url"`
    }
    
    type Short2LongResponse struct {
        ResponseHeader
        OriginUrl string `json:"origin_url"`
    }
    
    type ShortUrl struct {
        ShortUrl string `json:"short_url" db:"short_url"`
    }

    而将原来在logic中的处理逻辑都放到了controllers中的short_url文件中

    package controllers
    
    import (
        "github.com/astaxie/beego"
        "beego_short_url/models"
        "encoding/json"
        "database/sql"
        "crypto/md5"
        "github.com/jmoiron/sqlx"
        "fmt"
        _ "github.com/go-sql-driver/mysql"
    )
    
    var (
        Db *sqlx.DB
    )
    
    func InitDb()(err error){
        Db, err = sqlx.Open("mysql",beego.AppConfig.String("Db::dsn"))
        if err != nil{
            beego.Error("connect to mysql failed:",err)
            return
        }
        return
    }
    
    type ShortUrl struct {
        Id int64 `db:"id"`
        ShortUrl string `db:"short_url"`
        OriginUrl string `db:"origin_url"`
        HashCode string `db:"hash_code"`
    }
    
    type ShortUrlController struct {
        beego.Controller
    }
    
    
    func (c *ShortUrlController) Jump() {
        shortUrl := c.GetString("shorturl")
        if len(shortUrl) == 0{
            return
        }
        var req models.Short2LongRequest
        var resp *models.Short2LongResponse = &models.Short2LongResponse{}
    
        defer func(){
            if err := recover();err != nil{
                beego.Error("panic err:",err)
                //resp.Code = 500
                //resp.Message = "server busy"
                //c.Data["json"] = resp
                //c.ServeJSON()
                return
            }
        }()
        req.ShortUrl = shortUrl
        resp,err := Short2Long(&req)
        if err != nil{
            beego.Error("short2Long failed error:",err)
            return
        }
    
        beego.Info("origin url:%s short url:%s",resp.OriginUrl,shortUrl)
        c.Redirect(resp.OriginUrl,301)
    }
    
    func (c *ShortUrlController) ShortUrlList() {
        limit,err := c.GetInt("limit")
        if err != nil{
            beego.Warn("not have limit params use default 10")
            limit = 10
        }
        data,err := GetLastShortUrl(limit)
        if err != nil{
            beego.Error("from db get url list error:",err)
    
        }
    
        for i,v:= range data{
            v.ShortUrl = fmt.Sprintf("/jump/?shorturl=%s",v.ShortUrl)
            data[i] = v
        }
    
        c.Data["url_list"] = data
        c.TplName = "index.tpl"
    }
    
    func(c *ShortUrlController) Long2Short(){
        var req models.Long2ShortRequest
        var resp *models.Long2ShortResponse = &models.Long2ShortResponse{}
    
        defer func(){
            if err := recover();err != nil{
                beego.Error("panic err:",err)
                resp.Code = 500
                resp.Message = "server busy"
                c.Data["json"] = resp
                c.ServeJSON()
                return
            }
        }()
    
    
        err := json.Unmarshal(c.Ctx.Input.RequestBody,&req)
        if err != nil{
            beego.Error("unmarshal failed,err:",err)
            resp.Code = 1001
            resp.Message = "json unmarshal failed"
            c.Data["json"] = resp
            c.ServeJSON()
            return
        }
        resp,err = Long2Short(&req)
        if err != nil{
            beego.Error("long2short failed,err:",err)
            resp.Code = 1002
            resp.Message = "long2short failed"
            c.Data["json"] = resp
            c.ServeJSON()
            return
        }
        c.Data["json"] = resp
        c.ServeJSON()
    
    
    
    }
    
    func(c *ShortUrlController) Short2Long(){
        var req models.Short2LongRequest
        var resp *models.Short2LongResponse = &models.Short2LongResponse{}
    
        defer func(){
            if err := recover();err != nil{
                beego.Error("panic err:",err)
                resp.Code = 500
                resp.Message = "server busy"
                c.Data["json"] = resp
                c.ServeJSON()
                return
            }
        }()
    
    
        err := json.Unmarshal(c.Ctx.Input.RequestBody,&req)
        if err != nil{
            beego.Error("unmarshal failed,err:",err)
            resp.Code = 1001
            resp.Message = "json unmarshal failed"
            c.Data["json"] = resp
            c.ServeJSON()
            return
        }
        resp,err = Short2Long(&req)
        if err != nil{
            beego.Error("Short2Long failed,err:",err)
            resp.Code = 1002
            resp.Message = "long2short failed"
            c.Data["json"] = resp
            c.ServeJSON()
            return
        }
        c.Data["json"] = resp
        c.ServeJSON()
    }
    
    
    
    func Long2Short(req *models.Long2ShortRequest) (response *models.Long2ShortResponse, err error) {
        response = &models.Long2ShortResponse{}
        urlMd5 := fmt.Sprintf("%x",md5.Sum([]byte(req.OriginUrl)))
        var short ShortUrl
        err = Db.Get(&short,"select id,short_url,origin_url,hash_code from short_url where hash_code=?",urlMd5)
        if err == sql.ErrNoRows{
            err = nil
            // 数据库中没有记录,重新生成一个新的短url
            shortUrl,errRet := generateShortUrl(req,urlMd5)
            if errRet != nil{
                err = errRet
                return
            }
            response.ShortUrl = shortUrl
            return
        }
        if err != nil{
            return
        }
        response.ShortUrl = short.ShortUrl
        return
    }
    
    func generateShortUrl(req *models.Long2ShortRequest,hashcode string)(shortUrl string,err error){
        result,err := Db.Exec("insert INTO short_url(origin_url,hash_code)VALUES (?,?)",req.OriginUrl,hashcode)
        if err != nil{
            return
        }
        // 0-9a-zA-Z 六十二进制
        insertId,_:= result.LastInsertId()
        shortUrl = transTo62(insertId)
        _,err = Db.Exec("update short_url set short_url=? where id=?",shortUrl,insertId)
        if err != nil{
            fmt.Println(err)
            return
        }
        return
    }
    
    // 将十进制转换为62进制   0-9a-zA-Z 六十二进制
    func transTo62(id int64)string{
        // 1 -- > 1
        // 10-- > a
        // 61-- > Z
        charset := "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
        var shortUrl []byte
        for{
            var result byte
            number := id % 62
            result = charset[number]
            var tmp []byte
            tmp = append(tmp,result)
            shortUrl = append(tmp,shortUrl...)
            id = id / 62
            if id == 0{
                break
            }
        }
        fmt.Println(string(shortUrl))
        return string(shortUrl)
    }
    
    
    func Short2Long(req *models.Short2LongRequest) (response *models.Short2LongResponse, err error) {
        response = &models.Short2LongResponse{}
        var short ShortUrl
        err = Db.Get(&short,"select id,short_url,origin_url,hash_code from short_url where short_url=?",req.ShortUrl)
        if err == sql.ErrNoRows{
            response.Code = 404
            return
        }
        if err != nil{
            response.Code = 500
            return
        }
        response.OriginUrl = short.OriginUrl
        return
    }
    
    
    func GetLastShortUrl(limit int)(result []*models.ShortUrl,err error){
        err = Db.Select(&result,"select short_url from short_url ORDER BY id DESC  limit ? ",limit)
        return
    }

    在这里添加了一些之前没有的功能:
    获取数据库所有的short url 并且显示在页面上了,不过这里非常丑,如图:

    我们可以通过点击相应的连接就会跳转到长url的页面
    也可以通过模拟发送post请求来查看转换的情况:

  • 相关阅读:
    sourceTree免密码校验
    elasticsearch 服务安全配置
    qconf 介绍
    解决mysql不能远程登录的问题
    从git上下载代码并导入eclipse
    MAVEN 工程打包resources目录外的更多资源文件
    也谈BIO | NIO | AIO (Java版--转)
    web.xml 配置中classpath: 与classpath*:的区别
    Java @override报错的解决方法
    maven上传自定义jar到本地仓库
  • 原文地址:https://www.cnblogs.com/zhaof/p/8627928.html
Copyright © 2011-2022 走看看