beego搭建個人部落格(一)
上次我準備用Java的ssm框架來搭建一個部落格系統,我覺得後來覺得Java實在太羅嗦了,賊多的配置檔案。最近接觸了go的web開發,框架有beego,gin、revel以及iris,beego雖然很重量級,效能也差iris太遠,但是它對國人的學習是十分有好的,首先它的作者是國人,理念呢也還是參照傳統的mvc概念,加上詳盡的文件是一個非常好的入門go web的框架,所以我決定使用beego搭建一個個人部落格,前臺展示使用layui,畢竟我比較懶!
準備工作:
a.下載Sublime Text3,安裝go外掛,在mysql建立資料庫db_beego,然後匯入db_beego.sql(在github上有,連結在文章最下面),主要就是建立了使用者,文章,評論表並且插入幾條測試資料,大家隨便看下知道就可以了。
b.你的電腦肯定安裝了go環境,然後安裝beego,可以參考https://blog.csdn.net/suresand/article/details/79548796
$ go get -u github.com/astaxie/beego
$ go get -u github.com/beego/bee
直接安裝beego的框架及開發工具
或許還需要安裝go-mysql的驅動
go get github.com/go-sql-driver/mysql
c.然後在你的gopath的src目錄下執行:
bee new blog
然後看見自動建立的blog資料夾,進入blog資料夾:
bee run
訪問http://localhost:8080/出現welcome to beego畫面表示準備工作完成,然後就可以開始我們的開發了,當然由於我的水平有限,有模糊的地方請大家詳細參考beego文件https://beego.me/docs/intro/
一 配置檔案
首先配置app.conf,這個app.conf配置檔案可以做很多事,這裡我們主要配置資料庫的連結資訊:
appname = blog
httpport = 8080
runmode = dev
# MYSQL地址
dbhost = localhost
# MYSQL埠
dbport = 3306
# MYSQL使用者名稱
dbuser = root
# MYSQL密碼
dbpassword = 你的密碼
# MYSQL資料庫名稱
dbname = db_beego
# MYSQL表字首
dbprefix = tb_
二 構建登陸邏輯
我在考慮是先把所有的結構搭出來,還是一個一個去實現呢,然後我選擇了後者,因為這樣可以更快的做出效果提升興趣,所以我準備一上來就把登陸邏輯做個模版出來
a.首先我們需要將資料庫連線註冊到beego的orm中,這是各個操作都會用到的,在models檔案下新建base.go:
package models
import (
"github.com/astaxie/beego/orm"
"github.com/astaxie/beego"
)
func Init() {
dbhost := beego.AppConfig.String("dbhost")
dbport := beego.AppConfig.String("dbport")
dbuser := beego.AppConfig.String("dbuser")
dbpassword := beego.AppConfig.String("dbpassword")
dbname := beego.AppConfig.String("dbname")
if dbport == "" {
dbport = "3306"
}
dsn := dbuser + ":" + dbpassword + "@tcp(" + dbhost + ":" + dbport + ")/" + dbname + "?charset=utf8&loc=Asia%2FShanghai"
orm.RegisterDataBase("default", "mysql", dsn)
orm.RegisterModel(new(User))
}
//返回帶字首的表名
func TableName(str string) string {
return beego.AppConfig.String("dbprefix") + str
}
上面這段程式碼還是很容易看懂的,就是初始化資料庫連線,並且將User註冊到orm裡去
b.登入當然是跟使用者相關了,在models繼續新建user.go:
package models
import "time"
type User struct {
Id int
Username string
Password string
Email string
LoginCount int
LastTime time.Time
LastIp string
State int8
Created time.Time
Updated time.Time
}
func (m *User) TableName() string {
return TableName("user")
}
c.我們要注意不允許在未登入的情況下訪問我們的controller,所以需要判斷是否已經登入,在controller檔案下新建base.go:
package controllers
import (
"github.com/astaxie/beego"
"github.com/astaxie/beego/orm"
"strings"
"github.com/Echosong/beego_blog/models"
)
type baseController struct {
beego.Controller
o orm.Ormer
controllerName string
actionName string
}
func (p *baseController) Prepare() {
controllerName, actionName := p.GetControllerAndAction()
p.controllerName = strings.ToLower(controllerName[0 : len(controllerName)-10])
p.actionName = strings.ToLower(actionName)
p.o = orm.NewOrm();
if strings.ToLower( p.controllerName) == "admin" && strings.ToLower(p.actionName) != "login"{
if p.GetSession("user") == nil{
p.History("未登入","/admin/login")
//p.Ctx.WriteString(p.controllerName +"==="+ p.actionName)
}
}
//初始化前臺頁面相關元素
if strings.ToLower( p.controllerName) == "blog"{
p.Data["actionName"] = strings.ToLower(actionName)
var result []*models.Config
p.o.QueryTable(new(models.Config).TableName()).All(&result)
configs := make(map[string]string)
for _, v := range result {
configs[v.Name] = v.Value
}
p.Data["config"] = configs
}
}
//用來做跳轉的邏輯展示
func (p *baseController) History(msg string, url string) {
if url == ""{
p.Ctx.WriteString("<script>alert('"+msg+"');window.history.go(-1);</script>")
p.StopRun()
}else{
p.Redirect(url,302)
}
}
//獲取使用者IP地址
func (p *baseController) getClientIp() string {
s := strings.Split(p.Ctx.Request.RemoteAddr, ":")
return s[0]
}
Prepare()方法就是驗證使用者是否登入。
d.那麼我們現在來寫我們的登入controller,在controller資料夾下新建admin.go
package controllers
import (
"github.com/liwd/blog/models"
"strconv"
"github.com/liwd/blog/util"
"fmt"
"strings"
"time"
)
//繼承baseController
type AdminController struct {
baseController
}
//後臺使用者登入
func (c *AdminController) Login() {
if c.Ctx.Request.Method == "POST" {
username := c.GetString("username")
password := c.GetString("password")
user := models.User{Username:username}
c.o.Read(&user,"username")
if user.Password == "" {
c.History("賬號不存在","")
}
if util.Md5(password) != strings.Trim(user.Password, " ") {
c.History("密碼錯誤", "")
}
user.LastIp = c.getClientIp()
user.LoginCount = user.LoginCount +1
if _, err := c.o.Update(&user); err != nil {
c.History("登入異常", "")
} else {
c.History("登入成功", "/admin/main.html")
}
c.SetSession("user", user)
}
c.TplName = c.controllerName+"/login.html"
}
//主頁
func (c *AdminController) Main() {
c.TplName = c.controllerName + "/main.tpl"
}
c.TplName相當於http.Handle(http.FileServer())是用來尋找html的。
這裡使用了md5對密碼加密,我們在util檔案下新建function.go:
package util
import (
"crypto/md5"
"crypto/rand"
"encoding/base64"
"fmt"
"io"
"net/url"
"strings"
)
func Md5(str string) string {
hash := md5.New()
hash.Write([]byte(str))
return fmt.Sprintf("%x", hash.Sum(nil))
}
func Rawurlencode(str string) string {
return strings.Replace(url.QueryEscape(str), "+", "%20", -1)
}
//生成Guid字串
func UniqueId() string {
b := make([]byte, 48)
if _, err := io.ReadFull(rand.Reader, b); err != nil {
return ""
}
return Md5(base64.URLEncoding.EncodeToString(b))
}
e.構建路由
因為Java裡面tomcat或者其它server已經幫我們構建好了路由便不需要我們自己構建了,而go自己已經封裝好了net/http模組,所以我們自己構建路由也很是方便,修改router.go:
package routers
import (
"github.com/liwd/blog/controllers"
"github.com/astaxie/beego"
)
func init() {
bego.AutoRouter(&controllers.AdminController{})
}
這裡 bego.AutoRouter(&controllers.AdminController{})將AdminController的所有方法自動註冊為路由了,訪問/admin/login.html或者/admin/login都可以跳轉到login方法,是不是很簡單!
f.編寫登入頁面和登陸後的主頁面
首先新建static檔案,將我專案中static檔案下的所有資源複製到你的專案中,然後編寫登入頁面,在view資料夾中新建admin資料夾,在admin資料夾中新建login.html:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<title>後臺登入</title>
<link rel="stylesheet" href="/static/plug/layui/css/layui.css">
<style>
.main {
margin: 0 auto;
width: 400px;
border: 1px solid;
border-color: #eeeeee;
border-radius: 5px;
margin-top: 100px;
}
</style>
</head>
<body>
<script type="text/javascript" src="/static/plug/layui/layui.js"></script>
<div class="main layui-clear">
<form action="/admin/login" method="post">
<div class="fly-panel fly-panel-user" pad20>
<div class="layui-tab layui-tab-brief">
<ul class="layui-tab-title">
<li class="layui-this">歡迎登入後臺系統</li>
</ul>
<div class="layui-form layui-tab-content" id="LAY_ucm" style="padding-top: 20px; padding-left: 50px; ">
<div class="layui-form layui-form-pane">
<div class="layui-form-item">
<label class="layui-form-label">使用者名稱</label>
<div class="layui-input-inline">
<input type="text" name="username" required lay-verify="username" placeholder="使用者名稱"
autocomplete="off" class="layui-input">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">密碼</label>
<div class="layui-input-inline">
<input type="password" name="password" required lay-verify="password"
placeholder="密碼" autocomplete="off" class="layui-input">
</div>
</div>
<div class="layui-form-item" style="float: right; margin-right: 42px;">
<input type="checkbox" name="is_top" {{if .post.IsTop}} checked {{end}} value="1"
title="記住密碼">
</div>
<div class="layui-form-item">
<button lay-submit class="layui-btn btn-submit" style="width: 300px; border-radius:3px"
lay-submit=""
lay-filter="sub">立即登入
</button>
</div>
</div>
</div>
</div>
</div>
</form>
</div>
</body>
<script>
//Demo
layui.use('form', function () {
});
</script>
</html>
這裡主要使用layui的模版,layui的學習門檻是極低的,關於layui的具體使用和特性可以去官網學習http://www.layui.com/doc/。
同樣在admin資料夾下新建main.tpl:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="Keywords" content="">
<meta name="Description" content="">
<title>後臺管理系統</title>
<link rel="stylesheet" href="/static/plug/layui/css/layui.css">
<link rel="shortcut icon" href="favicon.ico" type="image/x-icon">
</head>
<body>
<!-- 佈局容器 -->
<div class="layui-layout layui-layout-admin">
<!-- 頭部 -->
<div class="layui-header">
<div class="layui-main">
<!-- logo -->
<a href="/" style="color: #c2c2c2; font-size: 18px; line-height: 60px;">後臺管理系統</a>
<!-- 水平導航 -->
<ul class="layui-nav" style="position: absolute; top: 0; right: 0; background: none;">
<li class="layui-nav-item">
<a href="javascript:;">
</a>
</li>
<li class="layui-nav-item">
<a href="javascript:;">
admin,歡迎你!
</a>
<dl class="layui-nav-child">
<dd>
<a href="/admin/logout">
退出系統
</a>
</dd>
</dl>
</li>
</ul>
</div>
</div>
<!--側邊欄 -->
<div class="layui-side layui-bg-black">
<div class="layui-side-scroll">
<ul class="layui-nav layui-nav-tree " lay-filter="left-nav" style="border-radius: 0;">
</ul>
</div>
</div>
<!-- 主體 -->
<div class="layui-body">
<!-- 頂部切換卡 -->
<div class="layui-tab layui-tab-brief" lay-filter="top-tab" lay-allowClose="true" style="margin: 0;">
<ul class="layui-tab-title"></ul>
<div class="layui-tab-content"></div>
</div>
</div>
<!-- 底部 -->
<div class="layui-footer" style="text-align: center; line-height: 44px;">
Copyright ©無鞋
</div>
</div>
<script src="/static/plug/layui/lay/lib/jquery.js" type="text/javascript" charset="utf-8"></script>
<script type="text/javascript" src="/static/plug/layui/layui.js"></script>
<script type="text/javascript">
/**
* 對layui進行全域性配置
*/
layui.config({
base: '/static/js/'
});
layui.use('form', function() {
var $ = layui.jquery,
form = layui.form();
});
/**
* 初始化整個系統骨架
*/
layui.use(['cms'], function() {
var cms = layui.cms('left-nav', 'top-tab');
cms.addNav([
{ id: 1, pid: 0, node: '<span style=" font-size: 16px"><i class="layui-icon"></i> 系統管理</span>', url: '#' },
{ id: 7, pid: 1, node: ' 系統設定', url: '/admin/config.html' },
{ id: 2, pid: 0, node: '<span style=" font-size: 16px"><i class="layui-icon"></i> 內容管理</span>', url: '#' },
{ id: 3, pid: 2, node: ' 分類管理', url: '/admin/category.html' },
{ id: 5, pid: 2, node: ' 博文列表', url: '/admin/index.html' },
{ id: 6, pid: 2, node: ' 博文新增', url: '/admin/article.html' },
], 0, 'id', 'pid', 'node', 'url');
cms.bind(60 + 41 + 20 + 44); //頭部高度 + 頂部切換卡標題高度 + 頂部切換卡內容padding + 底部高度
cms.clickLI(1);
});
function addTab(title, src, id,closeId){
if(closeId){
// debugger;
closeTab(closeId);
}
layui.use(['cms'], function() {
var cms = layui.cms('left-nav', 'top-tab');
cms.addTab(title,src,id);
});
}
function closeTab(id,refreshId){
layui.use(['cms'], function() {
var cms = layui.cms('left-nav', 'top-tab');
cms.closeTab(id,refreshId);
});
}
</script>
</body>
</html>
進入blog目錄,執行bee run命令,訪問http://localhost:8088/admin/login
輸入admin 密碼123456登入成功:
先不管右邊主體的錯誤,後面我們會完善。
好了到這裡我們就搭建完了登入邏輯,這個流程是這樣的:
啟動專案後,初始化資料庫註冊orm的相關model,然後通過router.go來註冊路由,當我們訪問http://localhost:8088/admin/login會先到baseController的Prepare方法驗證是否已經登入(我們設定了session,如果已經登入可以直接訪問http://localhost:8088/admin/main.html進入後臺管理頁面,沒登陸成功或者session失效肯定是不行的),如果沒登入會進入login.html頁面,輸入帳號密碼通過自動繫結的路由自動跳轉到AdminController的Login方法,驗證帳號密碼的正確與否再去判斷邏輯
相關文章
- beego搭建個人部落格(二)Go
- 一個基於 beego 的,有情懷的部落格Go
- hexo搭建個人網站部落格完全教程Hexo網站
- 如何搭建個人獨立部落格網站?網站
- 搭建個人部落格
- 個人部落格搭建( wordpress )
- 基於mkdocs-material搭建個人靜態部落格
- 個人搭建部落格的幾種方法和方案
- 從零開始搭建一個 hexo 部落格。Hexo
- 個人的小部落格
- 使用 hexo 搭建個人部落格Hexo
- Django搭建個人部落格:前言Django
- hexo搭建個人部落格心得Hexo
- 使用React搭建個人部落格React
- Django搭建個人部落格(二)Django
- beego 開發的部落格 go-blogGo
- 【個人部落格搭建及配置一】基礎配置
- 使用WordPress搭建一個專屬自己的部落格
- 手把手教你用Hexo搭建個人技術部落格Hexo
- Django搭建個人部落格:編寫部落格文章的Model模型Django模型
- hexo+github搭建個人部落格HexoGithub
- MkDocs+Github搭建個人部落格Github
- 使用 Hugo 快速搭建個人部落格Go
- 基於 GitBook 搭建個人部落格Git
- 我的個人部落格搭建之旅
- WordPress 搭建個人部落格/站點
- Hexo+Gitee搭建個人部落格HexoGitee
- 【部落格搭建】Typecho個人部落格搭建,快速安裝,超小白(很簡單的)
- 使用go搭建一個簡易的部落格系統Go
- 如何用虛擬主機搭建一個部落格/blog?
- 使用 github 和 Deno Deploy 搭建一個部落格網站Github網站
- 第一個部落格
- 分享一個部落格
- 用原生Go寫一個自己的部落格-搭建專案(一)Go
- 寶塔皮膚搭建wordpress個人技術部落格(圖文教程)
- 個人靜態部落格上線
- 部落格,休閒個人站點
- Hexo + Github 搭建靜態部落格(一)HexoGithub