为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
转载请注明出处
为Spring添加REST功能的更多相关文章
- Spring学习笔记5—为Spring添加REST功能
1 关于REST 我的理解,REST就是将资源以最合适的形式在服务端和客户端之间传递. 系统中资源采用URL进行标识(可以理解为URL路径中带参数) 使用HTTP方法进行资源的管理(GET,PUT,P ...
- 创建ASP.NET Core MVC应用程序(5)-添加查询功能 & 新字段
创建ASP.NET Core MVC应用程序(5)-添加查询功能 & 新字段 添加查询功能 本文将实现通过Name查询用户信息. 首先更新GetAll方法以启用查询: public async ...
- 033医疗项目-模块三:药品供应商目录模块——供货商药品目录t添加查询功能----------Dao层和Service层和Action层和调试
什么叫做供货商药品目录t添加查询功能?就是说我们前面的博客里面不是说供货商登录后看到了自己供应的药品了么如下: 现在供货商想要往里面添加别的药品,那么这个药品的来源就是卫生局提供的那个Ypxx表(药品 ...
- 图像处理控件ImageGear for .NET教程如何为应用程序 添加DICOM功能(2)
在前面的一些关于图像处理控件ImageGear for .NET文章<图像处理控件ImageGear for .NET教程: 添加DICOM功能(1)>中讲解了如何对应用程序添加DICOM ...
- (三)开始在OJ上添加签到功能
在了解完OJ文件下的各个文件夹的主要作用后,我们开始往里面添加东西(其实只要知道各文件夹是干什么的后,添加东西也变得非常简单了) 一 在数据库中添加对应功能的字段. 我们这个学期才刚开数据库这门课,所 ...
- sharepoint 2010 如何给文档库或自定义列表添加评论功能
转:http://www.cfanz.cn/?c=article&a=read&id=40924 最近公司在知识库中,有一个需求,就是想要给文档添加评论功能,在sharepoint 2 ...
- 给destoon商城的列表中和首页添加购物车功能
如何给destoon商城的列表中和首页添加购物车功能? 目前加入购物车的功能只存在商城的详细页面里,有时候我们需要批量购买的时候,希望在列表页就能够使用这个加入购物车的功能. 修改步骤见下: 例如在商 ...
- Centos6.4 为用户添加sudo功能
sudo即super user do,以超级管理员的方式运行命令.使用时,只需在命令最前面加上sudo即可. 要为用户添加sudo功能,需要修改sudo的配置文件: vi /etc/sudoers ( ...
- HTTP学习实验8-windows添加telnet功能
Windows 添加telnet功能: 控制面板->(查看方式:小图标)->程序和功能->打开或关闭Windows功能->Telnet客户端 Telnet 设置: 打开cmd, ...
随机推荐
- 手动升级Delphi控件时,修改inc文件的办法
以MustangPeakCommonLib.exe控件为例,想让它支持Delphi2010,就需要在D:\Program Files\Common Library\Mustangpeak\Common ...
- aliCloud基于RAMService实现跨账户资源访问
1,aliCloud基于RAM service实现跨账户ECS资源访问Example 主要的资源为Instance,Image,Snapshot,disk,SecurityGroup Action太多 ...
- Binary Tree Level Order Traversal - leetcode - java
Given a binary tree, return the level order traversal of its nodes' values. (ie, from left to right, ...
- MySQL的零碎知识点
让Windows下的MySQL表名大小写敏感: 在mysql查询中执行:SHOW VARIABLES LIKE 'lower_case_table_names'; 值的含义--->0:大小写敏感 ...
- #include <hash_set>
哈希查找,不需要排序,适用于精确查找,比二分查找更快 #define _SILENCE_STDEXT_HASH_DEPRECATION_WARNINGS #include <iostream&g ...
- 移动前端之viewport
在移动设备上进行网页的重构或开发,首先得搞明白的就是移动设备上的viewport了,只有明白了viewport的概念以及弄清楚了跟viewport有关的meta标签的使用,才能更好地让我们的网页适配或 ...
- OC基础4:类和方法
"OC基础"这个分类的文章是我在自学Stephen G.Kochan的<Objective-C程序设计第6版>过程中的笔记. 1.类的声明(@interface)要放在 ...
- 7-05. 魔法优惠券(25) (数学 ZJU_PAT)
题目链接:http://www.patest.cn/contests/ds/7-05 在火星上有个魔法商店,提供魔法优惠券.每一个优惠劵上印有一个整数面值K,表示若你在购买某商品时使用这张优惠劵.能够 ...
- 如何一步步把网站Retina优化
随着高清屏幕.高分辨率屏幕越来越流行,例如MacBook Retina机型.iPad Air系列,这些新生机器有着很高的PPI,对网页的清晰度要求很高,所以越来越多的站长都不得不面临一个问题,那就是把 ...
- log4j是什么
一.什么是log4jLog4j 是Apache的一个开放源代码项目,通过使用Log4j,我们可以控制日志信息输送的目的地是控制台.文件.GUI组件.甚至是套接口服务器.NT的事 件记录器.UNIX S ...