SpringMVC(四)应用掌握

141 阅读21分钟

返回值处理

不使用修饰

  • ModelAndView

    Controller方法中定义ModelAndView对象并返回,对象中可添加model数据,指定view

  • void

    在Controller方法形参可以定义request和response,使用request或response指定响应结果

    • 使用request转发

      request.getRequestDispatcher("页面路径").forward(requset,respose);

    • response重定向

      response.sendRedirect("url")

    • response指定响应结果(如json)

      response.setCharacterEncoding("usf-8"); response.setContentType("application/json;charset=utf-8"); response.getWriter().write("json串");

  • String

    逻辑视图名

    return "item/item-list";

    • redirect重定向

      return "redirect:textRedirect"

      • 相当于"response.sendRedirect()"
      • 浏览器URL发生改变
      • Request域不能共享
    • forward转发

      return "forward:testForward";

      • 相当于"request.getRequestDispatcher().forward(requset,respose)"
      • 浏览器URL不发生改变
      • Request域可以共享

使用注解修饰

  • ResponseBody注解介绍

    作用:

    • ResponseBody注解可以针对Controller返回值类型,使用内置的9种HttpMessageConverter进行匹配,找到合适的HttpMessageConverter进行处理

    • HttpMessageConverter处理逻辑分为三步

      • 指定HttpMessageConverter的ContentType值
      • 将转换之后的数据放到HttpMessageConverter对象的响应体
      • 返回到页面
  • RequestBody注解作用和Response注解正好相反,它是处理请求参数的http消息转换的

    • 常用的HttpMessageConverter

      • MappingJacksonHttpMessageConverter

        • 作用处理POJO类型返回值
        • 默认使用MappingJackson的JSON处理能力,将后台返回的Java对象(POJO类型),转为JSON格式输出到页面
        • 将响应体的Content-Type设置为application/json; charset=utf-8
        • 调用response.getWriter()方法将json格式的字符串写回给调用者
      • StringHttpMessageConverter

        • 作用:处理String类型返回值
        • 将响应体的Content-Type设置为text/plain; charset=utf-8
        • 调用response.getWriter()方法将Str类型的字符串写回给调用者

参数绑定

什么是参数绑定

  • 定义

    将请求参数串的value值获取到之后,再进行类型转换,然后将转换后的值赋给Controller类中方法的形参,这个过程就是参数绑定

    • 类型转换(请求中的String类型值---->Con各种数据类型的方法形参)
    • 赋值操作,将转换之后的值 赋值给Contr方法形参
  • 请求参数格式

    默认是key/value格式,比如: http://xxxxx?id=1&type=401

  • 请求参数值的数据类型

    都是String类型的各种值

  • 请求参数值要绑定的目标类型

    Controller类中的方法参数,比如简单类型,POJO类型、集合类型等

  • SpringMVC内置的参数解析组件

    默认内置了24种参数解析组件(ArgumentResolver)

默认支持的参数类型

Controller方法形参中可以随时添加如下类型的参数(Servlet API支持),处理器适配器自动识别并进行赋值

  • HttpServletRequest

    通过request对象获取请求信息

  • HttpServletResponse

    通过response处理响应信息

  • HttpSession

    通过session对象得到session中存放的对象

  • InputStream、OutputStream

  • Reader、Writer

  • Model/ModelMap

    ModelMap继承LinkedHashMap,Model是一个接口,它们的底层实现都是同一个类(BindingAwareModelMap),作用就是向页面传递数据,相当于Request的作用,如下 model.addAttribute("msg","测试springMVC")

参数绑定使用要求

简单类型

  • 直接绑定

    http请求参数的【key】和controller方法的【形参名称】一致

    请求参数的【key】和controller方法的【形参名称】不一致时,需要使用【@RequestParam】注解才能将请求参数绑定成功。

    • RequestParam注解

      • value

        参数名字,即入参的请求参数名字,如value="itemid"表示请求的参数

      • required

        是否必须,默认是true,表示请求中一定要有相应的参数,否则将报:TTP Status 400 - Required Integer parameter 'XXX' is not present

      • defaultValue

        默认值,表示如果请求中没有同名参数时的默认值

