文章目录
本文分为:前端、后端两部分讲诉。以下是前端发送请求到服务器,服务器响应前端,的整个过程的图解:
前端主要是发起请求,本文使用自定义的axios请求方法,分为注册页面模块、axios 请求方法模块两部分。
前端运行地址: http://localhost:8080/
该页面主要是通过点击提交按钮,触发点击事件,发起注册请求。
目标端口是:http://localhost:3000/api/login,协议、域名、端口号之中,存在端口号与前端运行地址不一样,满足跨域请求的条件。后端部分会讲到:如何解决跨域问题。
<el-button type="primary" @click="submitForm('loginForm')">提交</el-button>
点击提交,触发并传递给submitForm方法参数loginForm。其中,loginForm数据形式是
loginForm:{
username:"",
pass:"",
}
第 7 行,submitForm发起请求,调用自定义的axios方法:api.login(){}
import api from "@/api"
submitForm(formName) {
this.$refs[formName].validate((valid)=> {
if(valid){
if(this.currentIndex==='login'){
api.login(this.loginForm).then(res=>{
// 用户登陆成功
if(res.data.status === 200){
//用户信息存储到 vuex 和 localstorage
this.setUser(res.data)
localStorage.setItem('hp',JSON.stringify(res.data))
this.$notify({
title: '登录成功',
type: 'success'
});
// 用户登陆成功跳转到home页面
this.$router.push('/')
}else{
this.$notify.error({
title: '登录失败',
message: '请重新登录'
});
}
})
}
if(this.currentIndex==='register'){
api.register(this.registerForm).then(res =>{
console.log(res)
if(res.data.status === 200){
this.$notify({
title: '注册成功',
type: 'success'
});
}
})
}
}else{
return ;
}
})
}
为了请求方法的应用性更强,选择自定义请求的方式编写封装请求。
考虑到模块开发、代码可读性的好处,将请求方法封装模块分为路径配置、自定义 axios、API封装三部分。
每次请求都使用以下预定义的路径,该文件向外导出base对象
const base = {
baseUrl: "http://localhost:3000",
register: "/api/register",//用户的接口
login: "/api/login",
selectTbItemAllByPage: '/api/backend/item/selectTbItemAllByPage',//商品列表请求路径
total: "/api/total",//商品总条数
search: "/api/search" //商品 模糊查询
}
export default base
自定义axios 易用、简洁且高效的http库,对发起的axios请求和响应进行拦截
// /api/utils/request.js 文件
import axios from "axios
// 引入qs模块,用来序列化post类型的数据
import qs from 'qs'
import router from "@/router"
//主要步骤:三步
// 1.创建一个axios实例
// 2.拦截器--请求拦截
// 3.拦截器--响应拦截
// 1.创建一个axios实例
const instance = axios.create({
timeout: 5000, //超时处理,超过时间告诉用户超时
// baseURL: "http://localhost:3000",
})
instance.all = axios.all;
instance.spread = axios.spread
// 设置post的请求头
instance.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';
// interceptors 拦截器
// 2.请求拦截 做一个逻辑后再把请求发送,可以用于配置公用的逻辑,就不用每个请求都配一遍。
instance.interceptors.request.use(
// 请求拦截配置
// 拦截成功,返回非promise实例对象config
config => {
if (config.method === 'post') {
config.data = qs.stringify(config.data);
}
return config;
// 判断token是否存在,存在就添加到请求头上
// const token = store.state.loginModule.user.token;
// if(token){
// config.headers.authorization = store.state.loginModule.user.token;
// }
},
// 拦截失败时,返回promise
error => Promise.reject(error)
)
const toLogin = () => {
router.push("/login")
}
// errorHandle打印失败状态码对应的 描述和路由去向
const errorHandle = (status, info) => {
switch (status) {
case 400:
console.log("服务器收到客户端通过PUT或者POST请求提交的表示,表示的格式正确,但服务器不懂它什么意思");
toLogin();
break;
case 401:
console.log("客户端试图对一个受保护的资源进行操作,却又没有提供正确的认证证书");
toLogin();
break;
case 403:
console.log("客户端请求的结构正确,但是服务器不想处理它");
toLogin();
break;
case 404:
console.log("资源被围定义(网络请求地址错误)");
break;
case 500:
console.log("执行请求处理代码时遇到了异常,它们就发送此响应代码");
break;
case 503:
console.log("最可能的原因是资源不足:服务器突然收到太多请求,以至于无法全部处理");
break;
default:
console.log(info);
break;
}
}
// 3.interceptors拦截器配置response响应拦截
instance.interceptors.response.use(
// 成功时
response => response.status === 200 ? Promise.resolve(response) : Promise.reject(response),
// 失败时
error => {
const { response } = error;
if (response) {
errorHandle(response.status, response.data);
return Promise.reject(response);
} else {
console.log("请求被中断");
}
}
)
// 封装get请求
export function get(url, params) {
return new Promise((resolve, reject) => {
instance.get(url, params).then(res => {
//请求回调成功
console.log('封装这里,', params)
resolve(res.data);
}).catch(err => {
reject(err.data);
})
})
}
// 封装post请求
export function post(url, params) {
return new Promise((resolve, reject) => {
instance.post(url, params).then(res => {
//请求回调成功
resolve(res.data)
}).catch(err => {
reject(err.data)
})
})
}
export default instance
// api/index.js 文件
// 入口文件
// 导入自定义ajax封装库axios: myaxios
import myaxios from "@/api/utils/request"
// 导入自定义路径配置,模块化开发 简化url
import base from "./base"
// 定义前端的发送请求方法
const api = {
// 注册请求
register(params) {
// 调用自定义asiox(myaxios)封装的post方法
return myaxios.post(base.baseUrl + base.register, params)
}
}
}
// 定义的请求方法全部导出
export default api;
本文采用:node.js + express+MySQL,创建web 服务器,构建后端。后端编写分为服务器模块、接口模块、连接数据库模块三部分,都是server文件夹下的 js 文件。
后端运行地址:http://127.0.0.1:3000/
因此,需要完成获取数据请求必须解决跨域问题,跨域问题可以在前端或者后端解决。本文采取后端解决,使用 CORS。同源安全策略 默认阻止“跨域”获取资源。但是 CORS 给了 web 服务器这样的权限,即服务器可以选择,允许跨域请求访问到它们的资源。
//接口服务器 server/index.js文件
// 1.导入express
const express = require("express")
//跨域请求处理 后台处理
const cors = require("cors")
//post传参问题
const bodyParser = require("body-parser")
// 导入自定义路由
const router = require("./router")
// 2.创建web服务器
const app = express()
// 注册中间件
app.use(cors());
// app.use(express.json());
app.use(bodyParser.urlencoded({ extended: false }))
//路由访问前缀
app.use('/api', router)
// 3.启动服务器
app.listen(3000, () => {
console.log('express server running at http://127.0.0.1')
})
其中,web服务器服务器对象 app,通过导入接口方法模块,并使用app.use('/api', router)实现接口方法应用。
注册的步骤:主要是实现服务器获取请求体的数据,然后将数据插入数据库,最后给客户端响应。
// server/router.js文件
// 设置路由,定义对应post,URL的处理函数
const express = require("express")
// 创建路由对象
const router = express.Router();
//导入数据库配置对象
const sqlClient = require('./dbconfig')
//导入JWT生成token
const JWT = require("jsonwebtoken")
//导入JWT解密
const expressJWT = require("express-jwt")
// 请求post和url=localhost:3000/api/register 的注册路由
const url = require("url");
const { send } = require("process");
router.post("/register", (req, res) => {
//接收请求对象携带的数据
const { username, pass, email } = req.body;
//sqlClient实现连接数据库,并将用户数据插入数据库 并回调函数响应数据
sqlClient("insert into user values(null,?,?,?)", [username, pass, email], result => {
//插入成功 并响应对象数据给客户端
if (result.affectedRows > 0) {
res.send({
status: 200,
msg: "注册成功"
})
} else {
res.send({
statu: 401,
msg: "注册失败"
})
}
})
})
只需要导入mysql库,即可以实现数据库连接,并向外导出操作数据库的方法对象,该函数返回一个操作结果。
// server/dbconfig.js文件
const mysql = require("mysql")
//定义连接对象
const client = mysql.createConnection({
host: "localhost",
user: "root",
password: "root",
database: "vue_mall"
})
//定义操作数据库的方法,参数为sql语句,数组数据,回调函数
const sqlClient = (sql, arr, callback) => {
client.query(sql, arr, (error, result) => {
if (error) {
//发生错误,返回错误信息
console.log(error)
return
}
//成功,则调用回调函数返回操作的结果
callback(result)
})
}
module.exports = sqlClient
使用 mysql 对象的createConnection方法创建连接数据库对象 client,然后 定义一个sqlClient对象,其中 sqlClient 需要参数sql语句,数组数据,便会调用回调函数,并返回sql语句和数据操作数据库的结果。
在我的Controller中,我通过以下方式在我的index方法中支持HTML和JSON:respond_todo|format|format.htmlformat.json{renderjson:@user}end在浏览器中拉起它时,它会自然地以HTML呈现。但是,当我对/user资源进行内容类型为application/json的curl调用时(因为它是索引方法),我仍然将HTML作为响应。如何获取JSON作为响应?我还需要说明什么? 最佳答案 您应该将.json附加到请求的url,提供的格式在routes.rb的路径中定义。这
我是Google云的新手,我正在尝试对其进行首次部署。我的第一个部署是RubyonRails项目。我基本上是在关注thisguideinthegoogleclouddocumentation.唯一的区别是我使用的是我自己的项目,而不是他们提供的“helloworld”项目。这是我的app.yaml文件runtime:customvm:trueentrypoint:bundleexecrackup-p8080-Eproductionconfig.ruresources:cpu:0.5memory_gb:1.3disk_size_gb:10当我转到我的项目目录并运行gcloudprevie
rails中是否有任何规定允许站点的所有AJAXPOST请求在没有authenticity_token的情况下通过?我有一个调用Controller方法的JqueryPOSTajax调用,但我没有在其中放置任何真实性代码,但调用成功。我的ApplicationController确实有'request_forgery_protection'并且我已经改变了config.action_controller.consider_all_requests_local在我的environments/development.rb中为false我还搜索了我的代码以确保我没有重载ajaxSend来发送
在我做的一些网络开发中,我有多个操作开始,比如对外部API的GET请求,我希望它们同时开始,因为一个不依赖另一个的结果。我希望事情能够在后台运行。我找到了concurrent-rubylibrary这似乎运作良好。通过将其混合到您创建的类中,该类的方法具有在后台线程上运行的异步版本。这导致我编写如下代码,其中FirstAsyncWorker和SecondAsyncWorker是我编写的类,我在其中混合了Concurrent::Async模块,并编写了一个名为“work”的方法来发送HTTP请求:defindexop1_result=FirstAsyncWorker.new.async.
我是Ruby的新手。我试过查看在线文档,但没有找到任何有效的方法。我想在以下HTTP请求botget_response()和get()中包含一个用户代理。有人可以指出我正确的方向吗?#PreliminarycheckthatProggitisupcheck=Net::HTTP.get_response(URI.parse(proggit_url))ifcheck.code!="200"puts"ErrorcontactingProggit"returnend#Attempttogetthejsonresponse=Net::HTTP.get(URI.parse(proggit_url)
在我的路线文件中我有:match'graphs/(:id(/:action))'=>'graphs#(:action)'如果是GET请求(工作)或POST请求(不工作),我想匹配它我知道我可以使用以下方法在资源中声明POST请求:post'/'=>:show,:on=>:member但是我怎样才能为比赛做到这一点呢?谢谢。 最佳答案 如果你同时想要POST和GETmatch'graphs/(:id(/:action))'=>'graphs#(:action)',:via=>[:get,:post]编辑默认值可以设置如下match'g
我正在使用Rails3.2.2并希望递归加载某个目录中的所有代码。例如:[Railsroot]/lib/my_lib/my_lib.rb[Railsroot]/lib/my_lib/subdir/support_file_00.rb[Railsroot]/lib/my_lib/subdir/support_file_01.rb...基于谷歌搜索,我试过:config.autoload_paths+=["#{Rails.root.to_s}/lib/my_lib/**"]config.autoload_paths+=["#{Rails.root.to_s}/lib/my_lib/**/"
我试图像这样在我的测试用例中执行获取:request.env['CONTENT_TYPE']='application/json'get:index,:application_name=>"Heka"虽然,它失败了:ActionView::MissingTemplate:Missingtemplatealarm_events/indexwith{:handlers=>[:builder,:haml,:erb,:rjs,:rhtml,:rxml],:locale=>[:en,:en],:formats=>[:html]尽管在我的Controller中我有:respond_to:html,
我已经开始学习Ruby,我已经阅读了一些教程,甚至还买了一本书(“ProgrammingRuby1.9-ThePragmaticProgrammers'Guide”),我遇到了一些以前从未见过的新东西使用我知道的任何其他语言(我是一名PHP网络开发人员)。block和过程。我想我明白它们是什么,但我不明白的是为什么它们如此伟大,以及我应该在何时何地使用它们。我到处都看到他们说block和过程是Ruby中的一个很棒的特性,但我不理解它们。这里有人能给像我这样的Ruby新手一些解释吗? 最佳答案 block有很多好处。电梯演讲:bloc
如果使用rspec请求花费的时间太长,我该如何测试行为?我正在考虑使用线程来模拟这个:describe"Test"doit"shouldtimeoutiftherequesttakestoolong"dolambda{thread1=Thread.new{#net::httprequesttogoogle.com}thread2=Thread.new{sleep(xxseconds)}thread1.jointhread2.join}.shouldraise_errorendend我想确保在第一次发出请求后,另一个线程“启动”,在这种情况下只是休眠xx秒。然后我应该期望请求超时,因为执