自定義hibernate validator註解對字段進行校驗

1.  hibernate validator註解在web項目中經常用到,是一個很好用的字段校驗器,可以對前端傳入的參數進行判斷,如是否爲空,是否滿足正則規定的格式等等。

2. 假設有一個業務場景,需要判斷前端傳入的用戶是否存在,而項目中有很多地方會用到此判斷,此時可以構造一個自定義校驗器進行字段校驗,在需要的時候只需要加上此註解即可。

3. controller接口

package net.mshome.twisted.tmall.common.controller;


import net.mshome.twisted.tmall.common.dto.UserAddDTO;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;

import org.springframework.web.bind.annotation.RestController;

import javax.validation.Valid;

/**
 * <p>
 * 前端控制器
 * </p>
 *
 * @author tangjizhou
 * @since 2019-05-04
 */
@RestController
@RequestMapping("/user")
@Validated
public class UserController {


    @PostMapping("/register")
    public void register(@RequestBody @Valid UserAddDTO userAddDTO) {

    }

}

4. 前端傳入的參數,注意此處的自定義註解 @UserField

package net.mshome.twisted.tmall.common.dto;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import net.mshome.twisted.tmall.common.annotation.UserField;

import javax.validation.constraints.NotNull;

/**
 * @author tangjizhou
 * @date 2019-06-20
 * @description 前端post傳入參數
 */
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class UserAddDTO {

    /**
     * 假設此處可填寫多個用戶,以逗號隔開
     */
    @UserField(message = "填寫的用戶{}不存在")
    @NotNull(message = "請填寫用戶")
    private String usernames;

}

5. 自定義註解

package net.mshome.twisted.tmall.common.annotation;

import javax.validation.Constraint;
import javax.validation.Payload;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

import static java.lang.annotation.ElementType.*;

/**
 * @author tangjizhou
 * @date 2019-06-20
 * @description 驗證用戶是否存在註解
 */
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE})
@Constraint(validatedBy = UserFieldValidator.class)
public @interface UserField {

    String message() default "";

    String defaultMessage = "用戶{}不存在";

    Class<?>[] groups() default {};

    Class<? extends Payload>[] payload() default {};

}

6. 實現註解功能

package net.mshome.twisted.tmall.common.annotation;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import net.mshome.twisted.tmall.common.entity.User;
import net.mshome.twisted.tmall.common.service.IUserService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import java.util.Arrays;
import java.util.stream.Collectors;

/**
 * @author tangjizhou
 * @date 2019-06-20
 * @description 驗證用戶是否存在
 */
@Component
public class UserFieldValidator implements ConstraintValidator<UserField, String> {

    private String defaultMessage;

    @Autowired
    private IUserService userService;

    @Override
    public void initialize(UserField constraint) {
        this.defaultMessage = constraint.defaultMessage;
    }

    @Override
    public boolean isValid(String usernames, ConstraintValidatorContext context) {

        // 如果什麼都沒有輸入,則不判斷,直接返回
        if (StringUtils.isEmpty(usernames)) {
            return true;
        }

        // 判斷用戶是否存在
        String illegalUsernames = Arrays.stream(usernames.split(",")).distinct().map(username -> {
            User user = userService.getOne(new QueryWrapper<>(User.builder().username(username).build()));
            return user == null ? username : null;
        }).filter(StringUtils::isNotEmpty).collect(Collectors.joining(","));

        // 所有用戶都存在,返回true
        if (StringUtils.isBlank(illegalUsernames)) {
            return true;
        }

        /* ************************ 如果存在非法用戶****************************/

        // 禁用直接返回默認的message
        context.disableDefaultConstraintViolation();

        // 獲取註解配置的message
        String messageTemplate = context.getDefaultConstraintMessageTemplate();
        messageTemplate = StringUtils.isEmpty(messageTemplate) ? defaultMessage : messageTemplate;

        // 構造返回信息,進行佔位符替換
        context.buildConstraintViolationWithTemplate(StringUtils.replace(messageTemplate, "{}", illegalUsernames))
                .addConstraintViolation();

        return false;
    }
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章