django复习 以及源码

django请求生命周期

在浏览器上输入网址会发生什么事?
(地址会朝我对应的ip地址发送get请求,get请求遵循http协议)
先进入实现了wsgi协议的web服务器----》进入django---》中间件---》路由---》视图---》取模板,取数据,用数据渲染模板---》返回模板的字符串---》在浏览器上看到页面了
1 wsgi和cgi:通用网关协议
# 实现了wsgi协议的web服务器:uwsgi
# 对应到java中就是tomcat

最简单的Web应用就是先把HTML用文件保存好,用一个现成的HTTP服务器软件,接收用户请求,从文件中读取HTML,返回。javascript

若是要动态生成HTML,就须要把上述步骤本身来实现。不过,接受HTTP请求、解析HTTP请求、发送HTTP响应都是苦力活,若是咱们本身来写这些底层代码,还没开始写动态HTML呢,就得花个把月去读HTTP规范。php

正确的作法是底层代码由专门的服务器软件实现,咱们用Python专一于生成HTML文档。由于咱们不但愿接触到TCP链接、HTTP原始请求和响应格式,因此,须要一个统一的接口协议来实现这样的服务器软件,让咱们专心用Python编写Web业务。这个接口就是WSGI:Web Server Gateway Interface。而wsgiref模块就是python基于wsgi协议开发的服务模块。html

 1 from wsgiref.simple_server import make_server
 2 
 3 def mya(environ, start_response):
 4     print(environ)
 5     start_response('200 OK', [('Content-Type', 'text/html')])
 6     if environ.get('PATH_INFO') == '/index':
 7         with open('index.html','rb') as f:
 8             data=f.read()
 9 
10     elif environ.get('PATH_INFO') == '/login':
11         with open('login.html', 'rb') as f:
12             data = f.read()
13     else:
14         data=b'<h1>Hello, web!</h1>'
15     return [data]
16 
17 if __name__ == '__main__':
18     myserver = make_server('', 8011, mya)
19     print('监听8010')
20     myserver.serve_forever()

整个django框架就至关于def mya这个函数,只不过diango不是用函数,是用类包装起来。前端

对象加()调用是__call__的方法,__call__里面有这两个参数(environ, start_response),只要遵循这个http协议就会有这两个参数。wsgi就是将http请求拆开了,拆成python当中可以识别的变量,http直接来,能读出来就是字符串,可是还要作相应的处理,因此协议规定按照什么格式拆,拆到哪里,就是将数据当成字典拆到environ里面去,无论请求方式,请求头部等等而后再传到后面的可调用对象里面去,而后django就把这个东西包装成了对象request,因此request能够点http里的数据点出来。java

开发模式

#  开发模式(先后端分离和先后端不分离)
# -先后端不分离项目(后端渲染页面)
# -先后端分离项目
# -前端和后端经过json格式数据交互(不须要写模板语言)请求页面用ajax发请求,先后端只作json数据的交互,json数据拿回来的时候就用dom来渲染个人页面,前端拿到数据,页面前端本身渲染
前端能够是前端,后台,移动端和微信小程序
http://www.javashuo.com/article/p-ppeoyntg-ek.html

cbv源码分析

-FBV和CBV
# -执行流程:
# -路由若是这么配置:url(r'^test/', views.Test.as_view()),
# 请求经过中间件后进入路由--->根据路由匹配,一旦成功,会执行后面函数(request)---》本质就是执行了as_view内部的view函数----》内部又调用了self.dispatch---->根据请求方式,执行不一样的方法(必然get请求,就会执行咱么写的视图类的get方法)
# -尝试本身封装一个APIView,重写dispatch方法,在执行父类的dispatch以前,写一些逻辑,请求来了,就会执行这些逻辑
url()其实就是一个函数,views.Test.as_view()就是函数地址加括号,而且把request传进去,
#  python中一切皆对象
# def test():
# print('xxxx')
# test.name='lqz'
# print(test.name)

