使用Spring 3.1和基于Java的配置构建RESTful Web服务,第2部分

1.概述

本文介绍了如何在Spring中设置REST –控制器和HTTP响应代码,有效负载编组配置和内容协商。

2.在Spring了解REST

Spring框架支持两种创建RESTful服务的方式:

  • ModelAndView一起使用MVC
  • 使用HTTP消息转换器

ModelAndView方法较旧,文档记载得更好,但也很冗长,配置繁重。 它试图将REST范式转换为旧模型,但这并非没有问题。 Spring团队对此有所了解,并从Spring 3.0开始提供了一流的REST支持。

基于HttpMessageConverter注释的新方法轻巧得多,易于实现。 配置是最小的,它为RESTful服务提供了合理的默认值。 但是,它在文档方面比较新,有点轻松。 更重要的是,参考并不能完全消除两者之间的区别和权衡取舍。 尽管如此,这是在Spring 3.0之后构建RESTful服务的方式。

3. Java配置

@Configuration
@EnableWebMvc
public class WebConfig{//
}

新的@EnableWebMvc注释做了很多有用的事情-特别是在REST的情况下,它检测到类路径中存在Jackson和JAXB 2,并自动创建并注册默认的JSON和XML转换器 。 注释的功能等效于XML版本:

<mvc:注释驱动/>

这是一个捷径,尽管在许多情况下可能有用,但它并不完美。 当需要更复杂的配置时,请删除注释并直接扩展WebMvcConfigurationSupport

4.测试Spring上下文

Spring 3.1开始, 我们获得对@Configuration类的一流测试支持:

@RunWith( SpringJUnit4ClassRunner.class )
@ContextConfiguration( classes = { ApplicationConfig.class, PersistenceConfig.class },loader = AnnotationConfigContextLoader.class )
public class SpringTest{@Testpublic void whenSpringContextIsInstantiated_thenNoExceptions(){// When}
}

只需使用@ContextConfiguration批注指定Java配置类,新的AnnotationConfigContextLoader即可@Configuration类加载Bean定义。

注意, WebConfig配置类未包含在测试中,因为它需要在未提供的Servlet上下文中运行。

5.控制器

@Controller是RESTful API整个Web层中的中心构件。 出于本文的目的,控制器正在对简单的REST资源– Foo建模:

@Controller
@RequestMapping( value = "foo" )
class FooController{@AutowiredIFooService service;@RequestMapping( method = RequestMethod.GET )@ResponseBodypublic List< Foo > getAll(){return service.getAll();}@RequestMapping( value = "/{id}", method = RequestMethod.GET )@ResponseBodypublic Foo get( @PathVariable( "id" ) Long id ){return RestPreconditions.checkNotNull( service.getById( id ) );}@RequestMapping( method = RequestMethod.POST )@ResponseStatus( HttpStatus.CREATED )@ResponseBodypublic Long create( @RequestBody Foo entity ){RestPreconditions.checkNotNullFromRequest( entity );return service.create( entity );}@RequestMapping( method = RequestMethod.PUT )@ResponseStatus( HttpStatus.OK )public void update( @RequestBody Foo entity ){RestPreconditions.checkNotNullFromRequest( entity );RestPreconditions.checkNotNull( service.getById( entity.getId() ) );service.update( entity );}@RequestMapping( value = "/{id}", method = RequestMethod.DELETE )@ResponseStatus( HttpStatus.OK )public void delete( @PathVariable( "id" ) Long id ){service.deleteById( id );}}

Controller的实现是非公开的 –这是因为不需要这样做。 通常,控制器是依赖关系链中的最后一个控制器–它从Spring前端控制器( DispathcerServlet )接收HTTP请求,然后简单地将它们委托给服务层。 如果没有用例必须通过直接引用来注入或操纵控制器,则我不希望将其声明为公共。

请求映射很简单–与任何控制器一样,映射的实际以及HTTP 方法都用于确定请求的目标方法。 @ RequestBody将方法的参数绑定到HTTP请求的主体,而@ResponseBody对响应和返回类型执行相同的操作。 它们还确保使用正确的HTTP转换器对资源进行编组和解组。 尽管也可以使用其他HTTP头来确定表示形式,但将主要根据Accept头进行内容协商,以选择使用哪个活动转换器。

6.映射HTTP响应代码

HTTP响应的状态码是REST服务最重要的部分之一,因此主题很快就会变得非常复杂。 正确执行这些操作可能会导致或中断服务。

6.1。 未映射的请求

如果Spring MVC收到没有映射的请求,则认为该请求不被允许,并向客户端返回405 METHOD NOT ALLOWED NOT ALLOWED 。 这也是很好的做法,包括允许 HTTP标头返回一个405到客户端时,以指定哪些操作允许的。 这是Spring MVC的标准行为,不需要任何其他配置。

6.2。 有效的映射请求

对于任何确实具有映射的请求,Spring MVC认为该请求有效,如果未指定其他状态代码,则响应为200 OK 。 因此,控制器为createupdatedelete动作声明了不同的@ResponseStatus ,但为get声明了不同的@ResponseStatus ,实际上应该返回默认的200 OK。

6.3。 客户端错误

如果发生客户端错误 ,则会定义自定义异常并将其映射到适当的错误代码。 只需从Web层的任何层抛出这些异常,即可确保Spring在HTTP响应上映射相应的状态代码。

@ResponseStatus( value = HttpStatus.BAD_REQUEST )
public class BadRequestException extends RuntimeException{//
}
@ResponseStatus( value = HttpStatus.NOT_FOUND )
public class ResourceNotFoundException extends RuntimeException{//
}

这些例外是REST API的一部分,因此,仅应在与REST相对应的适当层中使用; 例如,如果存在DAO / DAL层,则不应直接使用异常。 还要注意,这些不是经过检查的异常,而是运行时异常 –与Spring的实践和习惯用法一致。

6.4。 使用@ExceptionHandler

将自定义异常映射到特定状态代码的另一种方法是在控制器中使用@ExceptionHandler批注。 这种方法的问题在于,注释仅适用于定义了它的控制器,而不适用于整个Spring容器,这意味着需要在每个控制器中分别声明它。 这很快变得很麻烦,尤其是在具有许多控制器的更复杂的应用程序中。 目前,Spring已解决了一些JIRA问题 ,以解决此限制和其他相关限制: SPR-8124 , SPR-7278 , SPR-8406 。

7.其他Maven依赖项

除了标准Web应用程序所需的spring-webmvc依赖关系之外,我们还需要为REST API设置内容编组和解编组:

<dependencies><dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-databind</artifactId><version>${jackson.version}</version></dependency><dependency><groupId>javax.xml.bind</groupId><artifactId>jaxb-api</artifactId><version>${jaxb-api.version}</version><scope>runtime</scope></dependency>
</dependencies><properties><jackson.version>2.2.2</jackson.version><jaxb-api.version>2.2.9</jaxb-api.version>
</properties>

这些库用于将REST资源的表示形式转换为JSONXML

8.结论

这篇文章介绍了使用Spring 3.1和基于Java的配置对RESTful服务的配置和实现,并讨论了HTTP响应代码,基本内容协商和封送处理。

在本系列的下一篇文章中,我将重点介绍API的可发现性 ,高级内容协商以及使用资源的其他表示形式 。 同时,检查github项目 。

参考:来自baeldung博客的JCG合作伙伴 Eugen Paraschiv 使用Spring 3和Java Config构建REST API 。

翻译自: https://www.javacodegeeks.com/2011/11/building-restful-web-service-with.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/374027.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Vmware Player 比较

VMware Workstation 12 Player 与 VMware Player 7 Pro 比较 主要功能特性VMware Player 7 ProVMware Workstation 12 Player针对商业用途授予许可是是支持多达 16 个虚拟 CPU、8 TB 磁盘、64 GB RAM 和 2 GB 显存是是支持 Microsoft Windows 10、Ubuntu 15.04、RHEL 7.1、Fedo…

(转)求单链表是否有环,环入口和环长

转自&#xff1a;http://www.cnblogs.com/youxin/p/3303172.html 1.链表中是否有环的判断可以设置两个指针(fast,slow)&#xff0c;初始值均指向头&#xff0c;slow每次向前一步&#xff0c;fast每次向前两步&#xff1b;如果链表中有环&#xff0c;则fast先进入环中&#xff0…

OJ RuntimeError常见原因

RuntimeError常见出错的原因可能有以下几种&#xff1a; 1、数组开得太小了&#xff0c;导致访问到了不该访问的内存区域 2、发生除零错误 3、大数组定义在函数内,导致程序栈区耗尽 4、指针用错了&#xff0c;导致访问到不该访问的内存区域 5、还有可能是程序抛出了未接收…

python recv_Python socket.recv方法代码示例

# 需要导入模块: from gevent import socket [as 别名]# 或者: from gevent.socket import recv [as 别名]def handle(self):"""The main request handling method, called by the server.This method runs a request handling loop, calling:meth:handle_one_r…

使用Selenium或WebDriver测试GWT应用

对于Web应用程序开发人员及其团队而言&#xff0c;良好的功能测试是最困难的任务之一。 开发价格低廉且维护良好的测试是一项挑战&#xff0c;这有助于降低质量检查成本并提高质量。 Selenium和WebDriver&#xff08;本质上现在是Selenium的继承者&#xff09;都提供了一种无需…

MySQL中有关TIMESTAMP和DATETIME的总结

一、MySQL中如何表示当前时间&#xff1f; 其实&#xff0c;表达方式还是蛮多的&#xff0c;汇总如下&#xff1a; CURRENT_TIMESTAMP CURRENT_TIMESTAMP() NOW() LOCALTIME LOCALTIME() LOCALTIMESTAMP LOCALTIMESTAMP() 二、关于TIMESTAMP和DATETIME的比较 一个完整的日期格式…

NYOJ 202 红黑树

红黑树 时间限制&#xff1a;3000 ms | 内存限制&#xff1a;65535 KB难度&#xff1a;3描述 什么是红黑树呢&#xff1f;顾名思义&#xff0c;跟枣树类似&#xff0c;红黑树是一种叶子是黑色果子是红色的树。。。 当然&#xff0c;这个是我说的。。。 《算法导论》上可不是这么…

为对象添加方法mothod

Function.prototype.mothod function( name, fn ) { this.prototype[name] fn ; return this ; };转载于:https://www.cnblogs.com/40dadao/p/5816521.html

python爬虫cookie池 与ip绑定_Python爬虫:设置Cookie解决网站拦截并爬取蚂蚁短租

前言文的文字及图片来源于网络,仅供学习、交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理。作者&#xff1a; EastmountPS&#xff1a;如有需要Python学习资料的小伙伴可以加点击下方链接自行获取我们在编写Python爬虫时&#xff0c;有时会遇到…

Java Secret:加载和卸载静态字段

总览 首先&#xff0c;很自然地假设静态字段具有特殊的生命周期&#xff0c;并且在应用程序的生命周期中一直存在。 您可以假设它们存在于内存中的特殊位置&#xff0c;例如C或类元信息的perm gen中的内存开始。 但是&#xff0c;得知静态字段驻留在堆上&#xff0c;可以具有任…

HTTP协议详解(真的很经典)

转自&#xff1a;http://blog.csdn.net/gueter/archive/2007/03/08/1524447.aspx Author :Jeffrey 引言 HTTP是一个属于应用层的面向对象的协议&#xff0c;由于其简捷、快速的方式&#xff0c;适用于分布式超媒体信息系统。它于1990年…

NYOJ 63 小猴子下落

小猴子下落 时间限制&#xff1a;3000 ms | 内存限制&#xff1a;65535 KB难度&#xff1a;3描述 有一颗二叉树&#xff0c;最大深度为D,且所有叶子的深度都相同。所有结点从左到右从上到下的编号为1,2,3&#xff0c;&#xff0c;2的D次方减1。在结点1处放一个小猴子&#xff0…

python科学计算与图形渲染_宁哥Python科学计算与图形渲染库课程

50dccd474759c0ffd343efcac14f8ab2.png (259.41 KB, 下载次数: 0)2019-4-9 12:23 上传课程目录章节1: NumPy基础知识课时1NumPy简介14:05课时2搭建NumPy开发环境&#xff0c;验证NumPy开发环境17:08课时3源代码和数据下载章节2: NumPy数组课时4创建多维数组09:20课时5获取单个数…

http协议说明

今天公司有同事让我给他讲一讲http..然后自己写了一个示例代码,这如果都看不懂.那我也没办法了.... 1 <?php2 3 //这里服务器以apache举例.nginx.iis.他们实际上处理方式的都是同理4 //申明http链接的数据包 注意最后面有两个换号.这是告诉apache.数据包的结束,如果后面没…

JBoss模块示例–模块化Web应用程序

最近&#xff0c;我读了为什么没有标准来开发真正的模块化Web应用程序&#xff1f; 由Patroklos Papapetrou撰写&#xff08; 在Java Code Geeks中也有介绍 &#xff09;。 受本文的启发&#xff0c;我决定检查实际使用的JBoss模块 。 这篇文章逐步描述了我的实验。 我首先想到…

由MySql漏洞导致电脑被入侵(特征为新增加名为piress的帐户)

今天开机&#xff0c;突然发现新增了一个名为piress的账户&#xff0c;突然间就意识到我的电脑可能被入侵了。后来发现网上很多人都遇到这样的问题。经过一步步的查证&#xff0c;原来最近MySQL爆出一个安全漏洞&#xff0c;远程登录mysql&#xff0c;尝试225次后就可以绕过身份…

multiprocessing.manager管理的对象需要加锁吗_Go: 内存管理和分配

本文基于Go1.13当不再使用内存时&#xff0c;标准库会自动执行Go的内存管理即从分配到回收。尽管开发者不需要处理它&#xff0c;但是Go的底层管理进行了很好的优化并且充满了有趣的概念。堆上的分配内存管理被设计可以在并发环境快速执行并且集成了gc。让我们从一个例子开始&a…

NYOJ 35表达式求值

表达式求值 时间限制&#xff1a;3000 ms | 内存限制&#xff1a;65535 KB难度&#xff1a;4描述 ACM队的mdd想做一个计算器&#xff0c;但是&#xff0c;他要做的不仅仅是一计算一个AB的计算器&#xff0c;他想实现随便输入一个表达式都能求出它的值的计算器&#xff0c;现在请…

Java EE6 CDI,命名组件和限定符

Java EE6的最大承诺之一就是简化了依赖注入的使用。 他们做到了&#xff0c;使用CDI 。 CDI代表Java EE的上下文和依赖注入&#xff0c;它提供了一个基础集&#xff0c;用于在企业应用程序中应用依赖注入。 在CDI之前&#xff0c;EJB 3还引入了依赖注入&#xff0c;但这有点基础…

c#获取当前目录的一些方法

【内容来源地址】&#xff1a;http://www.cnblogs.com/marcozh/archive/2008/10/19/1314667.html Assembly myAssembly Assembly.GetEntryAssembly(); string path myAssembly.Location; DirectoryInfo dr new DirectoryInfo(path); pathd…