技能学习:学习使用golang(gin框架) + vue.js,开发前端全栈网站-5.跨域并跨域传输数据 - Go语言中文社区

技能学习:学习使用golang(gin框架) + vue.js,开发前端全栈网站-5.跨域并跨域传输数据


技能学习:学习使用golang(gin框架) + vue.js,开发前端全栈网站-5.跨域并跨域传输数据

相关文章:
技能学习:学习使用golang(gin框架) + vue.js,开发前端全栈网站-1.工具和本地环境
技能学习:学习使用golang(gin框架) + vue.js,开发前端全栈网站-2.启动项目
技能学习:学习使用golang(gin框架) + vue.js,开发前端全栈网站-3.接收json数据
技能学习:学习使用golang(gin框架) + vue.js,开发前端全栈网站-4.连接mongodb数据库
技能学习:学习使用golang(gin框架) + vue.js,开发前端全栈网站-5.跨域并跨域传输数据
技能学习:学习使用golang(gin框架) + vue.js,开发前端全栈网站-6.GO语言做通用CRUD接口-1
技能学习:学习使用golang(gin框架) + vue.js,开发前端全栈网站-7.GO语言做通用CRUD接口-2
技能学习:学习使用golang(gin框架) + vue.js,开发前端全栈网站-8.模型的关联——无限层级分类
技能学习:学习使用golang(gin框架) + vue.js,开发前端全栈网站-9.管理员及登录注册功能的实现
技能学习:学习使用golang(gin框架) + vue.js,开发前端全栈网站-10.生产环境编译

跨域指的是浏览器不能执行其他网站或域名下的脚本。之所以形成跨域,是因为浏览器的同源策略造成的,是浏览器对javascript程序做的安全限制,现在所有支持JavaScript 的浏览器都会使用这个策略。
在本次项目就用到前后端分离,前后端不在同域(这里的同域指的是同一协议,同一域名,同一端口),那么,它们之间相互通信如何解决呢?

1.制作admin端

首先将前端内容做出。
大家对npm和vue不熟悉的话可以参考我之前的文章

技能学习:学习使用Node.js +
Vue.js,开发前端全栈网站-2.启动项目

技能学习:学习使用Node.js +
Vue.js,开发前端全栈网站-3.element-ui和路由的安装和使用

里面介绍了相关启动项目的包和element前端样式框架等。
我完全按这两篇文章进行admin端制作,本篇文章我就不做演示了。最终效果:
在这里插入图片描述
到此,我们已经知道如何使用vue搭建页面,下面改动我们做好的页面:
(1)制作新建分类页面CategorySet.vue:

<template>
    <div>
        <h1>创建分类</h1>
        <el-form label-width="80px" style="margin-top:20px;" @submit.native.prevent="save">
            <!-- submit事件中使用提交方法save,native是找到js原生表单,prevent是指阻止提交时默认跳转页面 -->
            <el-form-item label="分类名">
                <el-input v-model="model.name"></el-input>
                <!-- 双向绑定model -->
            </el-form-item>
            <el-form-item>
                <el-button type="primary" native-type="submit">保存</el-button>
            </el-form-item>
        </el-form>
    </div>
</template>
<script>
export default {
    data(){
        return {
            model: {}
        }
    },
    methods: {
        save(){
            //这里放axios方法,用来提交数据
        }
    }
}
</script>

在这里插入图片描述
(2)引入新建分类页面:
在这里插入图片描述
(3)将新建分类页面的路由设置在左侧导航栏:
在这里插入图片描述
此时创建分类页面就可以显示,可以当作表单进行上传功能使用。
在这里插入图片描述

2.安装axios并使用,在admin端编写提交方法

终端安装axios:

cd admin 
npm i axios

在这里插入图片描述
此时安装axios完成。
为了代码的清晰,避免main.js混乱,专门在main.js同级给axios创建一个js文件存放axios的接口,名为http.js,后在main.js引入。
引入axios包,同时创建一个axios实例,发送地址为服务器端server的admin/api接口下,此处直译为admin后台的api接口,稍后在服务端创建此地址。
http.js:

// 引入axios
import axios from 'axios'