restful规范(importment,interview)

一 什么是RESTful

  • REST与技术无关,表明的是一种软件架构风格,REST是Representational State Transfer的简称,中文翻译为“表征状态转移”
  • REST从资源的角度类审视整个网络,它将分布在网络中某个节点的资源经过URL进行标识,客户端应用经过URL来获取资源的表征,得到这些表征导致这些应用转变状态
  • REST与技术无关,表明的是一种软件架构风格,REST是Representational State Transfer的简称,中文翻译为“表征状态转移”
  • 全部的数据,不过是经过网络获取的仍是操做(增删改查)的数据,都是资源,将一切数据视为资源是REST区别与其余架构风格的最本质属性
  • 对于REST这种面向资源的架构风格,有人提出一种全新的结构理念,即:面向资源架构(ROA:Resource Oriented Architecture)
  • 资源就是实实存在的东西,如从动物园中新增一头动物,杀死一头动物    -10条
#     -1 API与用户的通讯协议,老是使用HTTPs协议。(http不安全,数据被截断,数据就会所有展现出来)
# -2 域名有区分
      (dtl是模板语言,可使用python等进行模板渲染再返回给前端)
      (后台管理并无作先后端分离,用的就是dtl,而不是前端渲染)
# -https://api.example.com   尽可能将API部署在专用域名(会存在跨域问题)
# -https://example.org/api/ 访问api表明就是访问路由接口
# -3 版本
      (就是如微博开一个接口,而后我写一个app去访问这个接口,须要传入两个参数,返回一个参数,而后后期微博数据须要改动,
       变成了一个接口须要传入三个参数,返回两个参数,不可能去改变个人app,只能再更新一个微博版本,开一个新的接口,
      而后app去链接一个新的接口,这期间就会有缓冲的过程)
# -能够放在路径中 URL 如:https://api.example.com/v1/
#        -能够放在请求头中  跨域时,引起发送屡次请求
# -4 路径,视网络上任何东西都是资源,均使用名词表示(重点)
# -https://api.example.com/v1/zoos
# -5 经过method 区分是什么操做
# -get表示获取
# -post表示新增
# -delete表示删除
# -patch/put 表示修改
# -6 过滤,经过在url上传参的形式传递搜索条件
      
  • https://api.example.com/v1/zoos?limit=10:指定返回记录的数量
  • https://api.example.com/v1/zoos?offset=10:指定返回记录的开始位置
  • https://api.example.com/v1/zoos?page=2&per_page=100:指定第几页,以及每页的记录数
  • https://api.example.com/v1/zoos?sortby=name&order=asc:指定返回结果按照哪一个属性排序,以及排序顺序
  • https://api.example.com/v1/zoos?animal_type_id=1:指定筛选条件

# -7 状态码
# {"status_code":100}
200 OK - [GET]:服务器成功返回用户请求的数据,该操做是幂等的(Idempotent)。
201 CREATED - [POST/PUT/PATCH]:用户新建或修改数据成功。
202 Accepted - [*]:表示一个请求已经进入后台排队(异步任务)
204 NO CONTENT - [DELETE]:用户删除数据成功。
400 INVALID REQUEST - [POST/PUT/PATCH]:用户发出的请求有错误,服务器没有进行新建或修改数据的操做,该操做是幂等的。
401 Unauthorized - [*]:表示用户没有权限(令牌、用户名、密码错误)。
403 Forbidden - [*] 表示用户获得受权(与401错误相对),可是访问是被禁止的。
404 NOT FOUND - [*]:用户发出的请求针对的是不存在的记录,服务器没有进行操做,该操做是幂等的。
406 Not Acceptable - [GET]:用户请求的格式不可得(好比用户请求JSON格式,可是只有XML格式)。
410 Gone -[GET]:用户请求的资源被永久删除,且不会再获得的。
422 Unprocesable entity - [POST/PUT/PATCH] 当建立一个对象时,发生一个验证错误。
500 INTERNAL SERVER ERROR - [*]:服务器发生错误,用户将没法判断发出的请求是否成功。

