前言
前后端分离以后,数据的获取渲染都由前端完成。后台只提供纯粹的数据,以JSON为主。因此在获取数据的过程中会遭遇诸如跨域、HTTP请求错误、前端提交数据格式错误等诸多问题。因此本文将结合自身开发经验,讨论在前后端分离过程中,数据获取的一些经验。
什么是跨域?
这些年我们处理过的跨域——援引博客园 幻精灵的一篇文章,本文详细的介绍了什么是跨域,以及相关的跨域方法
JAVA中的解决方法
常规跨域请求Http Header 设置
response.setHeader("Access-Control-Allow-Origin", "domain");//设置能够访问的域,"*"为任意可访问
response.setHeader("Access-Control-Allow-Methods", "POST, GET, PUT, OPTIONS, DELETE, PATCH");//设置能够访问的http method
response.setHeader("Access-Control-Allow-Headers", "Token,Origin, X-Requested-With, Content-Type, Accept");//设置能够访问的http header
response.setHeader("Access-Control-Max-Age", "3600");//设置超时时间
如前端(通常指JavaScript的AJAX)需要在请求后端后访问后端设置的某一Http Header,则后端需要设置响应跨域许可,如下:
response.setHeader("Access-Control-Expose-Headers","Token");//设置响应能够访问的http header
其中这条规则
response.setHeader("Access-Control-Expose-Headers","Token");//设置响应能够访问的http header
需要小本本记下来,后文将会提到
前端在跨域中的实践
推荐跨域工具——axios
axios——现代浏览器的ajax工具,支持promise的用法,解决前端异步方法中回调地狱问题,支持标准的GET POST PUT DELETE等请求方法。在node上通过配置axios请求,也支持流的处理。
一般使用方法
import axios from 'axios'; // 通过npm安装模块化后进行引用
axios.defaults.headers['Content-Type'] = 'application/json;charset=UTF-8';// 将HTTP请求中body设置为JSON格式,默认为表单提交
axios.get(URL, {headers:{ session: 'bamboocloud'}, timeout: 15000 })
.then(res => {
// TODO
})
.catch(err => {
console.log(err.response)
})
通过GET方法请求后台提供的API接口,其中第二个对象为设置参数,这里新增了一个请求头session,值为bamboocloud,设置了超时时间,以ms为单位。一般来说,我们把认证相关信息如session、token等放在请求头中,这样后台就能通过
@RequestHeader("XXX")
String XXX 注解获取我们传过去的请求头。
在then方法中返回的res是axios返回的对象,它有如下的数据结构
{
//`data` is the response that was provided by the server
data:{},
//`status` is the HTTP status code from the server response
status:200,
//`statusText` is the HTTP status message from the server response
statusText:'OK',
// `headers` the headers that the server responded with
// All header names are lower cased
headers:{},
//`config` is the config that was provided to `axios` for the
requestconfig:{},
//`request` is the request that generated this response
// It is the last ClientRequest instance in node.js (in redirects)
//and an XMLHttpRequest instance the browser
request:{}
}
其中data就是后台返回给我们的实际对象,status是请求的状态,注意,只有2XX才会走then回调,即成功回调。4XX,5XX都会走catch回调,如果没有写catch,则会抛出报错信息到全局,err是这个错误对象信息。
如果后台设置了错误信息,比如错误也会带body,那么通过err.response获取。
headers是这个请求的响应头,默认只有content-type,cookie能够被获取到。
想加载后台给我们的自定义header,一定要设置前文提到的
Access-Control-Expose-Headers。
常见误区
-
因为前后端分离,因此部署网页的服务器和提供API的服务器不是一台服务器。因此常见于后台通过创建session标记一个客户端的方法会失效。请求html文档,和axios请求方法会创建两个不同的session
-
因为默认是跨域的,而跨域默认是不带cookie的,推测这个是导致session不一致的原因(未验证)。可以通过设置{ withCredentials = true },让axios请求携带cookie,注意这种方法,后台
Access-Control-Allow-Origin 不能设置为 * ,必须指定具体的域名或者IP地址
-
后台传输JSON一定要添加@ResponseBody注解,否则会报404错误,建议在controller类上添加该注解
推荐的实践
在开发环境中,可以允许所有跨域。但是建议部署到生产环境,设置为指定IP地址或者域名提高安全性。
就是这样:)
网友评论