手撸博客2 留言板

作者: FinaLone | 来源:发表于2020-10-25 14:54 被阅读0次

0 为什么是留言板?

需要给easy-blog开一个头,想来想去,留言板好像比较合适。涉及到了需要用到的大部分内容:

  • html模板
  • 数据库
  • gin

1 设计思路

1.1 设计数据库

数据库字段如下:

  • 留言ID
  • 留言人昵称
  • 留言人邮箱
  • 留言内容
  • 留言时间

1.2 设计页面

  • 页面顶部为留言人昵称和邮箱的输入框
  • 下面是留言框
  • 再下面是历史留言的展示

2 实现细节

2.1 创建数据库表

create TABLE message_board(
    messageId int primary key auto_increment,
    authorName varchar(20),
    authorEmail varchar(30),
    message text,
    messageTime datetime)

2.2 创建html模板

我们这里先使用一个简易的页面,我承认确实很丑。

2.2.1 留言提交区

使用一个表单来实现留言提交区,使用POST方式提交到/msgboard路径。稍后会在路由中定义页面展示和后台处理的路由。

    <fieldset>
        <legend>留言</legend>
        <form action="/msgboard" method='post'>
            <div>
                <label for="name">Name:</label>
                <input type="text" id="name" name="name">
            </div>
            <div>
                <label for="mail">Mail:</label>
                <input type="email" id="mail" name="mail">
            </div>
            <div>
                <label for="msg">Message:</label>
                <textarea id="msg" name="msg"></textarea>
            </div>
            <div>
                <button type="submit">Push Message!</button>
            </div>
        </form>
    </fieldset>

效果如下:


留言提交

2.2.2 历史留言展示区

使用表格来实现留言展示。表格使用html模板来填充,使用传入的结构中的各个字段对td标签中的内容进行替换。

    <div class="msglist">
        {{if len .}}
            <table border="1">
                <tr>
                    <th>留言ID</th>
                    <th>留言人</th>
                    <th>邮箱</th>
                    <th>留言时间</th>
                    <th>留言内容</th>
                </tr>
            {{range .}}
                <tr>
                    <td>{{.MsgID}}</td>
                    <td>{{.AuthorName}}</td>
                    <td>{{.AuthorEmail}}</td>
                    <td>{{.MsgTime}}</td>
                    <td>{{.Msg}}</td>
                </tr>
            {{end}}
            </table>
        {{end}}
    </div>

效果如下:


留言展示

2.3 创建路由

创建以下两个路由,分别用来响应/msgboard路径的GET和POST请求。其中GET路由用来响应界面,POST请求用来处理新增留言。

engine := gin.Default()
engine.GET("/msgboard", msgboard.GetHandler)
engine.POST("/msgboard", msgboard.PostMsgHandler)

msgboard是一个本地的包,其中有GetHandler和PostHandler两个对外的函数。
另外,因为我们的需要使用到html模板,并且模板中会引用css或js的静态文件,需要添加如下逻辑:

engine.LoadHTMLGlob("./template/*") //加载html模板,加载后才能使用
engine.Static("/static", "./static") //配置静态文件服务,配置后才可以引用本地的静态文件

2.4 创建路由处理函数

在msgboard包中创建路由函数。

2.4.1 GetHandler

func GetHandler(c *gin.Context) {
    //Get msgs from sql
    msgs, err := dao.SelectAllMessage(SqlxDB)
    if err != nil {
        fmt.Println("get msgs from db err", err)
        c.String(http.StatusInternalServerError, err)
    }

    c.HTML(http.StatusOK, "msgboard.html", msgs)
}

其中dao是我们封装的数据库处理包,这里先从数据库中读取所有的留言信息,然后将其传入msgboard.html模板,并返回给用户。
msgs的结构如下,字段和模板中的数据对应:

type Message struct {
    MsgID       int    `db:"messageId"`
    AuthorName  string `db:"authorName"`
    AuthorEmail string `db:"authorEmail"`
    Msg         string `db:"message"`
    MsgTime     string `db:"messageTime"`
}

2.4.2 PostHandler

unc PostHandler(c *gin.Context) {
    //Write new msg to sql
    var msg model.Message
    msg.AuthorName = c.DefaultPostForm("name", "nobody")
    msg.AuthorEmail = c.DefaultPostForm("mail", "无邮箱信息")
    msg.Msg = c.DefaultPostForm("msg", "")
    dao.InsertOneMessage(SqlxDB, &msg)
    GetHandler(c)
}

PostHandler先获取POST请求中携带的信息,DefaultPostForm在请求中未包含该字段未,使用第二个参数的默认值代替。

msg.AuthorName = c.DefaultPostForm("name", "nobody")
msg.AuthorEmail = c.DefaultPostForm("mail", "无邮箱信息")
msg.Msg = c.DefaultPostForm("msg", "")

使用dao包中封装的InsertOneMessage函数将一条留言插入到数据库中,并调用GetHandler将所有留言的页面返回给用户。这里后面可以优化为使用ajax的方式更新页面,而不是整个返回。