更多看这里:http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html

# -8 错误处理,应返回错误信息
# {"status_code":100,'msg':'登陆成功'}
# {"status_code":101,'msg':'用户名错误'}
# -9 返回结果,针对不一样操做,服务器向用户返回的结果
# -get获取全部资源/get获取一个资源
# -127.0.0.1/api/vi/books 获取全部图书
# {"status_code":100,'msg':'获取成功',data:[{},{}]}
# -127.0.0.1/api/vi/books/3 获取id为3的图书
# {"status_code":100,'msg':'获取成功',data:{name:xx,....}}
# -新增数据,把新增的数据再返回
# -修改了数据,返回完整的资源对象
# -删除数据,返回一个空文档
    • 错误处理,应返回错误信息,error当作key。
      1
      2
      3
      {
           error:  "Invalid API key"
      }
    • 返回结果,针对不一样操做,服务器向用户返回的结果应该符合如下规范。
      1
      2
      3
      4
      5
      6
      GET  / collection:返回资源对象的列表(数组)
      GET  / collection / resource:返回单个资源对象
      POST  / collection:返回新生成的资源对象
      PUT  / collection / resource:返回完整的资源对象
      PATCH  / collection / resource:返回完整的资源对象
      DELETE  / collection / resource:返回一个空文档

#
# -10 返回结果中提供连接
Hypermedia API,RESTful API最好作到Hypermedia,即返回结果中提供连接,连向其余API方法,使得用户不查文档,也知道下一步应该作什么。
1
2
3
4
5
6
{ "link" : {
   "rel" :    "collection https://www.example.com/zoos" ,
   "href" :   "https://api.example.com/zoos" ,
   "title" "List of zoos" ,
   "type" :   "application/vnd.yourformat+json"
}}

django编写restful接口

#  DG软件
# -pycharm开发
# -idea
# -goland
# -AndroidStadio
不一样程序能够用同一个数据库
views.py
from django.shortcuts import render
from django.http import JsonResponse
# Create your views here.
from app01 import models
def Book(request):
    #获取全部的图书
    if request.method == 'GET':
        books = models.Book.objects.all()
        #把queryset对象转成json格式的字符串
        # li = []
        # for book in books:
        #     bo = {'name':book.name,'publish':book.publish}
        #     li.append(bo)
        #列表推导式
        li=[{'name':book.name,'publish':book.publish} for book in books ]

        response = {'code':100,'msg':'查询成功','data':li}
        #safe=False 若是序列化的对象中有列表,须要设置
        return JsonResponse(response ,safe=False,json_dumps_params={'ensure_ascii':False})

models.py
from
django.db import models # Create your models here. class Book(models.Model): id = models.AutoField(primary_key=True) name = models.CharField(max_length=32) publish = models.CharField(max_length=32)

 1    def __init__(self, data, encoder=DjangoJSONEncoder, safe=True,
 2                  json_dumps_params=None, **kwargs):
 3         if safe and not isinstance(data, dict):
 4             raise TypeError(
 5                 'In order to allow non-dict objects to be serialized set the '
 6                 'safe parameter to False.'
 7             )
 8         if json_dumps_params is None:
 9             json_dumps_params = {}
10         kwargs.setdefault('content_type', 'application/json')
11         data = json.dumps(data, cls=encoder, **json_dumps_params)
12         super(JsonResponse, self).__init__(content=data, **kwargs)
源码

APIView源码简单分析