// 创建axios实例,添加api路径
const http = axios.create({
    baseURL:'http://localhost:3000/admin'
})

// 将文件变量导出,导出到main.js
export default http

在这里插入图片描述
main.js:
在这里插入图片描述
此时http实例(也就是axios实例)已经创建好,并已放入vue实例中,在我们调用后端接口时只要使用this.$http(或Vue.$http)就可使用axios。
此时,回到CategorySet.vue页面,使用POST方法写提交数据的方法:
在这里插入图片描述
之前我们已经在server端创建好接口,先进行下测试:
(1)补全接口,使用异步请求

// 使用async..await异步请求方法
async save(){
   // 这里放axios方法,用来提交数据

    // 接口调用之前写好的后台find_all查询接口进行测试接口连接
    const res = await this.$http.post('/find_all')
    console.log(res)
}

在这里插入图片描述
(2)本地开启后台服务:
在这里插入图片描述
本地环境中需要开启server端项目,才可进行访问。
可以看到server端的find_all接口,但是我们发现之前定义的路由地址是http://localhost:3000/mongo/find_all,所以需要改一下现在的axios实例:
在这里插入图片描述
(2)点击保存按钮进行接口的调用:
在这里插入图片描述
请求报错,CORS error。
跨域问题,做了这么多,终于到了本篇文章的重点,跨域操作。

3.跨域

跨域操作,简单来说就是设置接口的请求头:

func(c *gin.Context) {
	method := c.Request.Method
	
	c.Header("Access-Control-Allow-Origin", "*") // 允许访问所有域,可以换成具体url,注意仅具体url才能带cookie信息
	c.Header("Access-Control-Allow-Headers", "Content-Type,AccessToken,X-CSRF-Token, Authorization, Token") //header的类型
	c.Header("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE") //允许请求方法
	c.Header("Access-Control-Expose-Headers", "Content-Length, Access-Control-Allow-Origin, Access-Control-Allow-Headers, Content-Type") //返回数据格式
	c.Header("Access-Control-Allow-Credentials", "true") //设置为true,允许ajax异步请求带cookie信息
	
	//放行所有OPTIONS方法
	if method == "OPTIONS" {
		c.AbortWithStatus(http.StatusNoContent)
	}
}

如何在go接口路由中使用请求头呢?先将整页代码贴出:

package db

import(
	"github.com/gin-gonic/gin"
	"gopkg.in/mgo.v2"
	"gopkg.in/mgo.v2/bson"
	"net/http"
)

// 定义结构
type user struct{
	Username string `json:"username"`
	Password string `json:"password"`
}

// 插入数据
func insert(ctx *gin.Context){
	// 连接mongodb服务
	url := "mongodb://127.0.0.1"
	// 设置数据库一致性模式
	// 连接数据库操作,该操作赋值给session
	// err值必写,用于错误处理
	session, err := mgo.Dial(url)
	// 后边程序执行的err与go程序比对,若有错误则返回错误内容
	if err != nil { 
		panic(err) 
	}else{
		// 若没有错误,则在页面返回字符串,显示插入成功
		ctx.String(http.StatusOK, "插入成功")
	}
	// defer用法大家自行百度,我解释不清
	defer session.Close()

	// 设置数据库一致性模式,就当作打开数据库
	session.SetMode(mgo.Monotonic, true)
	// 找到某数据库下的某数据表
	c := session.DB("db_go").C("user")

	// 将insert状态传值给err
	err = c.Insert(&user{"admin", "123456"},&user{"Johnson", "Johnson"})
}

// 查询数据
func find(ctx *gin.Context){
	url := "mongodb://127.0.0.1"
	session, err := mgo.Dial(url)
	if err != nil { 
		panic(err) 
	}
	defer session.Close()

	session.SetMode(mgo.Monotonic, true)
	c := session.DB("db_go").C("user")

	// 定义查询结构,根据上方定义的结构查询usr
	usr := user{}
	// 查找数据
	err = c.Find(bson.M{"username": "Johnson"}).One(&usr)
	ctx.JSON(http.StatusOK, usr)
}

