赞
踩
目录
二、SpringBoot解决跨域问题+其他前后端跨域请求解决方案
1. SpringBoot上直接添加@CrossOrigin
参考文章:(8条消息) 三、vue前后端交互(轻松入门vue)_vue如何和后端交互_莫逸风的博客-CSDN博客
在了解什么是跨域的时候,我们首先要了解一个概念,叫同源策略,什么是同源策略呢,就是我们的浏览器出于安全考虑,只允许与本域下的接口交互。不同源的客户端脚本在没有明确授权的情况下,不能读写对方的资源。
本域指的是同协议、同端口、同域名
① 请求未发送
② 请求发送后,服务器发现不一样,服务器未反应。
③ 请求发送,服务器有反应,数据返回的时候,浏览器发现不对,被拦截。
在Controller层直接添加@CrossOrigin注解就可以解决
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
- */
- @Configuration
- public class CorsConfig extends WebMvcConfigurerAdapter {
- static final String ORIGINS[] = new String[] { "GET", "POST", "PUT", "DELETE" };
- @Override
- public void addCorsMappings(CorsRegistry registry) {
- registry.addMapping("/**").allowedOrigins("*").allowCredentials(true).allowedMethods(ORIGINS)
- .maxAge(3600);
- }
- }
- @Component
- public class CORSFilter implements Filter {
-
- @Override
- public 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);
- }
- @Override
- public void destroy() {
- }
- @Override
- public void init(FilterConfig filterConfig) throws ServletException {
- }
- }
-
- 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.
- */
- @Configuration
- public 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";
-
- @Bean
- public 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.
- server {
- listen 80;
- server_name abc.com;
- #charset koi8-r;
- #access_log logs/host.access.log main;
-
- location /client { #访问客户端路径
- proxy_pass http://localhost:81;
- proxy_redirect default;
- }
- location /apis { #访问服务器路径
- rewrite ^/apis/(.*)$ /$1 break;
- proxy_pass http://localhost:82;
- }
- }
原生AJAX、基于jQuery的ajax、fetch、axios
格式:schema://host:port/path?query#fragment
schema:协议,例如http、https、ftp等。
host:域名或者IP地址。
port:端口,http默认端口80,可以省略。
path:路径,例如/abc/a/b/c
query:查询参数,例如uname=lisi&age=12
fragment:锚点(哈希Hash),用于定位页面的某个位置
HTTP请求方式
- GET 查询
- POST 添加
- PUT 修改
- DELETE 删除
Promise是异步编程的一种解决方案,从语法上讲,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.1 返回实例对象
- p.then(function(ret){
- //返回一个实例对象,这个实例对象用于调用下一个then
- return 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
- <script>
- //Promise基本使用,原生ajax
- 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;
- }
- //链式调用解决回调地狱,return一个新的调用就可以继续调用新的then()了。
- getText('http://localhost:8088/saymo').then(
- function (data) {
- alert(data);
- return getText('http://localhost:8088/sayyi');
- },function (info) {
- alert(info);
- }
- ).then(
- function (data) {
- alert(data);
- return getText('http://localhost:8088/sayfeng')
- }
- ).then(
- function (data) {
- alert(data);
- }
- );
- </script>
2.4.1 实例方法
1. p.then() #输出执行结果
2. p.catch() #捕获异常
3. p.finally() #无论正常还是异常都会执行
- <script>
- 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("结束了")
- })
- </script>
2.4.2 对象方法
Promise.all() #并发处理多个异步任务,只有所有任务都执行完成才可以得到结果
Promise.race() #并发处理多个异步任务,只要有一个执行完成就可以得到结果
- <script>
- 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);
- })
- </script>
还有一种更加简便的方法,就是使用fetch接口进行调用,这个是基于Promise实现的
1. 语法结构
- fetch(url).then(fn2)
- .then(fn3)
- ...
- .cach(fn)
2. 基本用法
- fetch('/abc').then(data=>{
- return data.text();
- }).then(ret=>{
- //这里得到的才是最终的数据
- console.log(ret);
- })
1. 常用配置选项
method(String):HTTP请求方法,默认为GET(GET、POST、PUT、DELETE)
body(String):HTTP的请求参数
headers(Object):HTTP的请求头,默认为{}
2. get请求参数传递
- <script>
- fetch('http://localhost:8088/sayHi?name="莫逸风',{
- method:'get'
- }).then(function (data) {
- return data.text();
- }).then(function (data) {
- alert(data);
- });
- </script>
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)一样
axios(官网:https://github.com/axios/axios)是一个基于Promise用于浏览器和node.js的HTTP客户端
它具有以下特征:
- //去github下载文件,此js位于axios-master\dist
- <script src="axios.js"></script>
- <script>
- axios.get('http://localhost:8088/saymo').then(function (ret) {
- //data属性是固定的用法,用于获取后台的实际数据
- alert(ret.data)
- })
- </script>
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的响应结果
- 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)
- })
async/await是ES7引入的语法,可以更加方便的进行异步操作
async关键字用于函数上(async函数的返回值是Promise实例对象)
await关键字用于async函数中(await可以得到异步的结果)
- <script src="axios.js"></script>
- <script>
- 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);
- });
- </script>
异步请求
- <script>
- 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);
- });
- </script>
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。