同服务器测试:
1.浏览器的网址信息: http://manage.xx.com/test.html
2.ajax请求的地址信息: http://manage.xx.com/test.json
发现: 请求协议名称://域名:端口号都相同时,请求可以正常进行.

不同服务器测试:
1.浏览器的网址信息: http://www.xx.com/test.html
2.ajax请求的地址信息: http://manage.xx.com/test.json
结论: 域名地址不相同时请求不能正常获取响应的结果.

同源策略

从上述的例子中可以想到:为什么同服务器的请求可以进行,不同服务器的就不行,也就引出了同源策略.

说明:
浏览器在解析ajax时,如果发现请求的协议名称://请求的域名:请求的端口号与网址的地址都相同的时满足同源策略的规定,浏览器可以正确的解析返回值.该访问称之为同域访问.该策略叫做同源策略.
但是如果违反了同源策略中的任意一条,则叫做跨域访问.浏览器出于安全性的考虑.不予解析返回值(请求正常的被处理,但是接收不到返回值).

概括: 浏览器解析ajax时,由于请求违反了同源策略则称之为跨域请求.

跨域访问

跨域访问的常用方式分为两种

JSONP实现跨域

JSONP概念

JSONP(JSON with Padding)是JSON的一种“使用模式”,可用于解决主流浏览器的跨域数据访问的问题

JSONP实现跨域的原理

第一步:在javaScript中的src属性不受同源策略的约束.可以获取远程服务器数据.

<!--该json一直保存到浏览器中等待调用,但是没有函数名称无法调用  -->
<script type="text/javascript" src="http://manage.jt.com/test.json"></script>

第二步:自定义回调函数 名称任意

/*定义回调函数  */
function hello(data){
    alert(data.name);
}

第三步:将返回值结果进行特殊的格式封装 callback(JSON);

hello({"id":"1","name":"tomcat猫"})

JSONP优化实现

1.利用script中的src属性发起请求不方便.不便于程序使用 --> 能否封装为ajax调用方式
2.在请求路径中拼接一个参数一般的key都是约定俗称的 http:xxx/xx? --> callback=“自定义函数名称”
3.动态的获取callback的参数名称之后进行特殊的格式封装callback(JSON);

JSONP简单示例

1.前端ajax调用

<script type="text/javascript">
    $(function(){
        alert("测试访问开始!!!!!")
        $.ajax({
            url:"http://manage.jt.com/web/testJSONP",
            type:"get",                //jsonp只能支持get请求 src只能是get请求
            dataType:"jsonp",       //dataType表示返回值类型
            //jsonp: "callback",    //指定参数名称
            //jsonpCallback: "hello",  //指定回调函数名称
            success:function (data){   //data经过jQuery封装返回就是json串
                alert(data.itemId);
                alert(data.itemDesc);
            }
        });    
    })
</script>

2.后台controller返回数据

@RestController
public class JSONPController {

    /**
     * 测试跨域访问是否成功
     * url地址: http://manage.jt.com/web/testJSONP?callback=jQuery111106536880527642785_1600138715329&_=1600138715330
     * 返回值的应该是经过特殊格式封装的数据.  callback(JSON)
     */
    @RequestMapping("/web/testJSONP")
    public String  jsonp(String callback){
        ItemDesc itemDesc = new ItemDesc();
        itemDesc.setItemId(100L).setItemDesc("跨域测试成功!!!!");
        String json = ObjectMapperUtil.toJSON(itemDesc);
        return callback+"("+json+")";
    }
}

3.优化
可以看到现在controller中是通过字符串拼接,拼接为JSONP所需要的特殊格式;
我们可以引入JSONPObject直接返回JSONP所需的格式数据,如下所示:

 /**
 * 测试跨域访问是否成功
 * url地址: http://manage.jt.com/web/testJSONP?callback=jQuery111106536880527642785_1600138715329&_=1600138715330
 * 返回值的应该是经过特殊格式封装的数据.  callback(JSON)
 * JSONPObject参数说明:
 *  1.function 回调函数名称
 *  2.返回的对象之后可以被转化为JSON
 */
@RequestMapping("/web/testJSONP")
public JSONPObject jsonp(String callback){
    ItemDesc itemDesc = new ItemDesc();
    itemDesc.setItemId(100L).setItemDesc("API测试!!!");
    return new JSONPObject(callback, itemDesc);
}

关于ajax请求时间毫秒的说明

在从前端接受的ajax请求中通常会拼接一串时间毫秒数,由于浏览器内部有缓存机制,所以如果遇到了一个相同的请求地址,浏览器可能会使用之间的结果.(使用缓存),但是有些数据必须要求浏览器重数据库中动态获取数据,为了避免浏览器缓存一般在url最后添加随机数或者时间毫秒数区分url请求.实现该功能.
image

CORS跨域访问

CORS跨域说明

说明:当下的主流的浏览器默认支持cors跨域的形式,但是需要服务器添加响应的信息.否则浏览器不支持数据的获取.

编辑CORS配置类

说明:在项目的common通用包中添加CORS的配置类

    /**
     * 实现跨域的方式
     * 需要配置服务端程序
     * 方法说明:
     *      1.addMapping(/**) 允许什么样的请求可以跨域  所有的请求
     *      2.allowedOrigins("*")可以允许任意的域名
     *      3.allowCredentials(true) 跨域时是否允许携带cookie等参数
     */
    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**")
                .allowedOrigins("*")
                .allowCredentials(true);
    }
}

跨域测试

将返回数据改为json格式,就可以直接进行返回了


迈克丝
85 声望5 粉丝

一步一步学技术,踏踏实实涨经验,兴趣广泛,广交好友,希望大家多多指正/批评.


引用和评论

0 条评论