// 查询全部数据
func findAll(ctx *gin.Context){
	url := "mongodb://127.0.0.1"
	session, err := mgo.Dial(url)
	if err != nil { 
		panic(err) 
	}
	defer session.Close()

	session.SetMode(mgo.Monotonic, true)
	c := session.DB("db_go").C("user")
	
	// 查找全部
	usrs := make([]user, 10)
	// 查找全部
	err = c.Find(nil).All(&usrs)
	ctx.JSON(http.StatusOK, usrs)
}

// 删除数据
func delete(ctx *gin.Context){
	url := "mongodb://127.0.0.1"
	session, err := mgo.Dial(url)
	if err != nil { 
		panic(err) 
	}else{
		ctx.String(http.StatusOK, "删除成功")
	}
	defer session.Close()

	session.SetMode(mgo.Monotonic, true)
	c := session.DB("db_go").C("user")
	
	err = c.Remove(bson.M{"username": "Johnson"})
	
}

// 修改数据
func update(ctx *gin.Context){
	url := "mongodb://127.0.0.1"
	session, err := mgo.Dial(url)
	if err != nil { 
		panic(err) 
	}else{
		ctx.String(http.StatusOK, "修改成功")
	}
	defer session.Close()

	session.SetMode(mgo.Monotonic, true)
	c := session.DB("db_go").C("user")
	
	err = c.Update(bson.M{"username": "Johnson"},bson.M{"$set": bson.M{"password": "123456"}})
	
}

// 处理跨域请求,将跨域请求函数作为中间件处理
func Cors() gin.HandlerFunc {
	return func(c *gin.Context) {
		method := c.Request.Method
 
		c.Header("Access-Control-Allow-Origin", "*") // 允许访问所有域,可以换成具体url,注意仅具体url才能带cookie信息
		c.Header("Access-Control-Allow-Headers", "Content-Type,AccessToken,X-CSRF-Token, Authorization, Token") //header的类型
		c.Header("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE") //允许请求方法
		c.Header("Access-Control-Expose-Headers", "Content-Length, Access-Control-Allow-Origin, Access-Control-Allow-Headers, Content-Type") //返回数据格式
		c.Header("Access-Control-Allow-Credentials", "true") //设置为true,允许ajax异步请求带cookie信息
 
		//放行所有OPTIONS方法
		if method == "OPTIONS" {
			c.AbortWithStatus(http.StatusNoContent)
		}
		// 处理请求
		c.Next()
	}
}

// 配置路由
func Main(e *gin.Engine)  {
	// 全局使用中间件
	e.Use(Cors())
	// 定义路由,调用接口函数
	e.GET("/mongo/insert", insert)
	// 定义json函数接口
	e.GET("/mongo/find", find)
	// 定义json结构体函数接口
	e.POST("/mongo/find_all", findAll)
	// 定义json结构体函数接口
	e.GET("/mongo/delete", delete)
	// 定义json结构体函数接口
	e.GET("/mongo/update", update)
	// 将路由信息return回调
	// return r
}

在这里插入图片描述
昨晚跨域工作后,由于我们传输方法用的是post(),所以后端路由接口也要改为POST方法:
在这里插入图片描述
此时,跨域操作已完成,重新编译执行server端:
在这里插入图片描述
在admin端测试接口:
在这里插入图片描述
接口调用成功,点击查看调用的数据:
在这里插入图片描述
成功查询成功。同时我们console的res也成功查询出来了:
在这里插入图片描述

4.重新编译插入接口,并接收admin端传值

(1)admin端修改调用接口的方法:

async save(){
            // 这里放axios方法,用来提交数据

            // 接口调用之前写好的后台insert插入接口进行测试接口连接
            // 并传值
            const res = await this.$http.post('/insert', this.model)
            console.log(res)

            // 提示信息,使用vue中自带的$message实例
            this.$message({
                type: 'success',
                message: '保存成功'
            })
        }

在这里插入图片描述
此时如果点击保存按钮就会带值传输到后端。
(2)修改server端插入数据接口:

