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{
@Test
public void whenSpringContextIsInstantiated_thenNoExceptions(){
// When
}
}
只需使用@ContextConfiguration批注指定Java配置类,新的AnnotationConfigContextLoader即可从@Configuration类加载Bean定义。
注意, WebConfig配置类未包含在测试中,因为它需要在未提供的Servlet上下文中运行。
5.控制器
@Controller是RESTful API整个Web层中的中心构件。 出于本文的目的,控制器正在对简单的REST资源– Foo建模:
@Controller
@RequestMapping( value = "foo" )
class FooController{
@Autowired
IFooService service;
@RequestMapping( method = RequestMethod.GET )
@ResponseBody
public List< Foo > getAll(){
return service.getAll();
}
@RequestMapping( value = "/{id}", method = RequestMethod.GET )
@ResponseBody
public Foo get( @PathVariable( "id" ) Long id ){
return RestPreconditions.checkNotNull( service.getById( id ) );
}
@RequestMapping( method = RequestMethod.POST )
@ResponseStatus( HttpStatus.CREATED )
@ResponseBody
public 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 。 因此,控制器为create , update和delete动作声明了不同的@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资源的表示形式转换为JSON或XML 。
8.结论
这篇文章介绍了使用Spring 3.1和基于Java的配置对RESTful服务的配置和实现,并讨论了HTTP响应代码,基本内容协商和封送处理。
在本系列的下一篇文章中,我将重点介绍API的可发现性 ,高级内容协商以及使用资源的其他表示形式 。 同时,检查github项目 。
翻译自: https://www.javacodegeeks.com/2011/11/building-restful-web-service-with.html