一、跨域问题的产生及概念
1.1 跨域的概念
JavaScript由于安全性方面的考虑,不允许页面跨域调用其他页面的对象。产生跨域的原因是这是由于浏览器同源策略的限制,现在所有支持JavaScript的浏览器都使用了这个策略。那么什么是同源呢?所谓的同源是指三个方面“相同”:
- 域名相同
- 协议相同
- 端口相同
1.2 跨域实例
下面就举几个例子来说明跨域现象:
http://www.a.com/a.js
http://www.a.com/b.js 同一域名 允许
http://www.a.com/a.js
http://www.b.com/a.js 不同域名 不允许
http://www.a.com:8000/a.js
http://www.a.com/b.js 同一域名不同端口 不允许
https://www.a.com/a.js
http://www.a.com/b.js 同一域名不同协议 不允许
二、跨域问题的解决方案
2.1 通过自定义过滤器设置Header
public class SimpleCORSFilter implements Filter{
@Override
public void destroy() {
}
@Override
public void doFilter(ServletRequest req, ServletResponse res,
FilterChain chain) throws IOException, ServletException {
HttpServletResponse response = (HttpServletResponse) res;
response.setHeader("Access-Control-Allow-Origin", "*");
response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE");
response.setHeader("Access-Control-Max-Age", "3600");
response.setHeader("Access-Control-Allow-Headers", "x-requested-with");
chain.doFilter(req, res);
}
@Override
public void init(FilterConfig arg0) throws ServletException {
}
}
在web.xml中需要添加如下配置:
<filter>
<filter-name>cors</filter-name>
<filter-class>com.ssm.web.filter.SimpleCORSFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>cors</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</filter>
2.2 Jsonp
设置接受类型为jsonp(注意,contenType和dataType是不同的。contentType用于定义发送的数据的类型,一般都是text类型;dataType是用于定义预期从服务器接受的数据类型,浏览器会按指定类型进行解析)
$.ajax({
url:"your url",
type:"get or post",
async:false,
//发送类型
contentType:"text/html; charset=utf-8",
//接收类型
dataType : "jsonp",
success:function(data){
console.log(data);
},
error:function(data){
console.log(data);
}
});
后台可设置注解驱动统一支持jsonp
public class CallbackMappingJackson2HttpMessageConverter extends MappingJackson2HttpMessageConverter {
// 做jsonp的支持的标识,在请求参数中加该参数
private String callbackName;
@Override
protected void writeInternal(Object object, HttpOutputMessage outputMessage) throws IOException,
HttpMessageNotWritableException {
// 从threadLocal中获取当前的Request对象
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder
.currentRequestAttributes()).getRequest();
String callbackParam = request.getParameter(callbackName);
if (StringUtils.isEmpty(callbackParam)) {
// 没有找到callback参数,直接返回json数据
super.writeInternal(object, outputMessage);
} else {
JsonEncoding encoding = getJsonEncoding(outputMessage.getHeaders().getContentType());
try {
String result = callbackParam + "(" + super.getObjectMapper().writeValueAsString(object)
+ ");";
IOUtils.write(result, outputMessage.getBody(), encoding.getJavaName());
} catch (JsonProcessingException ex) {
throw new HttpMessageNotWritableException("Could not write JSON: " + ex.getMessage(), ex);
}
}
}
public String getCallbackName() {
return callbackName;
}
public void setCallbackName(String callbackName) {
this.callbackName = callbackName;
}
}
修改配置文件,添加注解驱动
<!-- 注解驱动 -->
<mvc:annotation-driven>
<mvc:message-converters register-defaults="true">
<!-- 自定义String类型的消息转化器 -->
<!-- <bean class="org.springframework.http.converter.StringHttpMessageConverter">
<constructor-arg index="0" value="UTF-8"/>
</bean> -->
<bean class="com.taotao.common.spring.exetend.converter.json.CallbackMappingJackson2HttpMessageConverter">
<property name="callbackName" value="callback"/>
</bean>
</mvc:message-converters>
</mvc:annotation-driven>