php网站服务建设,网页设计师需要学什么专业,wordpress主题网站,网站服务内容我对此感到有些to愧#xff0c;但直到昨天#xff0c;我才知道我可以使用Valid和RequestBody批注将验证添加到REST API中。 这在Spring MVC 3.0中不起作用#xff0c;由于某种原因#xff0c;我没有注意到在Spring MVC 3.1中添加了对此功能的支持 。 我从不喜欢旧的方法但直到昨天我才知道我可以使用Valid和RequestBody批注将验证添加到REST API中。 这在Spring MVC 3.0中不起作用由于某种原因我没有注意到在Spring MVC 3.1中添加了对此功能的支持 。 我从不喜欢旧的方法因为我不得不 将Validator和MessageSource Bean注入到我的控制器中以便我可以验证请求并在验证失败时获取本地化的错误消息。 在每个必须验证输入的控制器方法中调用验证方法。 将验证逻辑移到由控制器类扩展的公共基类中。 当我发现不再需要执行这些操作时我决定写这篇博客文章并与大家分享我的发现。 注意如果我们想在Spring Framework中使用JSR-303支持的验证我们必须向我们的类路径添加JSR-303提供程序。 本博客文章的示例应用程序使用Hibernate Validator 4.2.0它是Bean验证APIJSR-303的参考实现。 让我们首先看一下本博客文章中使用的DTO类。 CommentDTO类的源代码如下所示 import org.hibernate.validator.constraints.Length;
import org.hibernate.validator.constraints.NotEmpty;public class CommentDTO {NotEmptyLength(max 140)private String text;//Methods are omitted.
} 让我们继续前进了解如何使用Spring MVC 3.1向REST API添加验证。 Spring MVC 3.1是一个好的开始 我们可以按照以下步骤将验证添加到REST API 实施控制器方法并确保其输入经过验证。 实现处理验证错误的逻辑。 以下小节将介绍这两个步骤。 实施控制器 我们可以通过执行以下步骤来实现我们的控制器 创建一个名为CommentController的类并使用Controller注释对该类进行注释。 将一个add方法添加到CommentController类该方法将添加的注释作为方法参数。 使用RequestMapping和ResponseBody注释对方法进行注释。 将Valid和RequestBody批注应用到方法参数。 返回添加的评论。 CommentController类的源代码如下所示 import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;import javax.validation.Valid;Controller
public class CommentController {RequestMapping(value /api/comment, method RequestMethod.POST)ResponseBodypublic CommentDTO add(Valid RequestBody CommentDTO comment) {return comment;}
} 现在我们向控制器添加了新方法并对其进行了验证。 验证失败时将引发MethodArgumentNotValidException 。 让我们找出验证失败时如何向API用户返回有意义的响应。 处理验证错误 通过执行以下步骤我们可以实现处理验证错误的逻辑 实现数据传输对象其中包含返回给我们REST API用户的信息。 实现异常处理程序方法。 下面将更详细地描述这些步骤。 创建数据传输对象 首先我们必须创建数据传输对象其中包含返回给REST API用户的信息。 我们可以按照以下步骤进行操作 创建一个DTO其中包含单个验证错误的信息。 创建将这些验证错误包装在一起的DTO。 让我们开始吧。 第一个DTO的源代码如下所示 public class FieldErrorDTO {private String field;private String message;public FieldErrorDTO(String field, String message) {this.field field;this.message message;}//Getters are omitted.
} 第二个DTO的实现非常简单。 它包含一个FieldErrorDTO对象列表和一个用于向列表中添加新字段错误的方法。 ValidationErrorDTO的源代码如下所示 import java.util.ArrayList;
import java.util.List;public class ValidationErrorDTO {private ListFieldErrorDTO fieldErrors new ArrayList();public ValidationErrorDTO() {}public void addFieldError(String path, String message) {FieldErrorDTO error new FieldErrorDTO(path, message);fieldErrors.add(error);}//Getter is omitted.
} 以下清单提供了一个示例Json文档当验证失败时该文档将发送回我们的API用户 {fieldErrors:[{field:text,message:error message}]
} 让我们看看如何实现异常处理程序方法该方法创建一个新的ValidationErrorDTO对象并返回创建的对象。 实现异常处理程序方法 我们可以按照以下步骤将异常处理程序方法添加到我们的控制器中 将一个MessageSource字段添加到CommentController类。 消息源用于获取验证错误的本地化错误消息。 通过使用构造函数注入来注入MessageSource bean。 将一个processValidationError方法添加到CommentController类。 此方法返回ValidationErrorDTO对象并使用MethodArgumentNotValidException对象作为方法参数。 使用ExceptionHandler注释对方法进行注释并确保在引发MethodArgumentNotValidException时调用该方法。 使用ResponseStatus注释对方法进行注释并确保返回HTTP状态代码400错误请求。 使用ResponseBody注释对方法进行注释。 实现该方法。 让我们仔细看看processValidationError方法的实现。 我们可以通过执行以下步骤来实现此方法 获取FieldError对象的列表并进行处理。 一次处理一场错误。 尝试使用MessageSource对象当前语言环境和已处理字段错误的错误代码来解决本地化的错误消息。 返回已解决的错误消息。 如果从属性文件中找不到错误消息请返回最准确的字段错误代码。 通过调用ValidationErrorDTO类的addFieldError方法来添加新的字段错误。 将字段名称和已解决的错误消息作为方法参数传递。 处理完每个字段错误后返回创建的ValidationErrorDTO对象。 CommentController类的源代码如下所示 import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.MessageSource;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.*;import javax.validation.Valid;
import java.util.List;
import java.util.Locale;Controller
public class CommentController {private MessageSource messageSource;Autowiredpublic CommentController(MessageSource messageSource) {this.messageSource messageSource;}//The add() method is omitted.ExceptionHandler(MethodArgumentNotValidException.class)ResponseStatus(HttpStatus.BAD_REQUEST)ResponseBodypublic ValidationErrorDTO processValidationError(MethodArgumentNotValidException ex) {BindingResult result ex.getBindingResult();ListFieldError fieldErrors result.getFieldErrors();return processFieldErrors(fieldErrors);}private ValidationErrorDTO processFieldErrors(ListFieldError fieldErrors) {ValidationErrorDTO dto new ValidationErrorDTO();for (FieldError fieldError: fieldErrors) {String localizedErrorMessage resolveLocalizedErrorMessage(fieldError);dto.addFieldError(fieldError.getField(), localizedErrorMessage);}return dto;}private String resolveLocalizedErrorMessage(FieldError fieldError) {Locale currentLocale LocaleContextHolder.getLocale();String localizedErrorMessage messageSource.getMessage(fieldError, currentLocale);//If the message was not found, return the most accurate field error code instead.//You can remove this check if you prefer to get the default error message.if (localizedErrorMessage.equals(fieldError.getDefaultMessage())) {String[] fieldErrorCodes fieldError.getCodes();localizedErrorMessage fieldErrorCodes[0];}return localizedErrorMessage;}
} 这就对了。 让我们花点时间评估我们刚刚完成的工作。 我们就快到了 现在我们已经使用Spring MVC 3.1将验证添加到了REST API中。 与旧方法相比此实现有一个主要优点 我们可以使用Valid批注来触发验证过程。 但是仅当从包含异常处理程序方法的控制器类中抛出配置的异常时才会触发使用ExceptionHandler注释进行注释的方法。 这意味着如果我们的应用程序具有多个控制器则必须为控制器创建一个通用基类并将处理验证错误的逻辑移至该类。 这听起来似乎没什么大不了但是我们应该更喜欢组合而不是继承 。 Spring MVC 3.2提供了可用于从控制器中消除继承需求的工具。 让我们继续前进找出实现方法。 Spring MVC 3.2抢救 Spring MVC 3.2引入了一个新的ControllerAdvice批注 我们可以使用该批注实现一个异常处理程序组件该组件处理控制器抛出的异常。 我们可以通过执行以下步骤来实现此组件 从CommentController类中删除处理验证错误的逻辑。 创建一个新的异常处理程序类并将处理验证错误的逻辑移至创建的类。 在以下小节中将更详细地说明这些步骤。 从我们的控制器中删除异常处理逻辑 我们可以按照以下步骤从控制器中删除异常处理逻辑 从CommentController类中删除MessageSource字段。 从我们的控制器类中删除构造函数。 从我们的控制器类中删除processValidationError方法和私有方法。 CommentController类的源代码如下所示 import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;import javax.validation.Valid;Controller
public class CommentController {RequestMapping(value /api/comment, method RequestMethod.POST)ResponseBodypublic CommentDTO add(Valid RequestBody CommentDTO comment) {return comment;}
} 我们的下一步是创建异常处理程序组件。 让我们看看这是如何完成的。 创建异常处理程序组件 我们可以按照以下步骤创建异常处理程序组件 创建一个名为RestErrorHandler的类并使用ControllerAdvice批注对其进行批注。 将一个MessageSource字段添加到RestErrorHandler类。 通过使用构造函数注入来注入MessageSource bean。 将processValidationError方法和所需的私有方法添加到RestErrorHandler类。 RestErrorHandler类的源代码如下所示 import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.MessageSource;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.http.HttpStatus;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;import java.util.List;
import java.util.Locale;ControllerAdvice
public class RestErrorHandler {private MessageSource messageSource;Autowiredpublic RestErrorHandler(MessageSource messageSource) {this.messageSource messageSource;}ExceptionHandler(MethodArgumentNotValidException.class)ResponseStatus(HttpStatus.BAD_REQUEST)ResponseBodypublic ValidationErrorDTO processValidationError(MethodArgumentNotValidException ex) {BindingResult result ex.getBindingResult();ListFieldError fieldErrors result.getFieldErrors();return processFieldErrors(fieldErrors);}private ValidationErrorDTO processFieldErrors(ListFieldError fieldErrors) {ValidationErrorDTO dto new ValidationErrorDTO();for (FieldError fieldError: fieldErrors) {String localizedErrorMessage resolveLocalizedErrorMessage(fieldError);dto.addFieldError(fieldError.getField(), localizedErrorMessage);}return dto;}private String resolveLocalizedErrorMessage(FieldError fieldError) {Locale currentLocale LocaleContextHolder.getLocale();String localizedErrorMessage messageSource.getMessage(fieldError, currentLocale);//If the message was not found, return the most accurate field error code instead.//You can remove this check if you prefer to get the default error message.if (localizedErrorMessage.equals(fieldError.getDefaultMessage())) {String[] fieldErrorCodes fieldError.getCodes();localizedErrorMessage fieldErrorCodes[0];}return localizedErrorMessage;}
} 我们终于到了 感谢Spring MVC 3.2我们现在实现了一种优雅的解决方案其中验证由Valid注释触发并且异常处理逻辑移至单独的类。 我认为我们可以称之为一天享受工作成果。 摘要 这篇博客文章告诉我们 如果要在使用Spring 3.0时向REST API添加验证则必须自己实现验证逻辑。 Spring 3.1通过使用Valid批注将验证添加到REST API成为可能。 但是我们必须创建一个包含异常处理逻辑的通用基类。 每个需要验证的控制器都必须扩展此基类。 当使用Spring 3.2时我们可以通过使用Valid批注来触发验证过程并将异常处理逻辑提取到单独的类中。 Github上提供了此博客的示例应用程序 Spring 3.1和Spring 3.2 参考资料 从槽中汲取经验 Petri Kainulainen博客上的JCG合作伙伴 Petri Kainulainen 向REST API添加了验证 。 翻译自: https://www.javacodegeeks.com/2013/05/spring-from-the-trenches-adding-validation-to-a-rest-api.html