zoukankan      html  css  js  c++  java
  • Spring学习笔记5—为Spring添加REST功能

    1 关于REST

      我的理解,REST就是将资源以最合适的形式在服务端和客户端之间传递。

    • 系统中资源采用URL进行标识(可以理解为URL路径中带参数)
    • 使用HTTP方法进行资源的管理(GET,PUT,POST,DELETE等HTTP方法)
    • 以一种或者多种适合客户端的方式来表述资源(@ResponseBody,@RequestBody,ContentNegotiatingViewResolver视图解析器)

     

    2 REST风格的Controller

    2.1 RESTful URL

      先来看一下RESTful的url和RESTless的url有何区别:

    RESTful的url——http://localhost:8080/ProjectName/students/123
    RESTless的url——http://localhost:8080/ProjectName/studentDetail.html?id=123

      RESTful的url是面向资源的,可以用来标识资源,而RESTless的url是面向行为的,不能标识资源。

      RESTful的url是有多个层级的,比如localhost:8080标识了域和端口,ProjectName标识了运行在服务器上的应用程序,students标识了学生列表资源,123标识了id为123的学生资源。

      RESTful的url的路径是参数化的。RESTless的url使用查询参数作为输入,而RESTful的url的输入是url路径的一部分。为了处理这种类型的url,需要一种能够从url路径中获取输入的Controller。

    2.2 获取RESTful URL的参数

      为了使用参数化的url路径,Spring 3引入了新的@PathVariable注解。

    @Controller
    @RequestMapping("/students")
    public class StudentController{
        ...
      
    @RequestMapping(value="/{id}",method=RequestMethod.GET)
      public String getStudent(@PathVariable("id") long id){
        ...
      }
    }

      @RequestMapping用于处理请求地址,@PathVariable用于获取请求地址中的参数。

      如果方法的参数名与路径的变量名相同,可以省略@PathVariable的值,如下:

      @RequestMapping(value="/{id}",method=RequestMethod.GET)
      public String getStudent(@PathVariable long id){
        ...
      }

    2.3 使用HTTP方法进行资源的管理

      HTTP提供了多种方法来操作资源,常用的有4种方法:GET,POST,PUT,DELETE。这四种方法对应的操作分别是:获取、创建、更新和删除。

      Spring中使用@RequestMapping注解的method属性设置方法应该处理的方法类型,例如上例中getStudent方法就是一个处理GET请求的例子。

      有一点非常重要:尽管@RequestMapping注解的method属性设置方法应该处理的方法类型,但方法里的实现也应该遵循方法的语义,这一点取决于开发者的代码编写,比如getStudent方法中不应该出现更新或者删除student的代码。

     

    3 表述资源

      表述资源是REST中很重要的一个方面,它意味着在服务器和客户端之间,资源可以以任意的形式传递——资源没有发生变化,只是它的表述方式发生变化了。

      Spring提供了两种方法将资源的Java表述形式转换为发送给客户端的表述形式:

    • 基于视图渲染进行协商(ContentNegotiatingViewResolver视图解析器)
    • HTTP消息转换器(@ResponseBody注解)

    3.1 ContentNegotiatingViewResolver视图解析器

      Spring的ContentNegotiatingViewResolver是一个特殊的视图解析器,它会将资源以最适合的形式返回给客户端(同一资源,多种返回)。

      ContentNegotiatingViewResolver如何确定客户端最适合的资源类型呢?

    • 通过查看URL的文件扩展名(http://www.test.com/user.json
    • 通过查看http request header的Accept(Accept:application/json
    • 通过查看URL中的format参数(http://www.test.com/user?format=json

      像其它的视图解析器一样,ContentNegotiatingViewResolver也需要作为一个<bean>配置在Spring上下文里。  

    <bean class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver">
        <property name="mediaTypes">
               <map>
                  <entry key="json" value="application/json" />
                  <entry key="xml" value="application/xml"/>
               </map>
        </property>
    
        默认为true,若设置为false,则忽略查看URL的文件扩展名  
        <property name="favorPathExtension" value="true"></property>
    
        默认为true,若设置为false,则忽略查看URL中的format参数
        <property name="favorParameter" value="false"></property>
    
        默认为false,若设置为true,则忽略查看Accept信息
        <property name="ignoreAcceptHeader" value="true"></property>
    
        如果所有的mediaType都没匹配上,并且请求头中不包含Accept头部信息,就会使用defaultContentType
        <property name="defaultContentType" value="text/html" />
    </bean>

      ContentNegotiatingViewResolver会首先查看URL的文件扩展名或format参数,如果没有,则查看Accept信息,如果再没有,则使用defaultContentType属性设置的类型。

      不像其它视图解析器那样,ContentNegotiatingViewResolver并不会直接解析视图,而是委托其它视图解析器来解析,如果没有特别指明的话,它将使用应用程序中的所有视图解析器。但可以通过设置viewResolvers属性声明它委托的视图解析器列表。

    3.2 Spring HTTP信息转换器和@ResponseBody

      典型的Spring MVC的Controller方法在结束的时候会将一些信息放在模型中,返回值通常解析为跳转路径。

      Spring HTTP消息转换器的工作是,将处理方法返回的Java对象转换为满足客户端要求的表述形式。

      如果方法使用@ResponseBody注解,则表明Spring HTTP信息转换器将会发挥作用,并将返回的对象转换为客户端需要的任意形式。即返回值不会被解析为跳转路径,而是直接写入HTTP response body中。

       @RequestMapping(value = "student/login")
        @ResponseBody
        public Student login(@RequestBody Student student) {//将请求中的数据写入student对象中
            return student;//不会被解析为跳转路径,而是直接写入HTTP response body中
        }

      上例中,@ResponseBody注解会告知Spring,将要返回的student对象作为资源返回给客户端,并转换为Accept头部信息要求的表述形式,如果请求中没有Accept头部信息的话,那就假设客户端可以接受任意的表述形式。

       @ResponseBody能对发送给客户端的数据进行转换成适合的表述形式,而@RequestBody能把客户端发来的数据转换成Java对象。

     

    4 提交RESTful表单

      前面说的都是如何在服务端添加REST功能,接下来说浏览器客户端如何与服务端的RESTful资源交互(Java客户端使用RestTemplate模板与服务端交互)。

      前面提到了如何使用HTTP方法(4个主要方法为:GET,POST,PUT和DELETE)定义资源的基本操作——通过使用@RequestMapping注解的method属性,让DispatcherServlet把不同的HTTP方法的请求定向到特定的Controller方法上。那么如何在请求中设置4种不同的HTTP方法呢?

      HTML4官方在表单中值支持GET和POST,忽略了PUT,DELETE以及其他的HTTP方法。HTML5中则支持所有的HTTP方法。

      规避HTML4中缺陷的方法是将PUT和DELETE请求伪装成POST请求,Spring通过两个特性来支持POST伪装:

    • 提交带有隐藏域的表单或者使用<sf:form>JSP标签。
    • 使用HiddenHttpMethodFilter来进行请求转换。

      带有隐藏域的表单示例:  

    <form method="post">
        <input type="hidden" name="_method" value="delete"/> 创建一个隐藏域,指明期望的HTTP方法。
        ...
    </form>

      使用<sf:form>JSP标签示例:

    <sf:form method="delete" modelAttribute="spitter"> 将method设置为期望的HTTP方法,<sf:form>将为你处理隐藏域。
        ...
    </sf:form>

      上面两个例子展示了浏览器端的POST伪装,那服务器端是如何处理这些伪装的POST请求的呢?

      伪装的POST请求到达服务器的时候仍然是一个POST请求,而服务端Controller的方法使用@RequestMapping注解,等待处理PUT和DELETE请求。所以在DispatcherServlet查找控制器处理方法之前,必须将伪装的POST请求转换成期望的请求类型。这就是HiddenHttpMethodFilter所要做的事情。

      HiddenHttpMethodFilter是一个Servlet过滤器,需要在web.xml中进行配置:

        <filter>    
                  <filter-name>HiddenHttpMethodFilter</filter-name>    
                  <filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>    
          </filter>    
          <filter-mapping>    
                  <filter-name>HiddenHttpMethodFilter</filter-name>    
                  <servlet-name>/*</servlet-name>    
          </filter-mapping>  
    

      当一个POST请求到达服务器端的时候,HiddenHttpMethodFilte会查看不同请求类型的hidden域,并将请求重写为期望的方法类型。

    参考:

    《Spring In Action》

    http://www.ruanyifeng.com/blog/2011/09/restful

    http://www.ruanyifeng.com/blog/2014/05/restful_api.html

    http://www.cnblogs.com/rollenholt/p/3693229.html

    http://www.cnblogs.com/guodefu909/p/4216327.html

    http://blog.csdn.net/z69183787/article/details/41654603

    转载请注明出处

  • 相关阅读:
    HDU 1069 Monkey and Banana
    HDU 1029 Ignatius and the Princess IV
    HDU 1024 Max Sum Plus Plus
    Gym100923H Por Costel and the Match
    Codeforces 682C Alyona and the Tree
    Codeforces 449B Jzzhu and Cities
    Codeforces (ccpc-wannafly camp day2) L. Por Costel and the Semipalindromes
    Codeforces 598D (ccpc-wannafly camp day1) Igor In the Museum
    Codeforces 1167c(ccpc wannafly camp day1) News Distribution 并查集模板
    快乐数问题
  • 原文地址:https://www.cnblogs.com/Jason-Xiang/p/5405273.html
Copyright © 2011-2022 走看看