jsonp解决跨域请求问题

来源:互联网 发布:达梦数据库下载网盘 编辑:程序博客网 时间:2024/05/18 03:10

之前了解了跨域,只是有些印象,正好这次前后端分离可以用到,在此详细记录一下。
1.跨域问题:浏览器出于安全考虑,不允许js的ajax跨域请求资源。

跨域的定义:域名或端口号不同都是跨域

2.解决跨域问题:本文的解决方案:jsonp

3.jsonp原理:
jsonp即json+padding,动态创建script标签,利用script标签的src属性可以获取任何域下的js脚本,通过这个特性(也可以说是漏洞),服务器端不再返回json格式,而是返回一段调用某个函数的js代码,在src中进行了调用,这样实现了跨域。

4.jsonp解决方案实现
写一个通用的类实现jsonp通用支持,让每一个request的请求都经过该类,若为跨域请求则使用jsonp进行处理,否则就正常处理。该类继承MappingJackson2HttpMessageConverter然后进行扩展。

package com.bdit.common;import java.io.IOException;import javax.servlet.http.HttpServletRequest;import org.apache.commons.io.IOUtils;import org.apache.commons.lang3.StringUtils;import org.springframework.http.HttpOutputMessage;import org.springframework.http.converter.HttpMessageNotWritableException;import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;import org.springframework.web.context.request.RequestContextHolder;import org.springframework.web.context.request.ServletRequestAttributes;import com.fasterxml.jackson.core.JsonEncoding;import com.fasterxml.jackson.core.JsonProcessingException;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);            System.out.println(callbackParam);            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)+");";                            System.out.println(result);                            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;    }}

5.前端调用格式:
前端调用在需要跨域请求的原url上添加?callback=任意函数名,同时需要在ajax的请求中设置数据乐西dataType:”jsonp”。
示例:

关于jsonp优缺点情况这篇文章《jsonp的原理,应用场景,优缺点》
关于跨域的解决方案请看此篇《前后端分离跨域问题解决方案》