绑定POJO类型

要求表单中【参数名称】和Controller方法中的【POJO形参的属性名称】保持一致

绑定集合或数组类型

  • 简单类型数组

    通过HTTP请求批量传递简单类型数据的情况,Controller方法中可以用String[]或者pojo的属性接收(两种方式任选其一),但不能使用List集合接收

  • POJO类型集合或数组

    批量传递的请求参数,最终要使用List来接收,那么这个List必须放在另一个POJO类中

自定义日期参数绑定

对于springMVC无法解析的参数绑定类型,比如【年月日时分秒格式的日期】绑定到Date类型会报错,此时需要自定义【参数转换器】进行参数绑定。

  • Converter代码

public class DateConverter implements Converter<String, Date> {

@Override

public Date convert(String source) {

SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");

try {

return simpleDateFormat.parse(source);

} catch (ParseException e) {

e.printStackTrace();

}

return null;

}

}
  • Converter配置
<!-- 加载注解驱动 -->

<mvc:annotation-driven conversion-service="conversionService"/>

<!-- 转换器配置 -->

<bean id="conversionService"

class="org.springframework.format.support.FormattingConversionServiceFactoryBean

">

<property name="converters">

<set>

<bean class="com.xxx.ssm.controller.converter.DateConverter"/>

</set>

</property>

</bean>

文件类型参数绑定

SpringMVC文件上传的实现,是由commons-fileupload这个第三方jar包实现的。

  • 加入依赖包

<dependency>

<groupId>commons-fileupload</groupId>

<artifactId>commons-fileupload</artifactId>

<version>1.3.1</version>

</dependency>
  • 上传页面

JSP中的form表单需要指定enctype="multipart/form-data"

  • 配置Multipart解析器

    在springmvc.xml中配置multipart类型解析器

<!-- multipart类型解析器,文件上传 -->

<bean id="multipartResolver"

class="org.springframework.web.multipart.commons.CommonsMultipartResolver">

<!-- 上传文件的最大尺寸 5M-->

<property name="maxUploadSize" value="5242880"/>

</bean>
  • Controller类代码
@RequestMapping("fileupload")

public String findUserById(MultipartFile uploadFile) throws Exception {

// 编写文件上传逻辑(mvc模式和三层结构模式)

// 三层模式:表现层(controller、action)、业务层(service、biz)、持久层(dao、

mapper)

// MVC模式主要就是来解决表现层的问题的(原始的表现层是使用Servlet编写,即编写业务逻

辑,又编写视图展示)

if (uploadFile != null) {

System.out.println(uploadFile.getOriginalFilename());

// 原始图片名称

String originalFilename = uploadFile.getOriginalFilename();

// 如果没有图片名称,则上传不成功

if (originalFilename != null && originalFilename.length() > 0) {

// 存放图片的物理路径

String picPath = "E:\\";

// 获取上传文件的扩展名

String extName =

originalFilename.substring(originalFilename.lastIndexOf("."));

// 新文件的名称

String newFileName = UUID.randomUUID() + extName;

// 新的文件

File newFile = new File(picPath + newFileName);

// 把上传的文件保存成一个新的文件

uploadFile.transferTo(newFile);

// 同时需要把新的文件名更新到数据库中

}

}

return "文件上传成功";

}

RequestMapping注解

  • value属性

    请求URL映射

    • 作用:用于映射URL和HandlerMethod方法

    • 用法

      • @RequestMapping(value="/item")
      • @RequestMapping("/item")
      • @RequestMapping(value={"/item","/item2"})
  • 窄化请求映射

    • 作用:限制此类下的所有方法的访问请求url必须以请求前缀开头,对url进行模块分类管理

    • 用法:访问时url是/item/findItem

