亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 開發 > Java > 正文

springMVC引入Validation的具體步驟詳解

2024-07-14 08:40:54
字體:
來源:轉載
供稿:網友

本文簡單介紹如何引入validation的步驟,如何通過自定義validation減少代碼量,提高生產力。特別提及:非基本類型屬性的valid,GET方法的處理,validation錯誤信息的統一resolve。

本文中validation的實際實現委托給Hibernate validation處理

基本配置

pom引入maven依賴

<!-- validation begin --><dependency>  <groupId>javax.validation</groupId>  <artifactId>validation-api</artifactId>  <version>1.1.0.Final</version></dependency><dependency>  <groupId>org.hibernate</groupId>  <artifactId>hibernate-validator</artifactId>  <version>5.4.0.Final</version></dependency><!-- validation end -->

增加validation配置

在spring-mvc-servlet.xml中增加如下配置:

<mvc:annotation-driven validator="validator"><bean id="validator" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean">  <property name="providerClass" value="org.hibernate.validator.HibernateValidator" />  <property name="validationMessageSource" ref="messageSource"/></bean>//messageSource 為i18n資源管理bean,見applicationContext.xml配置

自定義exceptionHandler

個性化處理validation錯誤信息,返回給調用方的信息更加友好, 在applicationContext.xml中增加如下配置:

<!-- 加載i18n消息資源文件 --><bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource">  <property name="basenames">    <list>      <value>errormsg</value>      <value>validation_error</value>    </list>  </property></bean><bean id="validationExceptionResolver" class="com.*.exception.ValidationExceptionResovler"/>

在項目類路徑上增加:validation_error_zh_CN.properties資源文件:

#the error msg for input validation#commonfield.can.not.be.null={field}不能為空field.can.not.be.empty={field}不能為空或者空字符串field.must.be.greater.than.min={field}不能小于{value}field.must.be.letter.than.max={field}不能大于{value}

ValidationExceptionResovler實現:

ValidationExceptionResovler.java