2.5 数据库处理

2.5.1 数据库连接

dbutil包的init函数中初始化数据库连接,保证后台运行起来时,数据库已就绪。
数据库处理使用了sqlx这个数据库包,其扩展了官方的sql包。注意在这里要匿名导入mysql的驱动包github.com/go-sql-driver/mysql,使用其中的init函数初始化mysql驱动,否则无法连接到mysql数据库。其他数据库也是同理。
所有服务使用SQLXDB作为服务器连接的handle,当数据库连接失败时,触发panic,服务无法启动。

package dbutil

import (
    "fmt"

    "github.com/finalone/easy-blog/app/config"
    _ "github.com/go-sql-driver/mysql"
    "github.com/jmoiron/sqlx"
)

var (
    // SQLXDB is sqlx instance
    SQLXDB *sqlx.DB
)

func init() {
    if SQLXDB != nil {
        return
    }
    SQLXDB = NewSQLXDB()
}

// NewSQLXDB get a *sqlx.DB
func NewSQLXDB() *sqlx.DB {
    cfg := &config.Cfg
    if cfg == nil {
        return nil
    }

    dsn := fmt.Sprintf("%s:%s@tcp(%s:%s)/easyblog?charset=utf8&parseTime=True", cfg.User, cfg.Passwd, cfg.Addr, cfg.Port)

    db, err := sqlx.Connect("mysql", dsn)
    if err != nil {
        fmt.Println("sql connect error", err)
        panic("sql connect error")
    }

    db.SetMaxOpenConns(20)
    db.SetMaxIdleConns(10)

    return db
}

2.5.2 数据库使用

前面提到,我们封装了dao包来实现对数据库的操作。目前dao包中只有两个函数,获取所有留言和插入一条留言,这个逻辑比较简单,就不再详述了。

// SelectAllMessage get all message from table message_board
func SelectAllMessage(sqlxDB *sqlx.DB) (*[]model.Message, error) {
    var msgs []model.Message
    sql := `SELECT * FROM message_board`
    err := sqlxDB.Select(&msgs, sql)
    if err != nil {
        return nil, err
    }

    return &msgs, nil
}

// InsertOneMessage insert one message to table message_board
func InsertOneMessage(sqlxDB *sqlx.DB, msg *model.Message) error {
    sql := `INSERT INTO message_board (authorName, authorEmail, message, messageTime) values (?, ?, ?, NOW())`
    _, err := sqlxDB.Exec(sql, msg.AuthorName, msg.AuthorEmail, msg.Msg)
    if err != nil {
        fmt.Println("insert msg err", err)
        return err
    }

    return nil
}

3 小结

本节介绍了留言板页面的几个关键点:

  • 数据库
  • 路由
  • GET和POST请求的不同处理
  • HTML模板

因为我目前还在思考如何布置整个系统的框架,这部分说的比较粗糙,待框架确定后,将各个模块放的正确的位置,再进行分享。

相关文章

  • 手撸博客2 留言板

    0 为什么是留言板? 需要给easy-blog开一个头,想来想去,留言板好像比较合适。涉及到了需要用到的大部分内容...

  • 起点

    打算自己手撸一个博客系统,练练手。后端使用go的gin框架+mysql,前端手撸js吧。 应该会挺丑,哈哈~~

  • 手撸博客1 gin初探

    之前只听说过gin的名字,第一次接触使用。参考了这篇文章:https://www.yoytang.com/go-g...

  • 手撸博客4 写文章

    1 设计思路 在文章列表页面显示写文章按钮,点击写文章后进入新文章的编辑页面。 在具体文章页面显示编辑按钮,点击编...

  • 大厂敲门砖——算法!手撸3道高频算法题,检测真水平!

    3道高频算法题 手撸算法1:查找数组中重复元素和重复元素的个数 手撸算法2:写个二分查找demo吧 手撸算法3:把...

  • 手撸 Vue2

    概念说明 hijackData 劫持数据让 vm.key 代理 vm.$data.key hijackData2 ...

  • 手撸博客3 文章列表及文章

    1 设计思路 1.1 路由设计 /article路由到文章列表页面/article/aid路由到具体的文章页面 1...

  • 第一篇博客

    这是我的第一篇博客 没错这是我的第一篇博客,以前老是说做一个程序员不光能撸一手好代码,还必须写得一手好文档,可惜我...

  • 2018-09-05使用leanCloud,增添数据与获取数据功

    有一阵时间没写博客了,今天更。 留言板留言 这次的留言板主要是加在网页里面,可以是简历等等,任何访问网页的人都有权...

  • 手撸博客5 导航栏及layout模板

    截止目前,我们的blog只有单个的页面,没有将其统一管理起来。要管理有两种方法,相信大家都见过: 首页,包含指向每...

网友评论

    本文标题:手撸博客2 留言板

    本文链接:https://www.haomeiwen.com/subject/ttnjmktx.html