@RequestMapping("item")

@Controller

public class ItemController {

@RequestMapping("findItem")

public String findItem(Model model) {

model.addAttribute("msg", "ItemController...findItem方法执行了");

return "success";

}

}
  • method属性

    • 作用:限定请求URL只能通过指定的method请求方式去访问该 HandlerMethod

    • 用法

      • @RequestMapping(value="/findItem",method=RequestMethod.GET)
      • @RequestMapping(value="/findItem",method=RequestMethod.POST)
      • @RequestMapping(value="/findItem",method={RequestMethod.GET,RequestMethod.POST})
  • params属性

    • 作用:通过设置 params 参数条件,进行访问 HandlerMethod 的限制

    • 用法

      • URL请求
      
      <a href="item/removeItem?name=iphone6&price>5000">删除商品,金额大于
      
      5000</a>
      
      <br />
      
      <a href="item/removeItem?name=iphoneXs&price>7000">删除商品,金额大于
      
      7000</a>
      
      • Controller方法
      @RequestMapping(value="removeItem",params= {"name","price>5000"})
      
      public String removeItem(Model model) {
      
      model.addAttribute("msg", "ItemController...removeItem方法执行
      
      了");
      
      return "success";
      
      }
      

RESTful支持

HTTP介绍

HTTP协议概述

超文本传输协议(Hyper Text Transfer Protocol,HTTP)是一个简单的请求-响应协议,它通常运行在TCP之上。

HTTP协议是建立在客户端和服务器之间的一个应用层协议,在客户端和服务器之间需要数据的传输,而传输数

据的时候,我们要按照指定的规则或者叫协议去传输数据。

URL/URI

  • URI:Uniform Resource Identififier,统一资源标识符

    它相当于一个网络资源的名称,只是名称的表现形式是/开头的路径形式

  • URL:Uniform Resource Location,统一资源定位符

  • URL和URI的区别:URL是URI的子集

WEB资源

通过浏览器可以访问到的所有资源都是 web资源 ,web资源分为静态资源和动态资源

  • 动态资源是通过后台程序展示页面数据的,比如Servlet请求
  • 静态资源的数据是不变的,比如HTML、JPG、AVI

HTTP的作用

就是为了约束客户端和服务器之间传输web资源时的格式

HTTP协议版本

1.0版本和1.1版本

HTTP1.1和HTTP1.0版本之间最大的区别就是:可以一个连接传输多个web资源,推荐使用HTTP1.1版本

HTTP协议组成

HTTP协议由两部分组成:请求协议信息和响应协议信息

  • 请求协议信息

    HTTP请求协议信息由三部分组成:请求行、请求头、请求体,简称行头体

    • 请求行

      也叫请求首行,它包含四部分(请求方法、URI、协议/版本、回车换行):

      GET /user.html HTTP/1.1

      • 请求方法

        GET、POST等8种

        互联网中WEB资源操作也有增删改查方法,它们分别是POST、DELETE、PUT和GET

      • URI

        Uniform Resource Identifier,统一资源标识符。它相当于一个网络资源的名称,只是名称的表现形式是/开头的路径形式

      • 协议/版本

        表示这次请求是通过哪个协议发送的,比如HTTP协议、HTTPS协议等,使用的HTTP协议一般都是1.1版本的

    • 请求头

      请求头的信息是以[key:value]形式展现的

      一般来说,大多数请求头的信息都不是必须的

      keyvalue
      Content-Type是请求消息中非常重要的内容,表示请求正文中的文档属于什么MIME类型。Content-Type: [type]/[subtype]; parameter。例如最常见的就是text/html,它的意思是说返回的内容是文本类型,这个文本又是HTML格式的
      Host指定请求资源的Intenet主机和端口号,必须表示请求url的原始服务器或网关的位置。HTTP/1.1请求必须包含主机头域,否则系统会以400状态码返回
      Accept浏览器可接受的MIME类型
      Accept-Charset浏览器可接受的字符集
      Accept-Encoding浏览器能够进行解码的数据编码方式,比如gzip。Servlet能够向支持gzip的浏览器返回经gzip编码的HTML页面。许多情形下这可以减少5到10倍的下载时间
      Accept-Language浏览器所希望的语言种类,当服务器能够提供一种以上的语言版本时要用到
      Authorization授权信息,通常出现在对服务器发送的WWW-Authenticate头的应答中
      Connection表示是否需要持久连接。如果Servlet看到这里的值为“Keep- Alive”,或者看到请求使用的是HTTP1.1(HTTP 1.1默认进行持久连接),它就可以利用持久连接的优点,当页面包含多个元素时(例如Applet,图片),显著地减少下载所需要的时间。要实现这一点,Servlet需要在应答中发送一个Content-Length头,最简单的实现方法是:先把内容写入 ByteArrayOutputStream,然后在正式写出内容之前计算它的大小
      Content-Length表示请求消息正文的长度
      Cookie这是最重要的请求头信息之一,可以在客户端记录访问状态
      From请求发送者的email地址,由一些特殊的Web客户程序使用,浏览器不会用到它
      If-Modifified-Since只有当所请求的内容在指定的日期之后又经过修改才返回它,否则返回304"Not Modifified"应答
      Pragma指定“no-cache”值表示服务器必须返回一个刷新后的文档,即使它是代理服务器而且已经有了页面的本地拷贝
      Referer包含一个URL,用户从该URL代表的页面出发访问当前请求的页面,使用场景:防盗链、统计网站访问信息
      User-Agent浏览器类型(客户端类型),如果Servlet返回的内容与浏览器类型有关则该值非常有用
      UA-Pixels,UA-Color,UA-OS,UA-CPU由某些版本的IE浏览器所发送的非标准的请求头,表示屏幕大小、颜色深度、操作系统和CPU类型
    • 请求体

      也叫请求正文

      • GET请求的请求体是空的,请求参数都是通过请求行转给服务器端
      • POST请求的请求体可以承载数据,请求头和请求体之间有一个空行作为分割线

      通过表单POST提交的请求体的表现形式主要有三种

      描述
      application/x-www-form-urlencoded在发送前编码所有字符(默认)
      multipart/form-data不对字符编码,在使用包含文件上传控件的表单时,必须使用该值
      text-plain空格转换为"+"加号,但不对特殊字符编码
      • application/x-www-form-urlencoded:会对中文进行URL编码,并且多个参数以&连接,上传文件 只能上传文件名称
      • text/plain:纯文本方式,不会对中文进行URL编码,不会使用&连接多个key-value参数,上传文件只 能上传文件名称
      • multipart/form-data:多部件表现形式,这种方式主要可以完成文件上传,可以将上传的文件名称和 文件内容都传递给服务器端
  • 响应协议信息

    响应协议信息,也由三部分组成:状态行、响应头、响应体(响应正文)

    • 状态行

      HTTP/1.1 200 OK

      状态行由协议/版本数字形式的状态码状态描述三部分组成

    • 响应头

      响应头中的信息也是key value方式展现的。

      keyvalue
      Content-Type是返回消息中非常重要的内容,表示后面的文档属于什么MIME类型。Content-Type: [type]/[subtype]; parameter。例如最常见的就是text/html,它的意思是说返回的内容是文本类型,这个文本又是HTML格式的。原则上浏览器会根据Content-Type来决定如何显示返回的消息体内容
      LocationLocation响应报头域用于重定向接受者到一个新的位置。例如:客户端所请求的页面已不存在原先的位置,为了让客户端重定向到这个页面新的位置,服务器端可以发回Location响应报头后使用重定向语句,让客户端去访问新的域名所对应的服务器上的资源。当我们在JSP中使用重定向语句的时候,服务器端向客户端发回的响应报头中,就会有Location响应报头域
      ServerServer响应报头域包含了服务器用来处理请求的软件信息。它和User-Agent请求报头域是相对应的,前者发送服务器端软件的信息,后者发送客户 端软件(浏览器)和操作系统的信息。下面是Server响应报头域的一个例子:Server:Apache-Coyote/1.1
      WWW-AuthenticateWWW-Authenticate响应报头域必须被包含在401(未授权的)响应消息中,这个报头域和前面讲到的Authorization请求报头域是 相关的,当客户端收到401响应消息,就要决定是否请求服务器对其进行验证。如果要求服务器对其进行验证,就可以发送一个包含了 Authorization报头域的请求,下面是WWW-Authenticate响应报头域的一个例子:WWW-Authenticate: Basicrealm="Basic Auth Test!" 从这个响应报头域,可以知道服务器端对我们所请求的资源采用的是基本验证机制
      Content-Length表示响应消息正文的长度
      ExpiresExpires实体报头域给出响应过期的日期和时间。通常,代理服务器或浏览器会缓存一些页面。当用户再次访问这些页面时,直接从缓存中加载并显示给用户,这样缩短了响应的时间,减少服务器的负载。为了让代理服务器或浏览器在一段时间后更新页面,我们可以使用Expires实体报头域指定页面过期的时 间。当用户又一次访问页面时,如果Expires报头域给出的日期和时间比Date普通报头域给出的日期和时间要早(或相同),那么代理服务器或浏览器就 不会再使用缓存的页面而是从服务器上请求更新的页面。不过要注意,即使页面过期了,也并不意味着服务器上的原始资源在此时间之前或之后发生了改变。
      Last-ModifiedLast-Modified实体报头域用于指示资源最后的修改日期及时间
      Set-Cookie设置和页面关联的Cookie。Servlet不应使用response.setHeader("Set-Cookie",...),而是应使用HttpServletResponse提供的专用方法addCookie。参见下文有关Cookie设置的讨论
      Allow服务器支持哪些请求方法(如GET、POST等)
      Content-Encoding文档的编码(Encode)方法。只有在解码之后才可以得到Content-Type头指定的内容类型。利用gzip压缩文档能够显著地减少HTML文档的下载时间。Java的GZIPOutputStream可以很方便地进行gzip压缩,但只有Unix上的Netscape和Windows上的IE 4、IE 5才支持它。因此,Servlet应该通过查看AcceptEncoding头(即request.getHeader("Accept-Encoding"))检查浏览器是否支持gzip,为支持gzip的浏览器返回经gzip压缩的HTML页面,为其他浏览器返回普通页面
    • 响应体

      响应体,也叫响应正文,里面包含服务器发给客户端的web资源信息。

      响应正文信息返回到浏览器时,浏览器需要根据响应头中Content-type设置的MIME类型来打开响应正文信息

RESTful介绍

REST

REST(英文:Representational State Transfer,简称 REST,意思是:(资源)表述性状态转化) 描述了一个架构样式的网络系统, 比如 web 应用程序

它是一种软件架构风格、设计风格,而不是标准,只是提供了一组设计原则和约束条件。它主要用于客户端和 服务器交互类的软件。基于这个风格设计的软件可以更简洁,更有层次,更易于实现缓存等机制

它本身并没有什么实用性,其核心价值在于如何设计出符合 REST 风格的网络接口

RESTful

REST指的是一组架构约束条件和原则。满足这些约束条件和原则的应用程序或设计就是 RESTful

RESTful的特性

  • 资源(Resources)

    • 网络上的一个实体,或者说是网络上的一个具体信息

    • 它可以是一段文本、一张图片、一首歌曲、一种服务,总之就是一个具体的存在

    • 可以用一个 URI(统一资源定位符)指向它,每种资源对应一个特定的 URI 。要获取这个资源,访问它的 URI 就可以,因此 URI 即为每一个资源的独一无二的识别符

  • 表现层(Representation)

    • 把资源具体呈现出来的形式,叫做它的表现层 (Representation)
    • 比如,文本可以用 txt 格式表现,也可以用 HTML 格式、XML 格式、JSON 格式表现,甚至可以采用二进 制格式
  • 状态转化(State Transfer)

    • 每发出一个HTTP请求,就代表了客户端和服务器的一次交互过程。HTTP协议,是一个无状态协议,即所有的 【状态】都保存在服务器端。因此,如果客户端想要操作服务器, 必须通过某种手段,让服务器端发生“状态 转化”(State Transfer)。而这种转化是建立在表现层之上的,所以就是 “ 表现层状态转化”
    • 具体说, 就是 HTTP 协议里面,四个表示操作方式的动词:GET 、POST 、PUT 、DELETE 。它们分别对 应四种基本操作:GET 用来获取资源,POST 用来新建资源,PUT 用来更新资源,DELETE 用来删除资源

设计RESTful应用程序的API

  • 路径设计:数据库设计完毕之后,基本上就可以确定有哪些资源要进行操作,相对于的路径也可以设计出来
  • 动词设计:也就是针对资源的具体操作类型,由HTTP动词表示,常用的HTTP动词如下:POST、DELETE、 PUT、GET

RESTful 的示例

  • /account/1 HTTP GET : 得到 id = 1 的 account
  • /account/1 HTTP DELETE: 删除 id = 1 的 account
  • /account/1 HTTP PUT: 更新 id = 1 的 account

SpringMVC对RESTful的支持

RESTful的URL路径变量

  • URL-PATTERN :设置为/,方便拦截 RESTful 请求

    <servlet-mapping> 
      <servlet-name>DispatcherServlet</servlet-name>       
      <url-pattern>/</url-pattern> 
    </servlet-mapping>
    
  • @PathVariable:可以解析出来URL中的模板变量({id})

    • URL

      http://localhost:8080/ssm/item/1/zhangsan

    • Controller

      @RequestMapping(“{id}/{name}”) 
      @ResponseBody 
      public Item queryItemById(@PathVariable Integer id,
                                  @PathVariable String name){
      }
      

静态资源

如果在DispatcherServlet中设置url-pattern为 /则必须对静态资源进行访问处理 在springmvc.xml文件中,使用 mvc:resources 标签,具体如下

<!-- 当DispatcherServlet配置为/来拦截请求的时候,需要配置静态资源的访问映射 --> 
<mvc:resources location="/js/" mapping="/js/"/> 
<mvc:resources location="/css/" mapping="/css/"/>

SpringMVC 会把 mapping 映射到ResourceHttpRequestHandler,这样静态资源在经过DispatcherServlet 转发时就可以找到对应的 Handler了

拦截器应用

拦截器介绍

  • SpringMVC 的拦截器主要是针对特定处理器进行拦截的

  • SpringMVC 拦截器( Interceptor )实现对每一个请求处理前后进行相关的业务处理,类似与servlet 中的Filter

  • SpringMVC 中的 Interceptor 拦截请求是通过 HandlerInterceptor 接口来实现的

在 SpringMVC 中定义一个 Interceptor 非常简单,主要有4种方式

  • 实现 SpringMVC 的 HandlerInterceptor 接口
  • 继承实现了 HandlerInterceptor 接口的类,比如 SpringMVC 已经提供的实现了HandlerInterceptor 接口的抽象类 HandlerInterceptorAdapter
  • 实现 SpringMVC 的 WebRequestInterceptor 接口
  • 继承实现了 WebRequestInterceptor的类

定义拦截器

实现 HandlerIntercepter 接口

public class MyHandlerIntercepter implements HandlerInterceptor{     
 //Handler执行前调用 
 //应用场景:登录认证、身份授权 
 //返回值为true则是放行,为false是不放行 
 @Override 
 public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { 
 return false; 
 } 
 //进入Handler开始执行,并且在返回ModelAndView之前调用 
 //应用场景:对ModelAndView对象操作,可以把公共模型数据传到前台,可以统一指定视图 
 @Override 
 public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { } 
 //执行完Handler之后调用 
 //应用场景:统一异常处理、统一日志处理 
 @Override 
 public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { }
 }

配置拦截器

SpringMVC 拦截器是绑定在 HandlerMapping 中的,即:如果某个 HandlerMapping 中配置拦截,则该 HandlerMapping 映射成功的 Handler 会使用该拦截器

SpringMVC 的全局拦截器配置,其实是把配置的拦截器注入到每个已初始化的 HandlerMapping 中了

<!-- 配置全局mapping的拦截器 --> 
<mvc:interceptors> 
<!-- 公共拦截器可以拦截所有请求,而且可以有多个 --> 
<bean class="com.xxx.ssm.interceptor.MyHandlerInterceptor" /> 
<bean class="com.xxx.ssm.interceptor.MyHandlerInterceptor2" /> 
<!-- 如果有针对特定URL的拦截器,则进行以下配置 --> 
<mvc:interceptor> 
<!-- /**表示所有URL和子URL路径 --> 
<mvc:mapping path="/orders/**" /> 
<!-- 特定请求的拦截器只能有一个 --> 
<bean class="com.xxx.ssm.interceptor.MyHandlerInterceptor3" />
</mvc:interceptor> 
</mvc:interceptors>

多拦截器拦截规则

如果有多个拦截器,那么配置到springmvc.xml中最上面的拦截器,拦截优先级最高

CORS跨域解决方案

跨域介绍

浏览器因为安全考虑,所以设置了同源策略。同源策略简单理解就是DNS域名,端口号,协议完全相同就称为同源。同源下的页面之间才能进行js的dom操作,如果不在一个源下任何跨文档dom访问都是被阻止的。不同源下的访问可以称之为跨域访问

CORS

  • CORS 是一个 W3C 标准,全称是"跨域资源共享"( Cross-origin resource sharing )

  • 它允许浏览器向跨源服务器,发出 XMLHttpRequest 请求,从而克服了 AJAX 只能同源使用的限制

  • CORS 需要浏览器和服务器同时支持。目前,所有浏览器都支持该功能, IE 浏览器不能低于IE10

  • CORS 原理

    • 客户端自动向请求头 header 中注入 Origin
    • 服务器端需要向响应头 header 中注入 Access-Control-Allow-Origin
    • 浏览器检测到 header 中的 Access-Control-Allow-Origin ,则就可以跨域操作了

客户端跨域处理

请求分类标准

浏览器将 CORS 请求分成两类:简单请求( simple request )和非简单请求( not-so-simple request )

同时满足以下两大条件,就是属于简单请求

  • 请求方法是一下三种方法之一:

    • HEAD
    • GET
    • POST
  • HTTP的头信息不超出以下几种字段:

    • Accept
    • Accept-Language
    • Content-Language
    • Last-Event-ID
    • Content-Type:只限于三个值 application/x-www-form-urlencoded、multipart/form-data、text/plain

    凡是不同时满足上面两个条件,就属于非简单请求

简单请求

对于简单请求,浏览器直接发出 CORS 请求。具体来说,就是在头信息之中,增加一个 Origin 字段

非简单请求

非简单请求是那种对服务器有特殊要求的请求,比如请求方法是 PUT 或 DELETE ,或者 Content-Type字段的类型是 application/json

非简单请求的 CORS 请求,会在正式通信之前,增加一次 HTTP 查询请求,称为"预检"请求( preflight )

浏览器先询问服务器,当前网页所在的域名是否在服务器的许可名单之中,以及可以使用哪些HTTP动词和头信 息字段。只有得到肯定答复,浏览器才会发出正式的XMLHttpRequest请求,否则就报错。