• jQuery的jsonp跨域是这么回事.


    实现跨域请求的有iframe,img,script中的src属性.
    那么jquery是如何解决跨域请求的呢?

    一:
    项目jsonp2中有个app.js文件,代码如下:

    function app(json){
        alert(json['name']);
    }

    项目jsonp1中的index.html

    <script type="text/javascript" src="http://127.0.0.1:8020/jsonp2/js/app.js"></script>
    <script type="text/javascript">
        app({'name':"guoyansi",'age':25});
    </script>

    执行结果:
    这里的app方法并没有申明,怎么就能调用了呢?
    这里的第一个script出现了跨域请求,src指向的是jsonp2中的app.js
    而在app.js中申明了app方法.
    我们现在在火狐中查看index.html的源码,点开app.js的script

    结论:从外部引入的app.js最终会被加载到浏览器中,渲染成这样:

    <script type="text/javascript">
        function app(json){
        alert(json['name']);
    }
    </script>

    根据上面的结论
    我们如果利用script跨域向后台发送一个请求,
    我们在后端返回一段js代码,前端不就可以调用了吗?
    现在我们来验证假设.
    我们用java为例子:
    新建javaweb项目并且新建一个servlet,
    这个servlet返回一个js代码;

    package servelt;
    
    import java.io.IOException;
    import java.io.PrintWriter;
    
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    public class Jsonp2 extends HttpServlet {
    
        public void doGet(HttpServletRequest request, HttpServletResponse response)
                throws ServletException, IOException {
    
            response.setContentType("text/javascript;charset=utf-8");//jsonp其实回写的就是一段javascript代码
            //或者:response.setContentType("text/plain;charset=utf-8");
            PrintWriter out = response.getWriter();
            out.print("app({'name':'思思博士','age':'25'})");
            out.flush();
            out.close();
        }
    
        public void doPost(HttpServletRequest request, HttpServletResponse response)
                throws ServletException, IOException {
            doGet(request, response);
        }
    
    }

    新建另外一个项目并且新建一个index.html页面

    <!DOCTYPE html>
    <html>
        <head>
            <meta charset="utf-8" />
            <title></title>
            <script type="text/javascript">
                function app(json){
                    console.log(json);
                }
            </script>
            <script type="text/javascript" src="http://192.168.6.130:8080/jp/Jsonp2"></script>
        </head>
        <body>
            
        </body>
    </html>

    上面的第二个script直接执行了这个新的项目上的servlet.
    并且最终被浏览器解析成如下格式:

    <script type="text/javascript">
        app({'name':'思思博士','age':'25'})
    </script>

    index.html最终的页面变成这个样子:

    <!DOCTYPE html>
    <html>
        <head>
            <meta charset="utf-8" />
            <title></title>
            <script type="text/javascript">
                function app(json){
                    console.log(json);
                }
            </script>
            <script type="text/javascript">
                app({'name':'思思博士','age':'25'})
            </script>
        </head>
        <body>
            
        </body>
    </html>

    上面的代码我想大家都知道是怎么执行的了吧.
    上面的代码返回的js代码的方法调用时时在服务器端写死的.我们也可以从客户顿指定要返回的反法调用名.
    修改servlet:

    package servelt;
    
    import java.io.IOException;
    import java.io.PrintWriter;
    
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    public class Jsonp2 extends HttpServlet {
    
        public void doGet(HttpServletRequest request, HttpServletResponse response)
                throws ServletException, IOException {
    
            response.setContentType("text/javascript;charset=utf-8");//jsonp其实回写的就是一段javascript代码
            String appMethod=request.getParameter("appMethod");
            PrintWriter out = response.getWriter();        
            out.print(appMethod+"({'name':'思思博士','age':'25'})");
            out.flush();
            out.close();
        }
    
        public void doPost(HttpServletRequest request, HttpServletResponse response)
                throws ServletException, IOException {
            doGet(request, response);        
        }
    
    }

    在客户端指定要服务器要返回的js方法,添加appMethod参数,修改index.html.

    <!DOCTYPE html>
    <html>
        <head>
            <meta charset="utf-8" />
            <title></title>
            <script type="text/javascript">
                function app(json){
                    console.log(json);
                }
            </script>
            <script type="text/javascript" src="http://192.168.6.130:8080/jp/Jsonp2?appMethod=app"></script>
        </head>
        <body>
            
        </body>
    </html>

    上面的例子都是返回一段可执行的js代码,来调用本地的方法.
    我们对上面的例子进行封装.java代码保持不变.

    (function($){
        $.gys=function(opt){
            var scriptCode=(new Date()).getTime();
            //拼接script标签
            var html="<";
            html+="script id='script"+scriptCode+"' type='text/javascript' src='"+opt.src+"?"+opt.callbackName+"="+opt.callback+"'>";
            html+="<";
            html+"/script>";
            //申明一个全局的方法变量供远程返回的js方法的调用,方法名有callback指定
            window[opt.callback]=function(json){
                opt.success(json);//调用当前参数的方法
                $("#script"+scriptCode).remove();//删除script标签
            }
            $("head").append(html);//插入script标签                    
        }
    })(jQuery);

    调用:

    $(function(){
        $.gys({
            callbackName:"appMethod",
            callback:"app",
            src:"http://192.168.6.130:8080/jp/Jsonp2",
            success:function(data){
                console.log(data);
            }
        });                
    });

    看到这个有没有觉得和jquery的jsonp有点像了啊.
    我们现在看看jquery的jsonp.
    jsonp其实用的就是上面的原理

    我们看看jquery的jsonp用法.

    $.ajax({
        type:"get",//jsonp只能触发get请求
        url:""//跨域url
        dataType:"jsonp",
        jsonp:"",//对应上面封装的callbackName
        jsonpCallback:"",//对应上面封装的callback
        data:{},//提交参数
        beforeSend:function(){
            //jsonp 方式此方法不被触发。原因是这里已经不是ajax事件了.
        },
        success:funciton(data){
            //参数jsonpCallback的方法调用这里的success
        },
        error:function(){
            //这里不是ajax了,所以这个方法也不会触发.
        }
    });

    jquery中把jsonp和ajax整合在一起了具有一定的迷惑性,ajax是不具有跨域请求的,
    另外jsonp使用的核心也不是ajax的xmlhttprequest,而是script的http请求(脚本注入的行为).
    另外这样的jsonp是不具有post请求的.
    $.getJSON()和$.getScript()都是jsonp的高级封装.

  • 相关阅读:
    Spring JdbcTemplate源码阅读报告
    Linux 套接字通信笔记(一)
    Python的科学计算包matplotlib setup
    创建Spring Boot项目
    Java反射与自定义注解
    二手前端入门React项目
    Spring 并发事务的探究
    使用IDEA结合MAVEN创建一个Spring Java Web项目
    FutureTask与Fork/Join
    结合业务,精炼SQL
  • 原文地址:https://www.cnblogs.com/guoyansi19900907/p/5033644.html
Copyright © 2020-2023  润新知