目录
一、 跨域
1. 什么是跨域?
2. 什么是本域?
3. 浏览器请求的三种报错
二、SpringBoot解决跨域问题+其他前后端跨域请求解决方案
1. SpringBoot上直接添加@CrossOrigin
2.处理跨域请求的Configuration
3. 采用过滤器的方式
3.1 方式一
3.2 方式二
4. 其他解决方案—NGINX反向代理
三、VUE的前后端交互
1. 前后端交互模式
1.1传统的交互方式
1.2传统的URL
1.3RESTFUL风格的URL
2. Promise相关概念与使用
2.1 promise使用的优势
2.2 promise的基本用法
2.3 then参数的函数返回值
2.4 Promise常用API
2.5 Fetch接口调用
2.5.1 fetch的基本语法
2.5.2 fetch请求参数
2.6 Axios进行接口调用
2.6.1 axios基本用法
2.6.2 axios常用API
2.7asyns/await接口调用
2.7.1async/await的基本用法
参考文章:(8条消息) 三、vue前后端交互(轻松入门vue)_vue如何和后端交互_莫逸风的博客-CSDN博客
一、 跨域
1. 什么是跨域?
在了解什么是跨域的时候,我们首先要了解一个概念,叫同源策略,什么是同源策略呢,就是我们的浏览器出于安全考虑,只允许与本域下的接口交互。不同源的客户端脚本在没有明确授权的情况下,不能读写对方的资源。
2. 什么是本域?
本域指的是同协议、同端口、同域名
3. 浏览器请求的三种报错
① 请求未发送
② 请求发送后,服务器发现不一样,服务器未反应。
③ 请求发送,服务器有反应,数据返回的时候,浏览器发现不对,被拦截。
二、SpringBoot解决跨域问题+其他前后端跨域请求解决方案
1. SpringBoot上直接添加@CrossOrigin
在Controller层直接添加@CrossOrigin注解就可以解决
2.处理跨域请求的Configuration
CrossOriginConfig.java
继承WebMvcConfigurerAdapter或者实现WebMvcConfigurer接口
import org.springframework.context.annotation.Configuration;import org.springframework.web.servlet.config.annotation.CorsRegistry;import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;/** * AJAX请求跨域 * @author Mr.W * @time 2018-08-13 */@Configurationpublic class CorsConfig extends WebMvcConfigurerAdapter {static final String ORIGINS[] = new String[] { "GET", "POST", "PUT", "DELETE" };@Overridepublic void addCorsMappings(CorsRegistry registry) {registry.addMapping("/**").allowedOrigins("*").allowCredentials(true).allowedMethods(ORIGINS).maxAge(3600);}}
3. 采用过滤器的方式
3.1 方式一
@Componentpublic class CORSFilter implements Filter {@Overridepublic void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)throws IOException, ServletException {HttpServletResponse res = (HttpServletResponse) response;res.addHeader("Access-Control-Allow-Credentials", "true");res.addHeader("Access-Control-Allow-Origin", "*");res.addHeader("Access-Control-Allow-Methods", "GET, POST, DELETE, PUT");res.addHeader("Access-Control-Allow-Headers", "Content-Type,X-CAF-Authorization-Token,sessionToken,X-TOKEN");if (((HttpServletRequest) request).getMethod().equals("OPTIONS")) {response.getWriter().println("ok");return;}chain.doFilter(request, response);}@Overridepublic void destroy() {}@Overridepublic void init(FilterConfig filterConfig) throws ServletException {}}
3.2 方式二
import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.http.HttpHeaders;import org.springframework.http.HttpMethod;import org.springframework.http.HttpStatus;import org.springframework.http.server.reactive.ServerHttpRequest;import org.springframework.http.server.reactive.ServerHttpResponse;import org.springframework.web.cors.reactive.CorsUtils;import org.springframework.web.server.ServerWebExchange;import org.springframework.web.server.WebFilter;import org.springframework.web.server.WebFilterChain;import reactor.core.publisher.Mono;/** * @author JiaweiWu * @create 2018/3/22. */@Configurationpublic class RouteConfiguration {//这里为支持的请求头,如果有自定义的header字段请自己添加(不知道为什么不能使用*)private static final String ALLOWED_HEADERS = "x-requested-with, authorization, Content-Type, Authorization, credential, X-XSRF-TOKEN,token,username,client";private static final String ALLOWED_METHODS = "*";private static final String ALLOWED_ORIGIN = "*";private static final String ALLOWED_Expose = "*";private static final String MAX_AGE = "18000L";@Beanpublic WebFilter corsFilter() {return (ServerWebExchange ctx, WebFilterChain chain) -> {ServerHttpRequest request = ctx.getRequest();if (CorsUtils.isCorsRequest(request)) {ServerHttpResponse response = ctx.getResponse();HttpHeaders headers = response.getHeaders();headers.add("Access-Control-Allow-Origin", ALLOWED_ORIGIN);headers.add("Access-Control-Allow-Methods", ALLOWED_METHODS);headers.add("Access-Control-Max-Age", MAX_AGE);headers.add("Access-Control-Allow-Headers", ALLOWED_HEADERS);headers.add("Access-Control-Expose-Headers", ALLOWED_Expose);headers.add("Access-Control-Allow-Credentials", "true");if (request.getMethod() == HttpMethod.OPTIONS) {response.setStatusCode(HttpStatus.OK);return Mono.empty();}}return chain.filter(ctx);};}}
1. ServerWebExchange的注释: ServerWebExchange是一个HTTP请求-响应交互的契约。提供对HTTP请求和响应的访问,并公开额外的服务器端处理相关属性和特性,如请求属性。
2.
4. 其他解决方案—NGINX反向代理
server {listen 80;server_nameabc.com;#charset koi8-r;#access_loglogs/host.access.logmain;location /client { #访问客户端路径proxy_pass http://localhost:81;proxy_redirect default;}location /apis { #访问服务器路径rewrite^/apis/(.*)$ /$1 break;proxy_pass http://localhost:82; }}
三、VUE的前后端交互
1. 前后端交互模式
1.1传统的交互方式
原生AJAX、基于jQuery的ajax、fetch、axios
1.2传统的URL
格式:schema://host:port/path” />1.3RESTFUL风格的URL
HTTP请求方式
- GET 查询
- POST 添加
- PUT 修改
- DELETE 删除
2. Promise相关概念与使用
2.1 promise使用的优势
Promise是异步编程的一种解决方案,从语法上讲,Promise是一个对象,从它可以获取异步操作的消息。
- 可以避免多层异步调用嵌套问题(回调地域)
- Promise对象提供了简介的API,使得控制异步操作更加容易
2.2 promise的基本用法
实例化Promise对象,构造函数中传递函数,该函数中用于处理异步任务。
resolve和reject两个(方法)参数用于处理成功和失败两种情况,并通过p.then获取处理结果。
var p = new Promise(function(resolve,reject){//成功时调用resolve()//失败时调用reject()});p.then(function(ret){//从resolve得到正常结果},function(ret){//从reject得到错误信息});
2.3 then参数的函数返回值
2.3.1 返回实例对象
p.then(function(ret){//返回一个实例对象,这个实例对象用于调用下一个thenreturn new Promise();}).then(...)
???在上面也就是如果目前获取了对象就相当于传到了ret中,下一步then中ret则可以调用其中的数据或者其他方法???
2.3.2 返回普通值
返回的普通值会直接传递给下一个then,通过then函数中函数的参数接收该值(底层会对返回的普通值封装为一个Promise使得能够继续调用then)
p.then(function(ret){return "hahah";}).then(function(ret){alter(ret); //这里的输出值就是 hahah}
2.3.3 基于promise请求ajax的demo
//Promise基本使用,原生ajaxfunction getText(url) {var p = new Promise(function (resolve, reject) {var xhr = new XMLHttpRequest();xhr.onreadystatechange = function () {//readyState表示文档状态if (xhr.readyState != 4) return;if (xhr.readyState == 4 && xhr.status == 200){//处理正常情况resolve(xhr.responseText);}else {reject('服务器错误');}};xhr.open('get',url);xhr.send(null);});return p;}//链式调用解决回调地狱,return一个新的调用就可以继续调用新的then()了。getText('http://localhost:8088/saymo').then(function (data) {alert(data);returngetText('http://localhost:8088/sayyi');},function (info) {alert(info);}).then(function (data) {alert(data);return getText('http://localhost:8088/sayfeng')}).then(function (data) {alert(data);});
2.4 Promise常用API
2.4.1 实例方法
1. p.then() #输出执行结果
2. p.catch() #捕获异常
3. p.finally() #无论正常还是异常都会执行
function foo() {return new Promise(function (resolve, reject) {setTimeout(function () {//resolve(123)//正常情况reject("出错了");//错误情况},1000)})}foo().then(function (data) {alert(data);}).catch(function (data) {alert(data);}).finally(function () {alert("结束了")})//与上面效果相同foo().then(function (data) {alert(data);},function (data) {alert(data);}).finally(function () {alert("结束了")})
2.4.2 对象方法
Promise.all() #并发处理多个异步任务,只有所有任务都执行完成才可以得到结果
Promise.race()#并发处理多个异步任务,只要有一个执行完成就可以得到结果
function getText(url) {var p = new Promise(function (resolve, reject) {var xhr = new XMLHttpRequest();xhr.onreadystatechange = function () {//readyState表示文档状态if (xhr.readyState != 4) return;if (xhr.readyState == 4 && xhr.status == 200){//处理正常情况resolve(xhr.responseText);}else {reject('服务器错误');}};xhr.open('get',url);xhr.send(null);});return p;}var p1 = getText("http://localhost:8088/saymo");var p2 = getText("http://localhost:8088/sayyi");var p3 = getText("http://localhost:8088/sayfeng");//result是一个数组形式的三个数据,顺序和p1,p2,p3顺序相同Promise.all([p1,p2,p3]).then(function (result) {alert(result);})//result返回一个数据,最快返回的一个Promise.race([p1,p2,p3]).then(function (result) {alert(result);})
2.5 Fetch接口调用
还有一种更加简便的方法,就是使用fetch接口进行调用,这个是基于Promise实现的
2.5.1 fetch的基本语法
1. 语法结构
fetch(url).then(fn2).then(fn3)....cach(fn)
2. 基本用法
fetch('/abc').then(data=>{return data.text();}).then(ret=>{//这里得到的才是最终的数据console.log(ret);})
2.5.2 fetch请求参数
1. 常用配置选项
method(String):HTTP请求方法,默认为GET(GET、POST、PUT、DELETE)
body(String):HTTP的请求参数
headers(Object):HTTP的请求头,默认为{}
2. get请求参数传递
fetch('http://localhost:8088/sayHi?name="莫逸风',{method:'get'}).then(function (data) {return data.text();}).then(function (data) {alert(data);});
3. post请求参数传递
参数form表单形式
fetch('http://localhost:8088/login',{method:'post',body:,headers:{'Content-Type':'application/x-www-form-urlencoded',// Content-Type还有下面三种形式//1.multipart/form-data//2.application/json//3.text/xml }}).then(function (data) {return data.text();}).then(function (data) {alert(data);})
参数json表单形式
fetch('http://localhost:8088/login',{method:'post',body:JSON.stringify({name:'莫逸风',pass:'1234',}),headers:{'Content-Type':'application/json',}}).then(function (data) {return data.text();}).then(function (data) {alert(data);});
4. 返回响应类型
text():将返回体处理成字符串类型
json():返回结果和JSON.parse(responseText)一样
2.6 Axios进行接口调用
axios(官网:https://github.com/axios/axios)是一个基于Promise用于浏览器和node.js的HTTP客户端
它具有以下特征:
- 支持浏览器和node.js
- 支持promise
- 能拦截请求和相应
- 自动转换JSON数据
2.6.1 axios基本用法
//去github下载文件,此js位于axios-master\distaxios.get('http://localhost:8088/saymo').then(function (ret) {//data属性是固定的用法,用于获取后台的实际数据alert(ret.data)})
2.6.2 axios常用API
- get:查询数据
- post:添加数据
- put:修改数据
- delete:删除数据
1. get传递参数
通过URL传递参数
axios.get('http://localhost:8088/sayhi?name=莫逸风').then(function (ret) {alert(ret.data)})
通过params传递参数
axios.get('http://localhost:8088/sayhi',{params:{name:"莫逸风"}}).then(function (ret) {//data属性是固定的用法,用于获取后台的实际数据alert(ret.data)})
2. post传递参数
通过对象传递参数,默认为json格式
axios.post('http://localhost:8088/login',{name:"莫逸风",pass:"1234",}).then(function (ret) {//data属性是固定的用法,用于获取后台的实际数据alert(ret.data)})
通过URLSearchParams传递参数
var param = new URLSearchParams();param.append('name','莫逸风');param.append('pass','12345');axios.post('http://localhost:8088/login',param).then(function (ret) {//data属性是固定的用法,用于获取后台的实际数据alert(ret.data)})
3. axios的响应结果
- data:实际响应回来的数据
- headers:响应头信息
- status:响应状态码
- statusText:响应状态信息
axios.post('http://localhost:8088/login',param).then(function(ret){console.log(ret);//所有数据都包含在此对象中//对于json形式的响应数据可以直接获取,不需要转换alert(ret.data.name);})
4. axios的全局配置
axios.defaults.timeout = 3000;//超时时间//默认地址,再写请求的时候只需要写后面的路由就行了axios.defaults.baseURL = 'http://localhost:3000/app';axios.defaults.headers['mytoken']='aqwerwqwerqwer2ewrwe23eresdff23'//设置请求头
5. axios拦截器
请求拦截器
//在这里就是在请求之前设置了拦截器,用于获取网页http://localhost:8088/axios.interceptors.request.use(function (config) {config.baseURL = "http://localhost:8088/";alert(config.url);return config;},function (err) {console.log(err);})axios.get('sayhi?name=莫逸风').then(function (ret) {//data属性是固定的用法,用于获取后台的实际数据alert(ret.data)})
响应拦截器
axios.interceptors.response.use(function (res) {var data = res.data;return data;},function (err) {console.log(err);})axios.get('sayhi?name=莫逸风').then(function (res) {//data属性是固定的用法,用于获取后台的实际数据alert(res)})
2.7asyns/await接口调用
2.7.1async/await的基本用法
async/await是ES7引入的语法,可以更加方便的进行异步操作
async关键字用于函数上(async函数的返回值是Promise实例对象)
await关键字用于async函数中(await可以得到异步的结果)
axios.defaults.baseURL = 'http://localhost:8088/';async function queryData(){var ret = await axios.get('saymo');//alert(ret.data);return ret.data;}queryData().then(function (data) {alert(data);});
异步请求
axios.defaults.baseURL = 'http://localhost:8088/';async function queryData(){var ret = await axios.get('saymo');alert(ret.data);var ret1 = await axios.get('sayyi');alert(ret1.data);var ret2 = await axios.get('sayfeng');return ret2.data;}queryData().then(function (data) {alert(data);});