最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

springMVC引入Validation的具體步驟詳解

 更新時(shí)間:2018年05月20日 10:40:13   作者:倒騎的驢  
本文簡單介紹如何引入validation的步驟,如何通過自定義validation減少代碼量,提高生產(chǎn)力,非常具有實(shí)用價(jià)值,需要的朋友可以參考下

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

本文中validation的實(shí)際實(shí)現(xiàn)委托給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

個(gè)性化處理validation錯(cuò)誤信息,返回給調(diào)用方的信息更加友好, 在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"/>

在項(xiàng)目類路徑上增加:validation_error_zh_CN.properties資源文件:

#the error msg for input validation
#common
field.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實(shí)現(xiàn):

ValidationExceptionResovler.java

@Slf4j
public class ValidationExceptionResovler extends AbstractHandlerExceptionResolver {
  public ValidationExceptionResovler() {
    // 設(shè)置order,在DefaultHandlerExceptionResolver之前執(zhí)行
    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 錯(cuò)誤信息,并組裝CommonResponse,返回給調(diào)用方。
   *
   * @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")
@ResponseBody
public BaseResponse buy(@RequestBody @Valid BuyFlowerRequest request) throws Exception {
 //......
} 

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

@Setter
@Getter
public class BuyFlowerRequest {

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

二級對象的validation

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

如下寫法:

@Setter
@Getter
public class BuyFlowerRequest {
  @NotEmpty(field = "花名")
  private String name;

  @Min(field = "價(jià)格", value = 1)
  private int price;

  @NotNull
  private List<PayType> payTypeList;

} 

@Setter
@Getter
public class PayType {

  @Valid
  @Min(value = 1)
  private int payType;

  @Valid
  @Min(value = 1)
  private int payAmount;
}

進(jìn)一步減少編碼量

為了減少編碼工作量,通過自定義Validation注解,嘗試將validation作用的filed名稱傳遞到 錯(cuò)誤信息的資源文件中,從而避免為每個(gè)域編寫不同的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均實(shí)現(xiàn)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如果沒有個(gè)性化需求,可以不用指明,validation組件會自行填充default message。

BuyFlowerRequest.java

@Setter
@Getter
public class BuyFlowerRequest {

  @NotEmpty(field = "花名")
  private String name;

  @Min(field = "價(jià)格", value = 1)
  private int price;
} 

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

支持GET請求

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

使用示例:

@RequestMapping(value = "/buy", method = RequestMethod.GET)
@ResponseBody
public BaseResponse detail(@Valid @ModelAttribute DetailFlowerRequest request) throws Exception {

  DetailFlowerResponse response = new DetailFlowerResponse();
  response.setName(request.getName());

  return ResultFactory.success(response, BaseResponse.class);
}

TODO

1、根據(jù)業(yè)務(wù)場景擴(kuò)展validation,如:日期格式、金額等

2、支持多個(gè)field關(guān)系校驗(yàn)的validation

 附:spring validation實(shí)現(xiàn)關(guān)鍵代碼

@RequestBody

實(shí)現(xiàn)類: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

實(shí)現(xiàn)類: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);
}

以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • maven私有鏡像倉庫nexus部署使用

    maven私有鏡像倉庫nexus部署使用

    Nexus在企業(yè)開發(fā)中還是比較常用的私有倉庫管理工具,本文主要介紹了maven私有鏡像倉庫nexus部署使用,具有一定的參考價(jià)值,感興趣的可以了解一下
    2024-07-07
  • Java仿12306圖片驗(yàn)證碼

    Java仿12306圖片驗(yàn)證碼

    這篇文章主要為大家詳細(xì)介紹了Java仿12306的圖片驗(yàn)證碼的相關(guān)資料,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2016-04-04
  • SpringAop的依賴注入方式

    SpringAop的依賴注入方式

    文章介紹了Spring框架的依賴注入(DI)和面向切面編程(AOP)的基本概念和實(shí)現(xiàn)方式,Spring通過IOC容器管理Bean的創(chuàng)建和依賴注入,并提供了多種AOP實(shí)現(xiàn)方式,包括代理機(jī)制和配置選項(xiàng)
    2025-02-02
  • Mybatis中通用Mapper的InsertList()用法

    Mybatis中通用Mapper的InsertList()用法

    文章介紹了通用Mapper中的insertList()方法在批量新增時(shí)的使用方式,包括自增ID和自定義ID的情況,對于自增ID,使用tk.mybatis.mapper.additional.insert.InsertListMapper包下的insertList()方法;對于自定義ID,需要重寫insertList()方法
    2025-02-02
  • JavaWeb響應(yīng)下載功能實(shí)例代碼(包含工具類)

    JavaWeb響應(yīng)下載功能實(shí)例代碼(包含工具類)

    今天通過本文給大家分享的是關(guān)于javaweb的響應(yīng)(response)下載功能,需要的朋友參考下吧
    2017-07-07
  • 基于Cookie與Session的Servlet?API會話管理操作

    基于Cookie與Session的Servlet?API會話管理操作

    這篇文章主要為大家介紹了基于Cookie與Session的Servlet?API會話管理操作詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-08-08
  • Spring Bean初始化及銷毀多種實(shí)現(xiàn)方式

    Spring Bean初始化及銷毀多種實(shí)現(xiàn)方式

    這篇文章主要介紹了Spring Bean初始化及銷毀多種實(shí)現(xiàn)方式,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-11-11
  • Java內(nèi)部類之間的閉包和回調(diào)詳解

    Java內(nèi)部類之間的閉包和回調(diào)詳解

    相信閉包和回調(diào)對每位學(xué)習(xí)Java的人來說都不陌生,那么今天小編和大家分享一篇關(guān)于Java內(nèi)部類之間的閉包和回調(diào),有需要的可以參考借鑒。
    2016-09-09
  • Idea配置超詳細(xì)圖文教程(2020.2版本)

    Idea配置超詳細(xì)圖文教程(2020.2版本)

    這篇文章主要介紹了Idea配置超詳細(xì)圖文教程(2020.2版本),本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-08-08
  • java自帶的四種線程池實(shí)例詳解

    java自帶的四種線程池實(shí)例詳解

    java線程的創(chuàng)建非常昂貴,需要JVM和OS(操作系統(tǒng))互相配合完成大量的工作,下面這篇文章主要給大家介紹了關(guān)于java自帶的四種線程池的相關(guān)資料,文中通過圖文介紹的非常詳細(xì),需要的朋友可以參考下
    2022-04-04

最新評論

万年县| 蒙自县| 兴业县| 青冈县| 德江县| 长治县| 斗六市| 汝城县| 疏附县| 马尔康县| 孝感市| 怀远县| 青田县| 比如县| 宁蒗| 永修县| 台安县| 天全县| 聂荣县| 大庆市| 呼伦贝尔市| 航空| 崇仁县| 遵义县| 安仁县| 兴和县| 离岛区| 河西区| 扎鲁特旗| 时尚| 苍溪县| 海盐县| 兰坪| 全州县| 云林县| 青阳县| 巴楚县| 蚌埠市| 抚远县| 斗六市| 陵水|