- 浏览: 1036577 次
- 性别:
- 来自: 成都
文章分类
最新评论
-
繁星水:
Useful!!
Object-C之(Null)与(Bool) -
pacer123:
请问注解@ApiModelProperty 在哪个jar包下面 ...
Micro Service工具集之Swagger:可测试的样式化API文档 -
sucheng2016:
这东东真的好用么/
对象转换利器之Dozer -
zzq0324:
http://git.oschina.net/zzq0324/ ...
基于Spring-WS的Restful API的集成测试 -
lrz0534:
你好,我在maven上面下载了swagger-springmv ...
Micro Service工具集之Swagger:可测试的样式化API文档
在开放平台的时候,尤其是坐Rest服务的时候,因为用户可以给你传输任何数据,因此,我们需要在服务的入口处添加一层Validator以保证所有无效的数据不泛滥到后续的处理流程中,该Validator会以Fail Fast的形式,尽早告诉客户请求不合法,以及为什么不合法。在Spring MVC框架中可以非常容易实现这样的一层Validator机制。
在Rest服务中,需要验证的输入分为2个部分:
验证URL参数的验证
对于URL参数的验证,Spring只能帮我们做到限制类型,剩下的还是需要我们自己写代码处理。栗子:
这个服务中,首先要求URL参数requestId为Int类型,然后在代码中进一步限制必须小于10,如果用户输入的RequestId不为数字,或者超出整数的范围,Spring会抛出TypeMismatchException, 然后在我上一篇文章(http://ningandjiao.iteye.com/admin/blogs/1995270)中提到的ExceptionHandler中捕获这个异常,给用户反馈就行了.
测试代码:
实现代码:
如果想处理的更细致一点,可以读取TypeMismatchException中的root cause做更为细致的Response处理。
Request Bean Validator
首先,需明确的Bean Validation是一个JAVA规范(JSR-303/JSR-349 Validator),并不是专属于Spring的一个概念,Spring MVC只是让该规范可以更加友好的运用到Spring MVC应用中。只要你把Bean Validation Provider的jar包添加到classpath下,Spring就可以自动的侦测到,并把Bean Validator机制应用到所有的Controller中。 目前常用的Bean Validator是Hibernate Validator。栗子:
假设我们又一个服务叫做Propagate, 是一个操作, Request是一个AuditDeatail对象,其中包含userId,dateTime两个Property,即谁在什么时候做了这个操作。但是,应用的限制条件是userId为一个小于10位的字符串,dateTime的格式必须为“yyyy-MM-dd HH:mm:ss”,并且不能是未来的时间。如果验证失败则返回对应的错误信息。
测试代码:
实现代码:
首先,把Hibernate Validator相关的依赖包添加到classpath下:
然后,添加服务,在需要Bean Validator的参数上添加@Valid注解
接着,创建Bean,并为property添加想要的限制条件,其中的CustomDateSerializer,CustomDateSerializer类是辅助json序列化的。
经过上面的步骤,应用已经具备了验证Property的功能,但是,验证失败了我们如何捕获失败,并生成响应的异常呢? 同样的,需要通过异常处理机制来做这个工作,在SpringMVC中,当Json序列化,反序列化失败的时候,会抛出HttpMessageNotReadableException异常, 当Bean validation失败的时候,会抛出MethodArgumentNotValidException异常,因此,只需要在ExceptionHandler类中添加处理对应异常的方法即可。
除了栗子中用到的这些验证机制,Hibernate Validator还提供了很多内置的验证规则, 具体的请查看:http://docs.jboss.org/hibernate/validator/5.0/reference/en-US/html_single/#section-builtin-constraints
本文中的所有代码可以从github中拿到:https://github.com/xianlinbox/TDD_Demo/tree/master/spring-ws-rest
在Rest服务中,需要验证的输入分为2个部分:
- URL路径参数
- Request Bean Data,通常情况下为一个Bean的Json格式表述。
验证URL参数的验证
对于URL参数的验证,Spring只能帮我们做到限制类型,剩下的还是需要我们自己写代码处理。栗子:
@RequestMapping(value = "/requests/{requestId}", method = RequestMethod.GET) public Request get(@PathVariable int requestId, @RequestParam(value = "userId") String userId) { if (requestId > 10) { throw new InvalidRequestIdException("Request id must less than 10"); } if (requestId == 10) { throw new RuntimeException("Unexpected Server Error"); } return new Request(userId, requestId, "GET"); }
这个服务中,首先要求URL参数requestId为Int类型,然后在代码中进一步限制必须小于10,如果用户输入的RequestId不为数字,或者超出整数的范围,Spring会抛出TypeMismatchException, 然后在我上一篇文章(http://ningandjiao.iteye.com/admin/blogs/1995270)中提到的ExceptionHandler中捕获这个异常,给用户反馈就行了.
测试代码:
@Test public void shouldGetStatus404WhenRquestIdOutOfIntegerRanger() throws Exception { mockMvc.perform(get("/requests/11123456789") .contentType(MediaType.APPLICATION_JSON) .param("userId", "xianlinbox") ) .andExpect(status().isBadRequest()) .andExpect(content().string("Request id must be an integer")); } @Test public void shouldGetStatus404WhenRquestIdIsNotInteger() throws Exception { mockMvc.perform(get("/requests/123ss") .contentType(MediaType.APPLICATION_JSON) .param("userId", "xianlinbox") ) .andExpect(status().isBadRequest()) .andExpect(content().string("Request id must be an integer")); }
实现代码:
@ExceptionHandler(TypeMismatchException.class) @ResponseStatus(value = HttpStatus.BAD_REQUEST) @ResponseBody public String handleTypeMismatchException(TypeMismatchException ex) { return "Request id must be an integer"; }
如果想处理的更细致一点,可以读取TypeMismatchException中的root cause做更为细致的Response处理。
Request Bean Validator
首先,需明确的Bean Validation是一个JAVA规范(JSR-303/JSR-349 Validator),并不是专属于Spring的一个概念,Spring MVC只是让该规范可以更加友好的运用到Spring MVC应用中。只要你把Bean Validation Provider的jar包添加到classpath下,Spring就可以自动的侦测到,并把Bean Validator机制应用到所有的Controller中。 目前常用的Bean Validator是Hibernate Validator。栗子:
假设我们又一个服务叫做Propagate, 是一个操作, Request是一个AuditDeatail对象,其中包含userId,dateTime两个Property,即谁在什么时候做了这个操作。但是,应用的限制条件是userId为一个小于10位的字符串,dateTime的格式必须为“yyyy-MM-dd HH:mm:ss”,并且不能是未来的时间。如果验证失败则返回对应的错误信息。
测试代码:
@Test public void testPropagateWithIllegalUserId() throws Exception { mockMvc.perform(post("/propagate") .contentType(MediaType.APPLICATION_JSON) .accept(MediaType.APPLICATION_JSON) .content("{\"userId\":\"xianlinbox2\",\"dateTime\":\"2013-12-25 10:10:00\"}") ) .andExpect(status().isBadRequest()) .andExpect(jsonPath("$.code").value("001")) .andExpect(jsonPath("$.message").value("Invalid Request:\nuserId must less than 10 digits\n")); } @Test public void testPropagateWithFutureDateTime() throws Exception { mockMvc.perform(post("/propagate") .contentType(MediaType.APPLICATION_JSON) .accept(MediaType.APPLICATION_JSON) .content("{\"userId\":\"xianlinbox\",\"dateTime\":\"2014-12-25 10:10:00\"}") ) .andExpect(status().isBadRequest()) .andExpect(jsonPath("$.code").value("001")) .andExpect(jsonPath("$.message").value("Invalid Request:\nDateTime should not in future\n")); } @Test public void testPropagateWithWrongFormatDateTime() throws Exception { mockMvc.perform(post("/propagate") .contentType(MediaType.APPLICATION_JSON) .accept(MediaType.APPLICATION_JSON) .content("{\"userId\":\"xianlinbox\",\"dateTime\":\"2014-12-25\"}") ) .andExpect(status().isBadRequest()) .andExpect(jsonPath("$.code").value("001")) .andExpect(jsonPath("$.message").value("Invalid format: \"2014-12-25\" is too short")); } @Test public void testPropagateWithBothIllegalUserIdAndIllegalDateTime() throws Exception { mockMvc.perform(post("/propagate") .contentType(MediaType.APPLICATION_JSON) .accept(MediaType.APPLICATION_JSON) .content("{\"userId\":\"xianlinbox2\",\"dateTime\":\"2014-12-25 10:10:00\"}") ) .andExpect(status().isBadRequest()) .andExpect(jsonPath("$.code").value("001")) .andExpect(jsonPath("$.message").value(containsString("DateTime should not in future"))) .andExpect(jsonPath("$.message").value(containsString("userId must less than 10 digits"))); }
实现代码:
首先,把Hibernate Validator相关的依赖包添加到classpath下:
org.hibernate:hibernate-validator:5.0.2.Final", "javax.el:javax.el-api:3.0.0", 'org.glassfish.web:el-impl:2.2',
然后,添加服务,在需要Bean Validator的参数上添加@Valid注解
@RequestMapping(value = "/propagate", method = RequestMethod.POST) @ResponseStatus(value = HttpStatus.ACCEPTED) public AuditDetail propagate(@Valid @RequestBody AuditDetail operationBy) { return operationBy; }
接着,创建Bean,并为property添加想要的限制条件,其中的CustomDateSerializer,CustomDateSerializer类是辅助json序列化的。
public class AuditDetail { @NotNull @Length(max = 10, message = "userId must less than 10 digits") private String userId; @Past(message = "DateTime should not in future") private DateTime dateTime; public String getUserId() { return userId; } public void setUserId(String userId) { this.userId = userId; } @JsonSerialize(using = CustomDateSerializer.class) public DateTime getDateTime() { return dateTime; } @JsonDeserialize(using = CustomDateSerializer.class) public void setDateTime(DateTime dateTime) { this.dateTime = dateTime; } } public class CustomDateSerializer extends JsonSerializer<DateTime> { @Override public void serialize(DateTime value, JsonGenerator jgen, SerializerProvider provider) throws IOException, JsonProcessingException { jgen.writeString(value.toString("yyyy-MM-dd HH:mm:ss")); } } public class CustomDateDeserializer extends JsonDeserializer<DateTime> { @Override public DateTime deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException { return DateTime.parse(jp.getText(), DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss")); } }
经过上面的步骤,应用已经具备了验证Property的功能,但是,验证失败了我们如何捕获失败,并生成响应的异常呢? 同样的,需要通过异常处理机制来做这个工作,在SpringMVC中,当Json序列化,反序列化失败的时候,会抛出HttpMessageNotReadableException异常, 当Bean validation失败的时候,会抛出MethodArgumentNotValidException异常,因此,只需要在ExceptionHandler类中添加处理对应异常的方法即可。
@ExceptionHandler(MethodArgumentNotValidException.class) @ResponseStatus(value = HttpStatus.BAD_REQUEST) @ResponseBody public ErrorResponse handleMethodArgumentNotValidException(MethodArgumentNotValidException ex) { BindingResult bindingResult = ex.getBindingResult(); String errorMesssage = "Invalid Request:\n"; for (FieldError fieldError : bindingResult.getFieldErrors()) { errorMesssage += fieldError.getDefaultMessage() + "\n"; } return new ErrorResponse("001", errorMesssage); } @ExceptionHandler(HttpMessageNotReadableException.class) @ResponseStatus(value = HttpStatus.BAD_REQUEST) @ResponseBody public ErrorResponse handleHttpMessageNotReadableException(HttpMessageNotReadableException ex) { return new ErrorResponse("001", ex.getRootCause().getMessage()); }
除了栗子中用到的这些验证机制,Hibernate Validator还提供了很多内置的验证规则, 具体的请查看:http://docs.jboss.org/hibernate/validator/5.0/reference/en-US/html_single/#section-builtin-constraints
本文中的所有代码可以从github中拿到:https://github.com/xianlinbox/TDD_Demo/tree/master/spring-ws-rest
发表评论
-
关于并发的思考
2015-02-08 22:33 4339并发数 并发数和2个因 ... -
使用Hystrix守护应用(3)
2015-01-02 22:04 12876监控HystrixCommand 除了隔离依赖服务的调用外,H ... -
使用Hystrix守护应用(2)
2014-12-30 14:35 16817接上篇(http://ningandjiao.iteye.co ... -
使用Hystrix守护应用(1)
2014-12-30 14:28 15285Hystrix(https://github.com/Netf ... -
Mac下同时安装多个版本的JDK
2014-04-14 21:42 33241JDK8 GA之后,小伙伴们喜大普奔,纷纷跃跃欲试,想体验一下 ... -
性能测试工具之Gatling
2014-01-15 19:27 17297Gatling一直是久闻其名但 ... -
JavaMail测试工具之GreenMail
2014-01-08 19:13 7367不管现在各种Mock框架的运用有多广,我个人在写单元测试的时候 ... -
定制一个Gradle Plugin --- project-structure
2014-01-03 21:23 8494最近在项目中遇到一个 ... -
Spring MVC中的异常处理
2013-12-25 13:13 24166在一个良好的Rest架构的应用中,所有的异常都应该有对应的Ht ... -
Spring 4.0升级小贴士
2013-12-22 19:40 11439随着Spring4.0的发布,很多同志估计都在考虑升级的事情了 ... -
Spring4.0给我们带来什么?
2013-12-22 17:13 45031JDK8 对JDK8的支持,这个目前来说还是探索性质,毕竟Ja ... -
RESTful API版本控制策略
2013-12-15 19:51 31740做RESTful开放平台,一方面其API变动越少, 对API调 ... -
对象转换利器之Dozer
2013-12-14 22:46 19880在Java的世界中,经常会 ... -
基于Spring-WS的Restful API的集成测试
2013-11-28 19:41 9070在很多Java企业级应用中,Spring占据了非常重要的位置, ... -
TDD Of Spring JMS
2013-11-25 19:53 1760不知何时养成了习惯,在没有一个可运行的测试的时候,个人完全没有 ... -
Micro Service工具集之Swagger:可测试的样式化API文档
2013-09-28 19:55 44741在我之前的一篇博文中,介绍了Yammer开发团队贡献的开源微服 ... -
进击的Java开发
2013-07-14 20:48 5913今天在公司的邮件组中看到一组很有趣的讨论,这是我最喜欢目前公司 ... -
说说SpringBatch的领域概念
2013-06-21 20:32 3625谈到Spring Batch,会谈到 ... -
做项目时需要考虑的安全性问题
2013-04-16 20:20 4786在开发一个项目的时候,大家经常会忽略项目的安全性问题,有很多的 ... -
使用Gradle部署jar包到Maven中央库
2013-04-12 16:15 24165Maven作为目前Java界最好的Dependency管理系统 ...
相关推荐
Spring MVC 是一个强大的Java框架,用于构建Web应用程序,特别是对于基于模型-视图-控制器(MVC)架构的应用。在本文中,我们将深入探讨如何利用Spring MVC创建RESTful服务,这些服务可以处理字符串、JSON和XML数据...
Spring 3 MVC框架是Java开发者广泛使用的构建Web应用的工具,它为开发RESTful API提供了强大的支持。本教程将深入探讨如何利用Spring 3 MVC实现RESTful服务。 首先,理解REST的基本原则至关重要。RESTful架构有以下...
Spring MVC 是一个基于Java的轻量级Web应用框架,它是Spring框架的重要组成部分,主要用于构建Web应用程序的后端控制器。Spring MVC的设计目标是提供一个清晰的组件化架构,使得开发者可以独立地开发和测试控制器、...
Spring MVC是Spring框架的一部分,它为构建基于Java的Web应用程序提供了一个模型-视图-控制器(MVC)架构。这本书深入浅出地介绍了如何有效地使用Spring MVC进行开发,以下是一些核心知识点的详细说明: 1. **...
6. **RESTful API**:Spring MVC支持构建RESTful服务,与jQuery的Ajax功能结合,可以轻松实现前后端分离的开发模式。 综上,Spring MVC、jQuery和Twitter Bootstrap的结合,可以构建出功能强大、交互性强且具有良好...
Spring MVC是Spring框架的一个模块,专为构建Web应用程序而设计,以其灵活性、高效性和可扩展性受到广大开发者的青睐。下面我们将详细探讨Spring MVC的核心概念和技术点。 1. **Spring MVC架构** Spring MVC采用...
Spring MVC 是一款基于 Java 的 Web 应用框架,它遵循 MVC(Model-View-Controller)设计模式。Spring MVC 提供了一种结构化的开发方式,旨在简化 Web 层的开发过程,同时提供了高度灵活性和扩展性。 #### Spring ...
Spring MVC是Spring框架的一个核心模块,它主要用于构建Web应用程序的模型-视图-控制器(MVC)架构。这篇文档详细地介绍了Spring MVC的功能、工作原理以及如何将其有效地应用于实际项目中。Spring MVC的设计目标是...
**Spring MVC RESTful 示例** Spring MVC 是 Spring 框架的一部分,它主要用于构建 Web 应用程序,尤其是处理 HTTP 请求和响应。RESTful 风格的 Web 服务已经成为现代 Web 开发的标准,因为它强调简单、轻量级的...
Spring MVC 是一个基于 Java 的轻量级 Web 开发框架,它是 Spring 框架的一部分,专为构建 MVC(Model-View-Controller)架构的应用程序而设计。Spring MVC 提供了一个灵活的模型,允许开发者将业务逻辑与用户界面...
RESTful SpringMVC CRUD是指使用RESTful原则设计Spring MVC应用程序,以执行创建(Create)、读取(Retrieve)、更新(Update)和删除(Delete)数据的基本操作。 首先,我们需要理解REST(Representational State Transfer...
Spring MVC 是一个强大的Java框架,用于构建Web应用程序,而REST(Representational State Transfer)是一种软件架构风格,常用于创建Web服务。"Spring MVC REST Demo"是一个示例项目,旨在展示如何在Spring MVC框架...
Spring MVC 是一个基于Java的轻量级Web应用框架,它为构建RESTful应用程序提供了强大的支持。在本教程中,我们将深入探讨Spring MVC的核心概念,特别是关于注解的使用以及简单的控制器实现。 首先,Spring MVC的...
9. **RESTful服务**:使用Spring MVC创建RESTful API,理解HTTP方法(GET、POST、PUT、DELETE)在资源操作中的应用。 10. **视图技术**:除了JSP,还可以使用FreeMarker、Thymeleaf等模板引擎作为视图。 在"Servlet...
Spring MVC 是一个强大的Java Web开发框架,用于构建可维护、高性能的Web应用程序。在实际的开发过程中,我们经常需要处理各种可能出现的异常情况。本文将深入探讨Spring MVC中的异常处理机制,帮助你更好地理解如何...
例如,如果我们有一个`User`类,Spring MVC可以通过`@RequestBody`注解将JSON解析成`User`对象。 4. **JSON输出** 对于响应,我们可以返回一个对象或集合,Spring MVC会自动将其转换为JSON并设置合适的HTTP响应头...
Spring MVC 是一个基于 Java 的轻量级 Web 开发框架,它是 Spring 框架的一部分,主要用于构建 MVC(Model-View-Controller)模式的 Web 应用程序。在现代 Web 开发中,JSON(JavaScript Object Notation)作为一种...
Spring MVC 是一个强大的Java Web开发框架,用于构建可维护、高性能和灵活的Web应用程序。它作为Spring框架的一部分,提供了一种模型-视图-控制器(MVC)架构,简化了处理HTTP请求和响应的复杂性。这个压缩包包含了...
在本文中,我们将深入探讨如何在Spring 3.0中整合MVC框架与RESTful服务,并结合Maven构建项目。RESTful(Representational State Transfer)是一种软件架构风格,用于设计网络应用程序,尤其适用于Web服务。Spring ...