黑马程序员技术交流社区

标题: 演示jsonp解决跨域访问问题的实现过程 [打印本页]

作者: 大山哥哥    时间: 2017-12-31 22:19
标题: 演示jsonp解决跨域访问问题的实现过程
本帖最后由 大山哥哥 于 2017-12-31 22:19 编辑

    在BOS2.0课程中,使用jQuery的ajax一步请求调用百度LBS云服务会出现跨域问题,解决方案是使用$.getJSON('LBS云服务请求路径&callback=?',function(json){})来完成请求发的发起和响应接收,本文通过几个简单的示例来说明JSONP的基本原理。
    我们在通过ajax异步请求跨域请求json数据都会出现跨域报错,但是通过<script>标签访问远程资源却不会出现跨域报错问题,那么,是否可以使用模拟标签请求方式将json数据从远程服务器上加载过来并提供给本地js代码使用?下面来做个演示:
    提前准备好一个web项目作为远程服务数据提供方,项目访问端口为9004,项目目录如下:


    准备其他项目作为客户端请求方(本文中我使用几个静态页面作为客户访问端)
    【演示一】使用<script>标签测试远程加载服务端car1目录下的js文件
    服务端blueCar.js的代码仅有一行:
[JavaScript] 纯文本查看 复制代码
alert("我是蓝色的车");

    客户端加载服务端js代码如下:
[HTML] 纯文本查看 复制代码
<html>
<head>
    <title>JSONP演示1-请首先启动bos_map_jsonp项目</title>
    <meta charset="utf-8" />
    <script type="text/javascript"
    src="http://localhost:9004/bos_map_jsonp/car1/blueCar.js"></script>
</head>
<body>
</body>
</html>

当在浏览器中打开该静态页面(直接访问页面路径 /bos_map/src/main/webapp/jsonP/jsonp_demo1.html)代码,会弹出窗口如下,
,也就是说,我们在客户端jsonp_demo1.html中通过script标签加载的远程服务端js代码被执行了,那么,可以想象,能否让远程服务端的js代码把json数据传过来呢?
    【演示二】利用json被js原生支持,从远程服务端加载json数据
我们先来看一下客户端代码:
[HTML] 纯文本查看 复制代码
<html >
<head>
    <title>jsonpdemo2</title>
    <meta charset="utf-8" />
    <script type="text/javascript">
            function myOwnFun(data){
                    alert("从jsonp项目请求的数据:" + data.id + "-" + data.value);
            }
    </script>
    <script type="text/javascript" src="http://localhost:9004/bos_map_jsonp/car2/redCar.js">
    </script>
</head>
<body>

</body>
</html>

在代码中,通过script标签加载远程服务器的redCar.js文件,在代码中还有一个JS函数,其中有一个data参数,下面我们来准备远程服务端的代码:
[JavaScript] 纯文本查看 复制代码
myOwnFun({"id":1,"value":"我是红色的车"})

直接在浏览器访问客户端页面,会发现,弹出了窗口并且能拿到远程服务端的数据
。这样,我们就可以通过script表现远程访问服务端的响应数据了,只需要远程服务器将函数名和数据拼接成字符串交给客户端的script标签加载即可
    【演示三】访问远程服务端的servlet
准备客户端代码如下:
[HTML] 纯文本查看 复制代码
<html >
<head>
    <title>jsonpdemo3</title>
    <meta charset="utf-8" />
    <script type="text/javascript">
            function myOwnFun(data){
                    alert("从jsonp项目请求的数据:" + data.id + "-" + data.value);
            }
    </script>
    <script type="text/javascript" src="http://localhost:9004/bos_map_jsonp/carInfo?callback=myOwnFun"></script>
</head>
<body>

</body>
</html>

观察代码,准备了一个函数,名为myOwnFun,同时向服务端发送了一个script标签的src路径,传递了一个参数callback,值为myOwnFun,与函数名同名。
在服务端准备servlet,只需要servlet能够将类似【演示二】中的数据返回给本次src请求即可。
服务端servlet处理如下:
[Java] 纯文本查看 复制代码
public class JsonpServlet extends HttpServlet{
        
        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp)
                        throws ServletException, IOException {
                String callback = req.getParameter("callback");
                String resultStr = callback + "({\"id\":2,\"value\":\"我是兰博基尼车\"})";
                //myOwnFun({id:2,value:我是兰博基尼})
                resp.setCharacterEncoding("utf-8");
                resp.getWriter().write(resultStr);
        }

}

在serlvet中,读取callback参数值,并拼接成字符串响应给请求,我们来看客户端页面访问效果:
,发现数据也被传递过来了

    【演示四】通过jQuery的jsonp请求方式请求数据。
客户端代码如下:
[HTML] 纯文本查看 复制代码
<html>
<head>
    <title>jsonpdemo2</title>
    <meta charset="utf-8" />
    <script type="text/javascript" src="../pickaddr/jquery.js"></script>
    <script type="text/javascript">
            //依旧请求demo3中的请求路径
            $.getJSON("http://localhost:9004/bos_map_jsonp/carInfo?callback=?",
                            {},
                            function(data){
                    alert(data.id + data.value);
            });
    </script>
</head>
<body>

</body>
</html>

观察页面请求效果:

和【演示三】一样,都可以获取远程服务端的数据。
其实,jQuery的 getJSON函数就是模仿【演示三】的效果,只不过在callback后的?会被jQuery自动替换为随机的函数名。
OK,jsonp的基本实现过程演示完毕。
代码可以参见附件。

projects.zip

195.22 KB, 下载次数: 32






欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2