# 6 drf:APIView 的源码,Requset的源码
# -安装:
# -pip3 install djangorestframework
# -pycharm中安装
# -使用
# -第一步,再写视图,都写cbv
# from rest_framework.views import APIView
# class Books(APIView):
# pass
# -在setting中配置
# INSTALLED_APPS= [
# 。。。。。
# 'rest_framework'
# ]
#
# -源码分析:
# 继承了APIView 以后:
# -1 全部的请求都没有csrf的认证了
# -2 在APIView中as_view本质仍是调用了父类的as_view(View的as_view)
# -3 as_view中调用dispatch -----》这个dispatch是APIView的dispatch
    @classmethod
    def as_view(cls, **initkwargs):
        """
        Store the original class on the view function.

        This allows us to discover information about the view when we do URL
        reverse lookups.  Used for breadcrumb generation.
        """
        if isinstance(getattr(cls, 'queryset', None), models.query.QuerySet):
            def force_evaluation():
                raise RuntimeError(
                    'Do not evaluate the `.queryset` attribute directly, '
                    'as the result will be cached and reused between requests. '
                    'Use `.all()` or call `.get_queryset()` instead.'
                )
            cls.queryset._fetch_all = force_evaluation

        view = super(APIView, cls).as_view(**initkwargs)
        view.cls = cls
        view.initkwargs = initkwargs

        # Note: session based authentication is explicitly CSRF validated,
        # all other authentication is CSRF exempt.
        return csrf_exempt(view)
源码
def csrf_exempt(view_func):
    """
    Marks a view function as being exempt from the CSRF view protection.
    """
    # We could just do view_func.csrf_exempt = True, but decorators
    # are nicer if they don't have side-effects, so we return a new
    # function.
    def wrapped_view(*args, **kwargs):
        return view_func(*args, **kwargs)
    wrapped_view.csrf_exempt = True
    return wraps(view_func, assigned=available_attrs(view_func))(wrapped_view)
源码
class View(object):
    """
    Intentionally simple parent class for all views. Only implements
    dispatch-by-method and simple sanity checking.
    """

    http_method_names = ['get', 'post', 'put', 'patch', 'delete', 'head', 'options', 'trace']

    def __init__(self, **kwargs):
        """
        Constructor. Called in the URLconf; can contain helpful extra
        keyword arguments, and other things.
        """
        # Go through keyword arguments, and either save their values to our
        # instance, or raise an error.
        for key, value in six.iteritems(kwargs):
            setattr(self, key, value)

    @classonlymethod
    def as_view(cls, **initkwargs):
        """
        Main entry point for a request-response process.
        """
        for key in initkwargs:
            if key in cls.http_method_names:
                raise TypeError("You tried to pass in the %s method name as a "
                                "keyword argument to %s(). Don't do that."
                                % (key, cls.__name__))
            if not hasattr(cls, key):
                raise TypeError("%s() received an invalid keyword %r. as_view "
                                "only accepts arguments that are already "
                                "attributes of the class." % (cls.__name__, key))

        def view(request, *args, **kwargs):
            self = cls(**initkwargs)
            if hasattr(self, 'get') and not hasattr(self, 'head'):
                self.head = self.get
            self.request = request
            self.args = args
            self.kwargs = kwargs
            return self.dispatch(request, *args, **kwargs)
        view.view_class = cls
        view.view_initkwargs = initkwargs

        # take name and docstring from class
        update_wrapper(view, cls, updated=())

        # and possible attributes set by decorators
        # like csrf_exempt from dispatch
        update_wrapper(view, cls.dispatch, assigned=())
        return view
源码

APIView的dispatch方法和request类分析

    -APIVIew的dispatch方法:
# -1 对原生request对象作了一层包装(面向对象的封装),之后再用的request对象都新的request对象
# -2 在APIView中self.initial(request, *args, **kwargs),里面有频率控制,权限控制和认证相关
# -3 根据请求方法执行我们写的视图类中的相应方法
# --视图类中方法的request对象,已经变成了封装后的request
# -Request类:
# -1 原生的request是self._request
# -2 取以post形式提交的数据,从request.data中取(urlencoded,formdata,json格式)
# -3 query_params 就是原生request的GET的数据
# -4 上传的文件是从FILES中取
# -5 (重点)其余的属性,直接request.属性名(由于重写了__getattr__方法)

