jQuery中Ajax+Spring MVC实现跨域请求

          项目开发中,某个可独立、也可集成的子业务模块需要向外开放相关API接口,先说下项目本身使用了jersery来实现RESTful webservice以名词形式发布API。有意思的是在实际的操作中同事却通过Ajax跨域请求的方式去调用该API,先不说成功与否,这种方式本就是“滑稽"的,和他一起探讨了此种做法的不合理性,之后选择jersey client的方式进行远程调用。不过他在跨域请求中遇到了问题,自己闲暇时间予以解决,这才是此篇文章的由来。

       jQuery对跨域请求有两种解决方案分别是jQuery的jquery.ajax jsonp格式和jquery.getScript方式,而且这两种方式都只支持get方法。这里主要谈的是jsonp跨域的实现。

       json格式我们倒是经常使用,但是jsonp就不那么常用了,所以首先需要对jsonp要有一个了解。

JSONP解释

        在解释JSONP之前,我们需要了解下”同源策略“这个概念,这对理解跨域有帮助。基于安全的原因,浏览器是存在同源策略机制的,同源策略阻止从一个源加载的文档或脚本获取或设置另一个源加载额文档的属性。有点绕,说的简单点就是浏览器限制脚本只能和同协议、同域名、同端口的脚本进行交互

        JSONP就是为了解决这一问题的,JSONP是英文JSON  with Padding的缩写,是一个非官方的协议。他允许服务端生成script tags返回值客户端,通过javascript callback的形式来实现站点访问。JSONP是一种script tag的注入,将server返回的response添加到页面是实现特定功能。

        简而言之,JSONP本身不是复杂的东西,就是通过scirpt标签对javascript文档的动态解析绕过了浏览器的同源策略。

JSONP原理及实现

        接下来,来实际模拟一个跨域请求的解决方案。后端为Spring MVC架构的,前端则通过Ajax进行跨域访问。

         1、首先客户端需要注册一个callback(服务端通过该callback(jsonp)可以得到js函数名(jsonpCallback)),然后以JavaScript语

               法的方式,生成一个function

         2、接下来,将JSON数据直接以入参的方式,放置到function中,这样就生成了一段js语法文档,返回给客户端。

         3、最后客户端浏览器动态的解析script标签,并执行返回的JavaScript语法文档片段,此时数据作为参数传入到了预先定义好的

              回调函数里(动态执行回调函数)。

          这种动态解析js文档和eval函数是类似的。

          接下来就是如何实现了,客户端代码。

               $.ajax({
                    type: "get",
                    async: false,
                    url: "http://localhost:8080/buy/get",
                    dataType: "jsonp",
                    jsonp: "callbackparam", //服务端用于接收callback调用的function名的参数  
                    jsonpCallback: "success_jsonpCallback", //callback的function名称,服务端会把名称和data一起传递回来  
                    success: function(json) {
                        alert(json[0].name);
                    }
                });

         注解:jsonp会创建一个查询字符串参数callback=?,这个参数会加载请求的URL后面,服务端应当在JSON数据前加上回调函数

              名,以便完成一个JSONP请求。也就是说服务器端需要对返回的数据做处理,格式为如下形式:

jsonpCallback([{ name:"jhon"}])
          接下来看服务器端针对上述代码的处理:

        @RequestMapping("/get")
	public void get(HttpServletRequest req,HttpServletResponse res) {
		res.setContentType("text/plain");
		String callbackFunName =req.getParameter("callbackparam");//得到js函数名称
		try {
			res.getWriter().write(callbackFunName + "([ { name:\"John\"}])"); //返回jsonp数据
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

        前端Ajax跨域请求触发之后,能够有效的得到JSON数据,情况如下:

        至此,Ajax跨域请求也已经解决了,不过还是有两点地方需要注意:

        1、没有关于JSONP调用的错误处理,动态插入的脚本有效,则执行调用,无效就默默失败(无任何提示)。

        2、JSONP被不信任的服务使用会有一定的安全隐患,不信任的服务提供的脚本是恶意的。



郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。