@Slf4jpublic class ValidationExceptionResovler extends AbstractHandlerExceptionResolver {  public ValidationExceptionResovler() {    // 設置order,在DefaultHandlerExceptionResolver之前執行    this.setOrder(0);  }  /**   * Handle the case where an argument annotated with {@code @Valid} such as   * an {@link } or {@link } argument fails validation.   * <p>   * 自定義ValidationException 異常處理器   * 獲取到具體的validation 錯誤信息,并組裝CommonResponse,返回給調用方。   *   * @param request current HTTP request   * @param response current HTTP response   * @param handler the executed handler   * @return an empty ModelAndView indicating the exception was handled   * @throws IOException potentially thrown from response.sendError()   */  @ResponseBody  protected ModelAndView handleMethodArgumentNotValidException(BindingResult bindingResult,                                 HttpServletRequest request,                                 HttpServletResponse response,                                 Object handler)      throws IOException {    List<ObjectError> errors = bindingResult.getAllErrors();    StringBuffer errmsgBF = new StringBuffer();    for (ObjectError error : errors) {      String massage = error.getDefaultMessage();      errmsgBF.append(massage);      errmsgBF.append("||");    }    String errmsgString = errmsgBF.toString();    errmsgString = errmsgString.length() > 2 ? errmsgString.substring(0, errmsgString.length() - 2) : errmsgString;    log.error("Validation failed! {} ", errmsgString);    Map<String, Object> map = new TreeMap<String, Object>();    map.put("success", false);    map.put("errorCode", "9999");    map.put("errorMsg", errmsgString);    ModelAndView mav = new ModelAndView();    MappingJackson2JsonView view = new MappingJackson2JsonView();    view.setAttributesMap(map);    mav.setView(view);    return mav;  }  @Override  protected ModelAndView doResolveException(HttpServletRequest request,                       HttpServletResponse response, Object handler,                       Exception ex) {    BindingResult bindingResult = null;    if (ex instanceof MethodArgumentNotValidException) {      bindingResult = ((MethodArgumentNotValidException) ex).getBindingResult();    } else if(ex instanceof BindException) {      bindingResult = ((BindException) ex).getBindingResult();    } else {      //other exception , ignore    }    if(bindingResult != null) {      try {        return handleMethodArgumentNotValidException(bindingResult, request, response, handler);      } catch (IOException e) {        log.error("doResolveException: ", e);      }    }    return null;  }}

在controller中增加@Valid 

@RequestMapping("/buy")@ResponseBodypublic BaseResponse buy(@RequestBody @Valid BuyFlowerRequest request) throws Exception { //......} 

在request bean上為需要validation的屬性增加validation注解

@Setter@Getterpublic class BuyFlowerRequest {@NotEmpty(message = "{name.can.not.be.null}") private String name;} 

二級對象的validation

上面的寫法,只能對BuyFlowerRequest在基本類型屬性上做校驗,但是沒有辦法對對象屬性的屬性進行validation,如果需要對二級對象的屬性進行validation,則需要在二級對象及二級對象屬性上同時添加@Valid 和 具體的validation注解.

如下寫法:

@Setter@Getterpublic class BuyFlowerRequest {  @NotEmpty(field = "花名")  private String name;  @Min(field = "價格", value = 1)  private int price;  @NotNull  private List<PayType> payTypeList;} @Setter@Getterpublic class PayType {  @Valid  @Min(value = 1)  private int payType;  @Valid  @Min(value = 1)  private int payAmount;}

進一步減少編碼量

為了減少編碼工作量,通過自定義Validation注解,嘗試將validation作用的filed名稱傳遞到 錯誤信息的資源文件中,從而避免為每個域編寫不同的message模版.

下面以重寫的@NotNull為例講解:

1、定義Validation注解,注意相比原生注解增加了field(),用于傳遞被validated的filed名字

NotNull.java

@Target( { ElementType.METHOD, ElementType.FIELD, ElementType.ANNOTATION_TYPE, ElementType.CONSTRUCTOR, ElementType.PARAMETER })@Constraint(validatedBy = { NotNullValidator.class })@Retention(RetentionPolicy.RUNTIME)public @interface NotNull {  String field() default "";  String message() default "{field.can.not.be.null}";  Class<?>[] groups() default {};  Class<? extends Payload>[] payload() default {};}

2、定義Validator,所有的Validator均實現ConstraintValidator接口:

NotNullValidator.java

public class NotNullValidator implements ConstraintValidator<NotNull, Object> {  @Override  public void initialize(NotNull annotation) {  }  @Override  public boolean isValid(Object str, ConstraintValidatorContext constraintValidatorContext) {    return str != null;  }}

3、在filed上加入Validation注解,注意指定filed值,message如果沒有個性化需求,可以不用指明,validation組件會自行填充default message。

BuyFlowerRequest.java

@Setter@Getterpublic class BuyFlowerRequest {  @NotEmpty(field = "花名")  private String name;  @Min(field = "價格", value = 1)  private int price;} 

注:@NotNull注解已經支持對list的特殊校驗,對于List類型節點,如果list==null || list.size() == 0都會返回false,validation失敗。目前已按照此思路自定義實現了@NotNull、@NotEmpty、@Min、@Max注解,在goods工程中可以找到.

支持GET請求

上面的示例都是POST請求,@RequestBody可以 resolve POST請求,但是不支持GET請求,閱讀spring的文檔和源碼,發現@ModelAttribute可以將GET請求resolve成Bean,且支持Validation。具體可以翻閱spring源碼:ModelAttributeMethodProcessor.resolveArgument()方法。

使用示例:

@RequestMapping(value = "/buy", method = RequestMethod.GET)@ResponseBodypublic BaseResponse detail(@Valid @ModelAttribute DetailFlowerRequest request) throws Exception {  DetailFlowerResponse response = new DetailFlowerResponse();  response.setName(request.getName());  return ResultFactory.success(response, BaseResponse.class);}

TODO

1、根據業務場景擴展validation,如:日期格式、金額等

2、支持多個field關系校驗的validation

 附:spring validation實現關鍵代碼

@RequestBody

實現類:RequestResponseBodyMethodProcessor.java

public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception { Object arg = this.readWithMessageConverters(webRequest, parameter, parameter.getGenericParameterType()); String name = Conventions.getVariableNameForParameter(parameter); WebDataBinder binder = binderFactory.createBinder(webRequest, arg, name); if (arg != null) { this.validateIfApplicable(binder, parameter); if (binder.getBindingResult().hasErrors() && this.isBindExceptionRequired(binder, parameter)) {  throw new MethodArgumentNotValidException(parameter, binder.getBindingResult()); } } mavContainer.addAttribute(BindingResult.MODEL_KEY_PREFIX + name, binder.getBindingResult()); return arg;}

@ModelAttibute

實現類:ModelAttributeMethodProcessor.java

public final Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception { String name = ModelFactory.getNameForParameter(parameter); Object attribute = mavContainer.containsAttribute(name) ? mavContainer.getModel().get(name) : this.createAttribute(name, parameter, binderFactory, webRequest); if (!mavContainer.isBindingDisabled(name)) { ModelAttribute ann = (ModelAttribute)parameter.getParameterAnnotation(ModelAttribute.class); if (ann != null && !ann.binding()) {  mavContainer.setBindingDisabled(name); } } WebDataBinder binder = binderFactory.createBinder(webRequest, attribute, name); if (binder.getTarget() != null) { if (!mavContainer.isBindingDisabled(name)) {  this.bindRequestParameters(binder, webRequest); } this.validateIfApplicable(binder, parameter); if (binder.getBindingResult().hasErrors() && this.isBindExceptionRequired(binder, parameter)) {  throw new BindException(binder.getBindingResult()); } } Map<String, Object> bindingResultModel = binder.getBindingResult().getModel(); mavContainer.removeAttributes(bindingResultModel); mavContainer.addAllAttributes(bindingResultModel); return binder.convertIfNecessary(binder.getTarget(), parameter.getParameterType(), parameter);}

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持VeVb武林網。


注:相關教程知識閱讀請移步到JAVA教程頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
国模极品一区二区三区| 久久久91精品国产| 国产美女精彩久久| 日韩精品在线观看一区二区| 亚洲欧洲黄色网| 国产精品亚洲美女av网站| 精品免费在线观看| 一区二区福利视频| 成人福利网站在线观看| 亚洲韩国日本中文字幕| 欧美视频中文字幕在线| 国产精品一久久香蕉国产线看观看| 亚洲福利影片在线| 国产成人涩涩涩视频在线观看| 中文字幕日韩在线观看| 欧美高清激情视频| 精品国内亚洲在观看18黄| 欧美网站在线观看| 国产热re99久久6国产精品| 亚洲香蕉伊综合在人在线视看| 久久久久99精品久久久久| 91亚洲永久免费精品| 国产日韩综合一区二区性色av| 久久久久久国产精品久久| 97超碰色婷婷| 欧美激情精品久久久久久| 日韩暖暖在线视频| 亚洲人精选亚洲人成在线| 国产美女久久精品香蕉69| 北条麻妃一区二区三区中文字幕| 欧美激情一区二区三级高清视频| 日韩中文字幕在线看| 欧美成人激情视频| 精品久久久久久久中文字幕| 伊人久久免费视频| 青青草原一区二区| 最新国产成人av网站网址麻豆| 中文字幕一区日韩电影| 日本道色综合久久影院| 国产精品久久久久久久久久新婚| 国产精品成人免费电影| 国产精品视频免费观看www| 97久久精品国产| 日韩成人网免费视频| 亚洲精品永久免费| 欧美成人sm免费视频| 国产精品69精品一区二区三区| 日韩高清免费观看| 少妇精69xxtheporn| 免费99精品国产自在在线| 久久人人97超碰精品888| 国产成人极品视频| 97国产成人精品视频| 成人高h视频在线| 亚洲精品黄网在线观看| 亚洲视频专区在线| 亚洲奶大毛多的老太婆| 国产成人涩涩涩视频在线观看| 亚洲最大成人网色| 色哟哟网站入口亚洲精品| 国产色综合天天综合网| 欧美激情精品久久久久久大尺度| 97碰碰碰免费色视频| 一区二区三区四区精品| 成人激情在线播放| 日韩免费看的电影电视剧大全| 亚洲福利在线观看| 久久久这里只有精品视频| 国产精品女视频| 97视频免费在线观看| 色综合久久中文字幕综合网小说| 日韩国产在线播放| 欧美日韩国产精品一区二区不卡中文| 国产欧美在线观看| 黑人巨大精品欧美一区免费视频| 久久久极品av| 日韩激情视频在线播放| 国产偷亚洲偷欧美偷精品| 国产视频丨精品|在线观看| 中文字幕无线精品亚洲乱码一区| 日韩在线视频导航| 亚洲精品自拍视频| 欧洲亚洲免费视频| 欧美激情videoshd| 91精品视频播放| 久久精品国亚洲| 国产精品va在线| 成人国产精品久久久久久亚洲| 色偷偷噜噜噜亚洲男人| 国产精品欧美亚洲777777| 精品福利视频导航| 中国日韩欧美久久久久久久久| 日韩精品视频在线播放| 精品一区精品二区| 97久久超碰福利国产精品…| 国产精品偷伦一区二区| 亚洲天堂av在线播放| 中文字幕视频一区二区在线有码| 日韩女优在线播放| 91亚洲va在线va天堂va国| 欧美激情一级二级| 91久久久久久久久久久| 热re99久久精品国产66热| 在线视频一区二区| 国产精品久久久久久av福利软件| 成人国产在线激情| 奇米4444一区二区三区| 国精产品一区一区三区有限在线| 久久久久久久久久久av| 91精品国产91久久久久| 国产v综合ⅴ日韩v欧美大片| 川上优av一区二区线观看| 日韩av快播网址| 尤物yw午夜国产精品视频明星| 欧美成人免费va影院高清| 91精品久久久久久久久久另类| 91视频国产一区| 草民午夜欧美限制a级福利片| 久久综合电影一区| 国产综合在线视频| 久久久久久久久久久免费| 久久精品久久久久| 亚洲精品国产综合久久| 欧美韩日一区二区| 亚洲香蕉伊综合在人在线视看| 国产精品久久久久aaaa九色| 色小说视频一区| 日韩精品极品视频免费观看| 久久久www成人免费精品张筱雨| 91久久精品一区| 国产精品美女久久久久久免费| 欧美激情久久久久| 欧美亚洲日本黄色| 欧美一级大片视频| 国内外成人免费激情在线视频网站| 国产精品国产三级国产aⅴ9色| 久久久久久成人精品| 日本精品久久久久久久| 日本久久久久久久久久久| 亚洲国产精品网站| 91产国在线观看动作片喷水| 亚洲精品视频久久| 国产精品日韩欧美| 成人午夜激情网| 精品国产一区二区三区久久| 精品国产视频在线| 国产精品成人免费电影| 国产精品日韩电影| 欧美日韩亚洲精品内裤| 久久精品国产一区| 久久久国产精彩视频美女艺术照福利| 日韩av电影手机在线| 国内精品视频在线| 色偷偷av一区二区三区乱| 欧美成人精品三级在线观看| 国产日韩欧美自拍| 亚洲国产精品999| 91情侣偷在线精品国产| 欧美国产视频一区二区| 日韩中文字幕在线观看| 成人羞羞国产免费| 日韩精品亚洲元码| 成人性生交xxxxx网站| xvideos国产精品|