文章知识点来源:从MVC到前后端分离(REST-个人也认为是目前比较流行和比较好的方式) 本文主要是抽取我想要的部分快速实现: 1,服务端要解决跨域问题: 前端应用为静态站点且部署在http://web.xxx.com域下,后端应用发布REST API并部署在http://api.xxx.com域下,如何使前端应用通过AJAX跨域访问后端应用呢?这需要使用到CORS技术来实现,这也是目前最好的解决方案了。 [CORS全称为Cross Origin Resource Sharing(跨域资源共享),服务端只需添加相关响应头信息,即可实现客户端发出AJAX跨域请求。] CORS技术非常简单,易于实现,目前绝大多数浏览器均已支持该技术(IE8浏览器也支持了),服务端可通过任何编程语言来实现,只要能将CORS响应头写入response对象中即可。 下面我们继续扩展REST框架,通过CORS技术实现AJAX跨域访问。 首先,我们需要编写一个Filter,用于过滤所有的HTTP请求,并将CORS响应头写入response对象中,代码如下:
import io.netty.util.internal.StringUtil;
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
/**
* Title: 跨域访问处理(跨域资源共享)
* Description: 解决前后端分离架构中的跨域问题
* @author cjj
* @created 2017年7月4日 下午5:00:09
*/
public class CorsFilter implements Filter{
private static final Logger logger = LoggerFactory.getLogger(CorsFilter.class);
private String allowOrigin;
private String allowMethods;
private String allowCredentials;
private String allowHeaders;
private String exposeHeaders;
@Override
public void init(FilterConfig filterConfig) throws ServletException {
allowOrigin = filterConfig.getInitParameter("allowOrigin");
allowMethods = filterConfig.getInitParameter("allowMethods");
allowCredentials = filterConfig.getInitParameter("allowCredentials");
allowHeaders = filterConfig.getInitParameter("allowHeaders");
exposeHeaders = filterConfig.getInitParameter("exposeHeaders");
}
/**
* @description 通过CORS技术实现AJAX跨域访问,只要将CORS响应头写入response对象中即可
* @author rico
* @created 2017年7月4日 下午5:02:38
* @param req
* @param res
* @param chain
* @throws IOException
* @throws ServletException
* @see javax.servlet.Filter#doFilter(javax.servlet.ServletRequest, javax.servlet.ServletResponse, javax.servlet.FilterChain)
*/
@Autowired
@Override
public void doFilter(ServletRequest req, ServletResponse res,
FilterChain chain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;
String currentOrigin = request.getHeader("Origin");
response.setHeader("Access-Control-Allow-Origin", currentOrigin);
/**
* Access-Control-Allow-Origin:允许访问的客户端域名,例如:http://web.xxx.com,若为*,则表示从任意域都能访问,即不做任何限制。
* Access-Control-Allow-Methods:允许访问的方法名,多个方法名用逗号分割,例如:GET,POST,PUT,DELETE,OPTIONS。
* Access-Control-Allow-Credentials:是否允许请求带有验证信息,若要获取客户端域下的cookie时,需要将其设置为true。
* Access-Control-Allow-Headers:允许服务端访问的客户端请求头,多个请求头用逗号分割,例如:Content-Type。
* Access-Control-Expose-Headers:允许客户端访问的服务端响应头,多个响应头用逗号分割。
*/
if (StringUtil.isNullOrEmpty(allowMethods)) {
response.setHeader("Access-Control-Allow-Methods", allowMethods);
}
if (StringUtil.isNullOrEmpty(allowCredentials)) {
response.setHeader("Access-Control-Allow-Credentials", allowCredentials);
}
if (StringUtil.isNullOrEmpty(allowHeaders)) {
response.setHeader("Access-Control-Allow-Headers", allowHeaders);
}
if (StringUtil.isNullOrEmpty(exposeHeaders)) {
response.setHeader("Access-Control-Expose-Headers", exposeHeaders);
}
chain.doFilter(req, res);
}
@Override
public void destroy() {
// TODO Auto-generated method stub
}
}
以上CorsFilter将从web.xml中读取相关Filter初始化参数,并将在处理HTTP请求时将这些参数写入对应的CORS响应头中,下面大致描述一下这些CORS响应头的意义: Access-Control-Allow-Origin:允许访问的客户端域名,例如:http://web.xxx.com,若为*,则表示从任意域都能访问,即不做任何限制。 Access-Control-Allow-Methods:允许访问的方法名,多个方法名用逗号分割,例如:GET,POST,PUT,DELETE,OPTIONS。 Access-Control-Allow-Credentials:是否允许请求带有验证信息,若要获取客户端域下的cookie时,需要将其设置为true。 Access-Control-Allow-Headers:允许服务端访问的客户端请求头,多个请求头用逗号分割,例如:Content-Type。 Access-Control-Expose-Headers:允许客户端访问的服务端响应头,多个响应头用逗号分割。 需要注意的是,CORS规范中定义Access-Control-Allow-Origin只允许两种取值,要么为*,要么为具体的域名,也就是说,不支持同时配置多个域名。为了解决跨多个域的问题,需要在代码中做一些处理,这里将Filter初始化参数作为一个域名的集合(用逗号分隔),只需从当前请求中获取Origin请求头,就知道是从哪个域中发出的请求,若该请求在以上允许的域名集合中,则将其放入Access-Control-Allow-Origin响应头,这样跨多个域的问题就轻松解决了。 以下是web.xml中配置CorsFilter的方法:
corsFilter
com.ssm.fliter.CorsFilter
allowOrigin
*
allowMethods
GET,POST,PUT,DELETE,OPTIONS
allowCredentials
true
allowHeaders
Content-Type
corsFilter
/*
前端跨域简单文件上传尝试:
XMLHttpRequest上传文件
var xhr;
//上传文件方法
function UpladFile() {
var fileObj = document.getElementById("file").files[0]; // js 获取文件对象
var url = "http://localhost:8080/okssm/user/publish/info.json"; // 接收上传文件的后台地址
var form = new FormData(); // FormData 对象
form.append("imgs", fileObj); // 文件对象
form.append("userPhone", "138000000001"); // 文件对象
form.append("type", "1"); // 文件对象
xhr = new XMLHttpRequest(); // XMLHttpRequest 对象
xhr.open("post", url, true); //post方式,url为服务器请求地址,true 该参数规定请求是否异步处理。
xhr.onload = uploadComplete; //请求完成
xhr.onerror = uploadFailed; //请求失败
xhr.send(form); //开始上传,发送form数据
}
//上传成功响应
function uploadComplete(evt) {
//服务断接收完文件返回的结果
var data = JSON.parse(evt.target.responseText);
if(data.resCode==10000) {
alert("上传成功!");
}else{
alert("上传失败!");
}
}
//上传失败
function uploadFailed(evt) {
alert("上传失败!");
}
//取消上传
function cancleUploadFile(){
xhr.abort();
}
|