postman的安装和使用

美化jason的格式python

-Django的请求生命周期
-CBV源码分析
-类名.as_view()---->执行结果返回内存地址---》内存函数view的内存地址---》请求路径跟路由匹配成,会调用view(request)
view()内部调用了self.disaptch---->根据请求不一样,执行不一样的方法

-restful规范:
-10
-1 路径中资源都名词,能够用复数
-2 经过请求方式来执行不一样操做
-3 返回状态码
-4 返回错误信息
-5 返回的数据中带连接
-用原生django写restful的接口
-drf
-使用:
-1 在setting.py 中把rest_framework加入到app中
-2 之后再写全写CBV,继承APIView
-源码分析:
-APIView:重写了dispatch方法:1 包装request 2 加入了一些校验
-Request对象:重写了__getattr__ query_params FILES request.data

 

 

图书的增删查改接口
# -登陆以后才能操做修改,新增,删除接口
from django.db import models

# Create your models here.
class Book(models.Model):
    nid = models.AutoField(primary_key=True)
    name = models.CharField(max_length=32)
    price = models.DecimalField(max_digits=5, decimal_places=2)
    publish_date = models.DateField()
    # 阅读数
    # reat_num=models.IntegerField(default=0)
    # 评论数
    # commit_num=models.IntegerField(default=0)

    publish = models.ForeignKey(to='Publish',to_field='nid',on_delete=models.CASCADE)
    authors=models.ManyToManyField(to='Author')
    def __str__(self):
        return self.name


class Author(models.Model):
    nid = models.AutoField(primary_key=True)
    name = models.CharField(max_length=32)
    age = models.IntegerField()
    author_detail = models.OneToOneField(to='AuthorDatail',to_field='nid',unique=True,on_delete=models.CASCADE)


class AuthorDatail(models.Model):
    nid = models.AutoField(primary_key=True)
    telephone = models.BigIntegerField()
    birthday = models.DateField()
    addr = models.CharField(max_length=64)


class Publish(models.Model):
    nid = models.AutoField(primary_key=True)
    name = models.CharField(max_length=32)
    city = models.CharField(max_length=32)
    email = models.EmailField()
models.py
from rest_framework import serializers
from app01 import models
class BookSerializer(serializers.ModelSerializer):
    class Meta:
        model=models.Book
        fields='__all__'
        # depth=1
myserializer.py
from django.shortcuts import render

# Create your views here.
class Get():
    def get(self,request,*args,**kwargs):
        response = {'code': 100, 'msg': '查询成功'}
        ret=self.models_object
        book_ser=self.ser(instance=ret,many=True)
        response['data']=book_ser.data
        return Response(response)

from app01 import models
from app01.MySer import BookSerializer
from rest_framework.views import  APIView
from rest_framework.response import  Response
class Books(APIView,Get):
    models_object=models.Book.objects.all()
    ser=BookSerializer

    def post(self,request,*args,**kwargs):
        print(request.data)
        print(type(request.data))
        response={'code': 100, 'msg': '新增成功'}
        book_ser=BookSerializer(data=request.data)
        if book_ser.is_valid():
            book_ser.save()
        else:
            response['code']=101
            response['msg']=book_ser.errors

        return Response(response)

class BookDetail(APIView):
    def get(self,request,id):
        response = {'code': 100, 'msg': '查询成功'}
        ret=models.Book.objects.filter(pk=id).first()
        book_ser=BookSerializer(instance=ret,many=False)
        response['data']=book_ser.data
        return Response(response)
    def put(self,request,id):
        response = {'code': 100, 'msg': '修改为功'}
        ret=models.Book.objects.filter(pk=id).first()
        book_ser=BookSerializer(instance=ret,data=request.data)
        if book_ser.is_valid():
            book_ser.save()
        else:
            response['code'] = 101
            response['msg'] = book_ser.errors
        return Response(response)

    def delete(self, request, id):
        response = {'code': 100, 'msg': '删除成功'}
        models.Book.objects.filter(pk=id).delete()

        return Response(response)


