使用Golang 搭建http web服务器
转自:http://www.cnblogs.com/yjf512/archive/2012/09/03/2668384.html Golang在搭建web服务器方面的能力是毋庸置疑的。官方已经有提供net/http包为搭建http服务器做准备。使用这个包能很简单地对web的路由,静态文件,模版,cookie等数据进行设置。至于这个包是否好用,这个就见仁见智了。你可以从net包开始封装一个web框架,当然也可以基于http包封装一个web框架。但是不论你是打算怎么样做,了解基本的net/http包一定是你借鉴的基础。 需求我们要做两个简单的后台web系统。这个系统简单到只有两个页面:登陆和首页。 1 登陆页面
登陆页面需要提交用户名和密码,将用户名和密码和mysql数据库中的用户名密码比对达到验证的效果。mysql数据库的go语言驱动推荐使用mymysql(https://github.com/ziutek/mymysql)。 当用户名和密码正确的时候,需要在cookie中种下用户名和加密后的密钥来进行cookie认证。我们不对cookie设置ExpireTime,这样这个cookie的有效期就是浏览器打开到浏览器关闭的session期间。 另外,这个页面还需要加载一个js。提交用户名和密码的是由js进行ajax post命令进行查询的。 这个页面需要加载css,进行页面排版
2 首页首页是非常简单,但它是一个动态页面。 首先右上角的”欢迎登陆, 管理员:yejianfeng“。这里的用户名yejianfeng是根据不同的用户会进行变化的。这里需要用到模版,我们又会用到了一个模版包html/template。这个包的作用就是加载模版。 其次这个页面也需要的是css,js(退出系统的删除cookie操作由js控制) 路由分析下访问路径,会有几个文件: /admin/index -- 首页/login/index --登陆页显示/ajax/login -- 登陆的ajax动作/css/main.css -- 获取main的css文件/js/login.js -- 获取登陆的js文件在net/http包中,动态文件的路由和静态文件的路由是分开的,动态文件使用http.HandleFunc进行设置,静态文件就需要使用到http.FileServer
这里的http.FileServer(http.Dir("template"))的路径是怎么算的要注意下了。相对路径都是从当前执行路径路径下开始算的,这里设置的路径树是这样: 关于http.HandleFunc如果不理解请参考我的上一篇文章 http://www.cnblogs.com/yjf512/archive/2012/08/22/2650873.html
处理器这里需要定制4个handler对应相应的一级路径。我们将这些个handler都放入到route.go文件中 页面404处理器main中的逻辑是当/admin/ /login/ /ajax/都不符合路径的时候就进入404页面处理器NotFoundHandler |
func NotFoundHandler(w http.ResponseWriter,r *http.Request) {
if
r.URL.Path ==
{
http.Redirect(w,r,
"/login/index"
t,err := template.ParseFiles(
"template/html/404.html"
)
(err != nil) {
log.Println(err)
}
t.Execute(w,nil)
这段逻辑是很清晰的:如果路径是"/" 即访问路径是http://192.168.100.166:8888/的时候,访问会跳转到登陆页面,否则当访问路径不满足制定的路由,读取404模版,显示404。
|
func loginHandler(w http.ResponseWriter,monospace!important; font-size:12px!important; min-height:inherit!important; white-space:pre-wrap">pathInfo := strings.Trim(r.URL.Path,monospace!important; font-size:12px!important; min-height:inherit!important; white-space:pre-wrap">)
parts := strings.Split(pathInfo,monospace!important; font-size:12px!important; min-height:inherit!important; white-space:pre-wrap">)
var action =
""
len(parts) > 1 {
action = strings.Title(parts[1]) +
"Action"
}
login := &loginController{}
controller := reflect.ValueOf(login)
method := controller.MethodByName(action)
!method.IsValid() {
method = controller.MethodByName(strings.Title(
"index"
) +
"Action"
)
}
requestValue := reflect.ValueOf(r)
responseValue := reflect.ValueOf(w)
method.Call([]reflect.Value{responseValue,requestValue})
根据MVC思想,对具体的逻辑内容使用不同的Controller,这里定义了一个loginController,使用reflect将pathInfo映射成为controller中的方法。
|
"github.com/ziutek/mymysql/autorc"
_
"github.com/ziutek/mymysql/thrsafe"
"encoding/json"
)
type Result
{
Ret
int
Reason
string
Data
interface
{}
type ajaxController
{
}
*ajacController)LoginAction(w http.ResponseWriter,r *http.Request) {
w.Header().Set(
"content-type"
"application/json"
)
err := r.ParseForm()
err != nil {
OutputJson(w,monospace!important; font-size:12px!important; min-height:inherit!important; white-space:pre-wrap; color:blue!important">"参数错误"
}
admin_name := r.FormValue(
"admin_name"
)
admin_password := r.FormValue(
"admin_password"
)
admin_name ==
""
|| admin_password ==
{
return
}
db := mysql.New(
"tcp"
"192.168.199.128"
"root"
"test"
"webdemo"
)
err := db.Connect(); err != nil {
"数据库操作失败"
}
defer db.Close()
rows,res,err := db.Query(
"select * from webdemo_admin where admin_name = '%s'"
err != nil {
return
}
name := res.Map(
)
admin_password_db := rows[0].Str(name)
admin_password_db != admin_password {
"密码输入错误"
return
}
// 存入cookie,使用cookie存储
expiration := time.Unix(1,0)
cookie := http.Cookie{Name:
)),Path:
}
http.SetCookie(w,&cookie)
"操作成功"
}
func OutputJson(w http.ResponseWriter,ret
int
string
{}) {
out
:= &Result{ret,reason,i}
b,err := json.Marshal(
)
err != nil {
return
}
w.Write(b)
这段代码有几个地方可以看看:
|
func adminHandler(w http.ResponseWriter,0)!important">// 获取cookie
cookie,err := r.Cookie(
err != nil || cookie.Value ==
{
}
)
admin := &adminController{}
controller := reflect.ValueOf(admin)
method := controller.MethodByName(action)
!method.IsValid() {
)
}
requestValue := reflect.ValueOf(r)
responseValue := reflect.ValueOf(w)
userValue := reflect.ValueOf(cookie.Value)
其他的部分都是一样的了。
|
type User
{
UserName
string
}
type adminController
{
*adminController)IndexAction(w http.ResponseWriter,r *http.Request,user
) {
"template/html/admin/index.html"
(err != nil) {
log.Println(err)
}
这里就将user传递出去给admin/index模版
|