// 插入数据
func insert(ctx *gin.Context){
	// 连接mongodb服务
	url := "mongodb://127.0.0.1"
	// 设置数据库一致性模式
	// 连接数据库操作,该操作赋值给session
	// err值必写,用于错误处理
	session, err := mgo.Dial(url)
	// 后边程序执行的err与go程序比对,若有错误则返回错误内容
	if err != nil { 
		panic(err) 
	}else{
		// 若没有错误,则在页面返回字符串,显示插入成功
		ctx.String(http.StatusOK, "插入成功")
	}
	// defer用法大家自行百度,我解释不清
	defer session.Close()

	// 设置数据库一致性模式,就当作打开数据库
	session.SetMode(mgo.Monotonic, true)
	// 找到某数据库下的某数据表
	c := session.DB("db_go").C("user")

	// 接收传值,将传值添加到上方定义的数据表结构中
	var form user 
	// 如果传值格式不符合上方定义的结构,则返回错误信息
	if err := ctx.Bind(&form); err != nil {
		ctx.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}
	// 此时&form就继承了上方定义的结构格式
	// 插入数据,并将insert状态传值给err
	err = c.Insert(&form)
}

在这里插入图片描述
(3)将之前定义的接口路由改为POST方法:
在这里插入图片描述
编译测试,重启server端:
在这里插入图片描述
在admin端页面输入信息,并点击按钮:
在这里插入图片描述
数据的传值与接收没什么问题,虽然过程成功,但是我目前有一个很大的错误:
在这里插入图片描述
所以我们需要查询一下这个表的所有数据,看到底有没有成功插入词条数据。

5.Postman调用接口

由于我们的接口方法改成了POST传输,所以在网页中已经无法调用这个接口了:
在这里插入图片描述
所以我们需要使用第三方测试工具Postman,进行调用接口查询。
(1)下载安装Postman
下载地址:https://www.postman.com/downloads/
下载好双击安装即可。
(2)使用Postman
使用前需要先登录,登录完成到此界面:
在这里插入图片描述
新建项目:
在这里插入图片描述
选择HTTP Request:
在这里插入图片描述
选择请求方式,并输入路由地址:
在这里插入图片描述
点击Send后查询到数据:
在这里插入图片描述
果然,跟我想的一样,并没有传入成功。看来之前的错误审核操作只能返回接口的调用状态,并不能检查出结构和名字的错误:
在这里插入图片描述

5.定义新的数据库接口路由

我们根据CategorySet新建分类功能,新建一个数据结构,并新建插入数据接口函数。
(1)新定义结构:
在这里插入图片描述
(2)新定义插入数据接口函数:
在这里插入图片描述
(3)添加新的插入接口:
在这里插入图片描述
路由的定义与真实路径无关,只要访问到该路径即可调用接口函数。
(4)server端编译执行测试:
在这里插入图片描述
(5)前端传输数据路由改成对应路径:
在这里插入图片描述
前端页面进行测试:
在这里插入图片描述
显示成功,我们需要查询是否成功。
(6)由于我们将数据插入到了新的表category中,所以我们同样需要制作category表的查询接口函数:
在这里插入图片描述
同时下方引入接口路由:
在这里插入图片描述
重新编译运行:
在这里插入图片描述
此时,使用Postman访问路由地址进行查询:
在这里插入图片描述
可以,没问题,很牛*。

6.结语

到此,跨域和跨域传输数据,也就是前后端分离的数据传输就完成了,这也是一个动态网站功能进行完善的基础与雏形。
(1)本篇文章到这里,我们还是继承了上篇文章的问题,我们目前每需要调用一个接口,就需要新建一个接口函数,太烦了,太惨了。
所以下篇文章我们一起研究CRUD通用接口,让所有数据表只使用固定的几个增删改查接口。
(2)在CRUD接口完成后,我们再继续完善查找、删除、修改数据的接口(否则我们得多写好几个函数接口,写的越多大家学习过程就越乱)。

更多设计、功能的学习经验,大家也可以去我的公众号查看!

————
在这里插入图片描述

版权声明:本文来源CSDN,感谢博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.csdn.net/m0_51592186/article/details/118991918
站方申明:本站部分内容来自社区用户分享,若涉及侵权,请联系站方删除。

0 条评论

请先 登录 后评论

官方社群

GO教程

猜你喜欢