class Publish(APIView,Get):
    models_object=models.Publish.objects.all()
    ser=BookSerializer
views.py
from django.conf.urls import url
from django.contrib import admin
from app01 import views
urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^books/$', views.Books.as_view()),
    url(r'^books/(?P<id>\d+)$', views.BookDetail.as_view()),

]
urls.py
INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'app01.apps.App01Config',
    'rest_framework'
]
settings.py
301和302的区别

302重定向只是暂时的重定向,搜索引擎会抓取新的内容而保留旧的地址,由于服务器返回302,因此,搜索搜索引擎认为新的网址是暂时的。git

  而301重定向是永久的重定向,搜索引擎在抓取新的内容的同时也将旧的网址替换为了重定向以后的网址web

 

定义以下:ajax

301 Moved Permanently 被请求的资源已永久移动到新位置,而且未来任何对此资源的引用都应该使用本响应返回的若干个URI之一。若是可能,拥有连接编辑功能的客户端应当自动把请求的地址修改成从服务器反馈回来的地址。除非额外指定,不然这个响应也是可缓存的。数据库


302 Found 请求的资源如今临时从不一样的URI响应请求。因为这样的重定向是临时的,客户端应当继续向原有地址发送之后的请求。只有在Cache-Control或Expires中进行了指定的状况下,这个响应才是可缓存的。

字面上的区别就是301是永久重定向,而302是临时重定向。 固然,他们之间也是有共同点的,就是用户均可以看到url替换为了一个新的,而后发出请求。

 

 

301适合永久重定向

  301比较经常使用的场景是使用域名跳转。

  好比,咱们访问 http://www.baidu.com 会跳转到 https://www.baidu.com,发送请求以后,就会返回301状态码,而后返回一个location,提示新的地址,浏览器就会拿着这个新的地址去访问。 

  注意: 301请求是能够缓存的, 即经过看status code,能够发现后面写着from cache。

     或者你把你的网页的名称从php修改成了html,这个过程当中,也会发生永久重定向。

 

 

302用来作临时跳转

  好比未登录的用户访问用户中心重定向到登陆页面。

  访问404页面会从新定向到首页。 

##niginx 301/302配置

rewrite后面接上permenent就表明301跳

//把来自veryyoung.me的请求301跳到 www.veryyoung.me
if ($host != 'veryyoung.me') {
    rewrite ^/(.*)$ http://www.veryyoung.me/$1 permanent;
}

 

接上redirect就表明302跳

//把来自veryyoung.me的请求302跳到 www.veryyoung.me
if ($host != 'veryyoung.me') {
    rewrite ^/(.*)$ http://www.veryyoung.me/$1 redirect;
}

 跨域

1、为何会出现跨域问题
出于浏览器的同源策略限制。同源策略(Sameoriginpolicy)是一种约定,它是浏览器最核心也最基本的安全功能,若是缺乏了同源策略,则浏览器的正常功能可能都会受到影响。能够说Web是构建在同源策略基础之上的,浏览器只是针对同源策略的一种实现。同源策略会阻止一个域的javascript脚本和另一个域的内容进行交互。所谓同源(即指在同一个域)就是两个页面具备相同的协议(protocol),主机(host)和端口号(port)

2、什么是跨域
当一个请求url的协议、域名、端口三者之间任意一个与当前页面url不一样即为跨域

