• JQ之$.ajax()方法以及ajax跨域请求


    AJAX(Asynchronous javascript AND xml :异步javascript和xml):是一种创建交互式网页应用的网页开发技术。AJAX可以在不重新加载整个页面的情况下与服务器进行交互。

    AJAX的应用范围:

      登录失败不跳转页面

      注册时验证用户是否存在

      图片服务器进行延时加载

      多页数据进行翻页

      自动制新页面等。

    AJAX的写法:

     1 $.ajax({
     2    url:"请求地址",
     3    type:"请求方式" 4    data:"请求数据" 5    dataType:"服务器响应的数据类型",
     6    success:function(msg){
     7         //请求成功要做的事,msg:服务器响应的数据    
     8      },请求成功后的回调函数 
     9    error:function(XMLHttpRequest,textStatus,errorThrown){
    10            
    11      } 请求失败或者超时的回调函数            
    12 })

       这里是一个最简单的ajax请求,其中包括的参数还有很多,见下表:

    参数 值/描述
    url 发送请求的地址,一般为string类型
    type 请求的方式,值一般为:get/post
    async 设置请求为异步还是同步请求,值:true(默认):异步请求、false:同步请求
    data 需要向服务器发送的请求数据,值要以key/value的格式,如{name:"123",pwss:"123"}如果请求方式为get,会将数据连接到url上
    datatype 服务器返回过来的数据类型是以什么格式返回的,值:xml、html、script、json、jsonp,text
    timeout 设置本地请求超时时间,单位:毫秒。此设置将覆盖$.ajaxSetup()方法的全局设置。
    cache 表示浏览器是否缓存请求的页面,默认值为true
    beforeSend 请求发送前要执行的函数。要求为Function类型的参数
    complete 请求完成后要执行的函数。在success和error执行完后执行。参数也为Function
    success 请求成功后所执行的回调函数。第一个参数为:服务器响应的dataType类型的数据,第二个参数是描述状态的字符串,第三个为XMLHttpRequest对象
    error 请求失败后所执行的回调函数。第一个参数为XMLHttpRequest对象,第二个为描述状态的字符,每三个为error异常
    contentType 发送数据到服务器时所使用的内容类型。默认是:"application/x-www-form-urlencoded"。
    dataFilter 用于处理 XMLHttpRequest 原始响应数据的函数。
    username 要求为String类型的参数,用于响应HTTP访问认证请求的用户名。
    password 要求为String类型的参数,用于响应HTTP访问认证请求的密码。
    global 表示是否触发全局ajax事件。设置为false将不会触发全局ajax事件,ajaxStart或ajaxStop可用于控制各种ajax事件。
    ifModified 仅在服务器数据改变时获取新数据。服务器数据改变判断的依据是Last-Modified头信息。默认值是false。
    jsonp 在一个jsonp请求中重写回调函数的名字。该值用来替代在"callback=?"这种GET或POST请求中URL参数里的"callback"部分,例如{jsonp:'onJsonPLoad'}会导致将"onJsonPLoad=?"传给服务器。
    processData 默认为true,发送的数据将被转换为对象(从技术角度来讲并非字符串)以配合默认内容类型"application/x-www-form-urlencoded"。如果要发送DOM树信息或者其他不希望转换的信息,请设置为false。
    scriptCharset 只有当请求时dataType为"jsonp"或者"script",并且type是GET时才会用于强制修改字符集(charset)。通常在本地和远程的内容编码不同时使用。

      

    AJAX跨域请求

      //注:转载自https://blog.csdn.net/csdn_ds/article/details/73691134

      以上的方法对于AJAX来说只能在同下个域名下进行请求访问,如果我们需要跨域请求要怎么做呢?

      如果AJAX出现跨域请求,浏览器就会报:XMLHttpRequest cannot load http://目标地址No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://当前页面地址' is therefore not allowed access. 错误

      为什么会出现跨域问题

        跨域,指的是浏览器不能执行其他网站的脚本。它是由浏览器的同源策略造成的,是浏览器对JavaScript施加的安全限制。

        在此说明一下,所谓的同源,指的是域名、协议、端口均相等。举例如下:

        http://www.abc.com/a/b 调用 http://www.abc.com/d/c(非跨域)

        http://www.abc.com/a/b 调用 http://www.def.com/d/c (跨域:域名不一致)

        http://www.abc.com:81/a/b 调用 http://www.abc.com:82/d/c (跨域:端口不一致)

        http://www.abc.com/a/b 调用 https://www.abc.com/d/c (跨域:协议不同)

        请注意:localhost和127.0.0.1虽然都指向本机,但也属于跨域。

      解决跨域问题有以下三种方法:

        1、使用jsonp

        2、服务器代理

        3、在服务端设置response header中Access-Control-Allow-Origin字段。

      1、使用jsonp

        jsonp解决跨域问题的原理是,浏览器的script标签是不受同源策略限制的,我们可以在script标签中访问任何域名下的资源文件。利用这一特性,用script标签从服务器中请求数据,同时服务器返回一个带有方法和数据的js代码,请求完成,调用本地的js方法,来完成数据的处理。

    前端实现,以Jquery的ajax方法为例:

     1 $.ajax({  
     2         url:"",  
     3         dataType:'jsonp',  
     4         data:'',  
     5         jsonp:'callback',  //传递给请求处理程序或页面的,用以获得jsonp回调函数名的参数名(默认为:callback)
     6  
     7         success:function(result) {  
     8             //成功的处理
     9         },
    10         error:function(){
    11             //错误处理
    12 } 
    13 });  

    服务端此时返回的不能是普通的json字符串,而是一段可以被前端js执行的一段js代码。

    比较一下json与jsonp格式的区别:

    json格式:

    1 {
    2     "message":"获取成功",
    3     "state":"1",
    4     "result":{"name":"工作组1","id":1,"description":"11"}
    5 }

    jsonp格式:

    1 callback({
    2     "message":"获取成功",
    3     "state":"1",
    4     "result":{"name":"工作组1","id":1,"description":"11"}
    5 })

    从格式来看,jsonp是在json的基础上包装了一个方法名,此方法名是前端请求传过来的,如请求地址为:http://localhost:9999/tookApp/tbk/getItem?callback=JSONP_CALLBACK,那么方法名就是JSONP_CALLBACK。

    下面提供一段java代码,对象转jsonp的工具类:

     1 package com.tooklili.app.web.util;
     2  
     3 import javax.servlet.http.HttpServletRequest;
     4  
     5 import org.apache.commons.lang.StringUtils;
     6 import org.springframework.web.context.request.RequestContextHolder;
     7 import org.springframework.web.context.request.ServletRequestAttributes;
     8  
     9 import com.fasterxml.jackson.databind.util.JSONPObject;
    10  
    11 /**
    12  * 
    13  * @author ding.shuai
    14  * @date 2016年8月15日上午9:47:02
    15  */
    16 public class AppUtil {
    17     
    18     /**
    19      * 判断json字符串是否需要转化成jsonp格式
    20      * @param request
    21      * @param result
    22      * @return
    23      */
    24     public static Object conversionJsonp(Object result){
    25         HttpServletRequest request = ((ServletRequestAttributes)RequestContextHolder.getRequestAttributes()).getRequest();
    26         return conversionJsonp(request, result);
    27     }
    28     
    29  
    30     public static Object conversionJsonp(HttpServletRequest request,Object result){
    31         String callback = request.getParameter("callback");
    32         if(StringUtils.isNotEmpty(callback)){
    33             return new JSONPObject(callback, result);
    34         }
    35         return result;
    36     }
    37 }

    jsonp的缺点:

    1、JSONP是一种非官方的方法,而且这种方法只支持GET方法,不如POST方法安全。(从实现机制就可明白)。

    2、JSONP的实现需要服务器配合,如果是访问的是第三方的服务器,我们没有修改服务器的权限,那么这种方式是不可行的。

    2、服务器代理

    这种方式运用的就是服务器的反向代理技术,控制客户端和服务器的访问都从代理服务器经过,比如用nginx作为服务器代理,在nginx上配置客户端和第三方服务的反向代理,这样就可保证客户端、第三方是同源的了,同一个源,都来自代理服务器。

    关于nginx的反向代理配置,可访问我的这篇博客:http://blog.csdn.net/csdn_ds/article/details/58605591

    服务器代理的缺点:

    开发比较麻烦,对开发环境比较严格,需要在本机上配置代理服务器。

    优点:

    完美解决使用jsonp,第三方服务没有修改权限的问题。程序的代码侵入性小,代码级别不需要考虑跨域问题。

    3、在服务端设置response header中Access-Control-Allow-Origin字段

    在被请求的Response Header中加入如下代码:

    如果所有请求都想让其他域名的服务通过浏览器ajax请求到,可以通过Filter统一设置response header。

     1 package com.tooklili.app.web.filter;
     2  
     3 import java.io.IOException;
     4  
     5 import javax.servlet.Filter;
     6 import javax.servlet.FilterChain;
     7 import javax.servlet.FilterConfig;
     8 import javax.servlet.ServletException;
     9 import javax.servlet.ServletRequest;
    10 import javax.servlet.ServletResponse;
    11 import javax.servlet.http.HttpServletResponse;
    12  
    13 /**
    14  * 设置公共属性的过滤器
    15  * @author shuai.ding
    16  *
    17  * @date 2017年6月21日上午11:02:27
    18  */
    19 public class CommonSetFilter implements Filter{
    20  
    21     @Override
    22     public void init(FilterConfig filterConfig) throws ServletException {        
    23     }
    24  
    25     @Override
    26     public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
    27             throws IOException, ServletException {
    28         //解决跨域问题
    29         HttpServletResponse httpServletResponse =(HttpServletResponse)response;
    30         // 指定允许其他域名访问 
    31         httpServletResponse.setHeader("Access-Control-Allow-Origin", "*");
    32         // 响应类型 
    33         httpServletResponse.setHeader("Access-Control-Allow-Methods", "POST");
    34         // 响应头设置 
    35         httpServletResponse.setHeader("Access-Control-Allow-Headers", "x-requested-with,content-type");
    36         
    37         chain.doFilter(request, response);
    38     }
    39  
    40     @Override
    41     public void destroy() {    
    42     }
    43  
    44 }

    此处说明一下,笔者亲测:只设置Access-Control-Allow-Origin属性也是可以的。

    Access-Control-Allow-Origin:* 表示允许任何域名跨域访问

    如果需要指定某域名才允许跨域访问,只需把Access-Control-Allow-Origin:*改为Access-Control-Allow-Origin:允许的域名

    例如:response.setHeader(“Access-Control-Allow-Origin”,”http://www.client.com”);

    缺点:

    1、此种解决跨域方案,需要浏览器支持H5,因为这是HTML5解决跨域的方式,如果产品面向的是PC端,这种方式可能就不是一个好的解决方案,如果面向的是手机端,此方法不为一个简单、粗暴的好方式。

    2、设置*,存在安全隐患。

    4、总结

    综上三种解决跨域的方案,个人感觉使用服务代理最好,没有破坏浏览器的安全策略,但这个对开发环境要高一点。设置response header的方式,根据具体情况分析,要考虑清楚产品面向的用户。对于jsonp这种方式,虽然没有破坏浏览器的安全策略,但只支持get方式的请求,有点不能接受,因为get传输有参数长度的限制,同时又要考虑传输中文的乱码问题,但如果项目中只是简单的查询、展示,这种方式还是可以考虑的。

    其他好文推荐

    Access-Control-Allow-Origin 跨域设置多域名:http://www.jianshu.com/p/b587dd1b7086

  • 相关阅读:
    VMware克隆虚拟机
    3种Redis分布式锁的对比
    高并发下缓存与数据库双写不一致解决方案
    30分钟Maven入门到精通
    Linux安装rabbitmq (解决guest无法登陆问题)
    RocketMQ高性能原理(pushConsumer,CommitLog,ZeroCopy)
    XA 分布式事务原理(转)
    SpringBoot学习(八)RestTemplate/WebClient 调用REST服务、Validation校验和发邮件
    @Valid和@Validated的总结区分(转)
    Dubbo 同步调用原理(转)
  • 原文地址:https://www.cnblogs.com/EmilZs/p/9305577.html
Copyright © 2020-2023  润新知