当前页面url                                  被请求页面url                                  是否跨域          缘由
http://www.test.com/                    http://www.test.com/index.html        否                     同源(协议、域名、端口号相同)
http://www.test.com/                    https://www.test.com/index.html      跨域                  协议不一样(http/https)
http://www.test.com/                    http://www.baidu.com/                     跨域                  主域名不一样(test/baidu)
http://www.test.com/                    http://blog.test.com/                         跨域                  子域名不一样(www/blog)
http://www.test.com:8080/           http://www.test.com:7001/               跨域                  端口号不一样(8080/7001)
3、非同源限制
【1】没法读取非同源网页的 Cookie、LocalStorage 和 IndexedDB

【2】没法接触非同源网页的 DOM

【3】没法向非同源地址发送 AJAX 请求

4、跨域解决方法
【1】设置document.domain解决没法读取非同源网页的 Cookie问题

由于浏览器是经过document.domain属性来检查两个页面是否同源,所以只要经过设置相同的document.domain,两个页面就能够共享Cookie

// 两个页面都设置
document.domain = 'test.com';

【2】跨文档通讯 API:window.postMessage()

调用postMessage方法实现父窗口http://test1.com向子窗口http://test2.com发消息(子窗口一样能够经过该方法发送消息给父窗口)

// 父窗口打开一个子窗口
var openWindow = window.open('http://test2.com', 'title');

// 父窗口向子窗口发消息(第一个参数表明发送的内容,第二个参数表明接收消息窗口的url)
openWindow.postMessage('Nice to meet you!', 'http://test2.com');

调用message事件,监听对方发送的消息

// 监听 message 消息
window.addEventListener('message', function (e) {
console.log(e.source); // e.source 发送消息的窗口
console.log(e.origin); // e.origin 消息发向的网址
console.log(e.data); // e.data 发送的消息
},false);

【3】JSONP

JSONP 是服务器与客户端跨源通讯的经常使用方法。最大特色就是简单适用,兼容性好(兼容低版本IE),缺点是只支持get请求,不支持post请求。

核心思想:网页经过添加一个<script>元素,向服务器请求 JSON 数据,服务器收到请求后,将数据放在一个指定名字的回调函数的参数位置传回来。

<script src="http://test.com/data.php?callback=dosomething"></script>
// 向服务器test.com发出请求,该请求的查询字符串有一个callback参数,用来指定回调函数的名字

// 处理服务器返回回调函数的数据
<script type="text/javascript">
function dosomething(data){
//处理得到的数据
}
</script>

【4】CORS

CORS 是跨域资源分享(Cross-Origin Resource Sharing)的缩写。它是 W3C 标准,属于跨源 AJAX 请求的根本解决方法。

1.前端代码(须要判断浏览器是否支持状况)

function createCORSRequest(method, url) {
var xhr = new XMLHttpRequest();
if ("withCredentials" in xhr) {

// 此时即支持CORS的状况
// 检查XMLHttpRequest对象是否有“withCredentials”属性
// “withCredentials”仅存在于XMLHTTPRequest2对象里
xhr.open(method, url, true);

} else if (typeof!= "undefined") {

// 不然检查是否支持XDomainRequest,IE8和IE9支持
// XDomainRequest仅存在于IE中,是IE用于支持CORS请求的方式
xhr = new XDomainRequest();
xhr.open(method, url);

} else {

// 不然,浏览器不支持CORS
xhr = null;

}
return xhr;
}

var xhr = createCORSRequest('GET', url);
if (!xhr) {
throw new Error('CORS not supported');
}

 


2.服务器

服务器端对于CORS的支持,主要是经过设置Access-Control-Allow-Origin来进行的。若是浏览器检测到相应的设置,就能够容许Ajax进行跨域的访问。咱们主要介绍Apache和PHP里的设置方法

Apache须要使用mod_headers模块来激活HTTP头的设置,它默认是激活的。你只须要在Apache配置文件的<Directory>, <Location>, <Files>或<VirtualHost>的配置里加入如下内容便可

Header set Access-Control-Allow-Origin *

 

PHP使用以下代码设置便可

<?php
header("Access-Control-Allow-Origin:*")
相关文章
相关标签/搜索