SpringBoot校验框架Validation及项目的国际化

一、概述

虽然前端系统对后台API接口调用之前都会做数据的校验,但是考虑到很多API接口是直接暴露在外网中,后台接口对传入的参数做校验是不可缺少的。比如判断字段非空,字段长度限制,邮箱格式验证等,这时就可以用到Validation。

二、创建Spring Boot工程

三、创建类

3.1  UserVo类

package com.anron.vo;

import lombok.Data;
import javax.validation.constraints.*;
import java.io.Serializable;
import java.util.List;

/**
 * @Author: Anron
 * @Date: 2020/3/29 17:30
 */
@Data
public class UserVo implements Serializable {
    private static final long serialVersionUID = 3869883763128105939L;

    @NotEmpty(message="{vo.UserVo.NAME_NOT_EMPTY}")
    private String name;

    @Min(value=18, message="{vo.UserVo.AGE_MUST_GREATERTHAN_18}")
    private int age;

    @NotEmpty(message="{vo.UserVo.HOBILLES_NOT_EMPTY}")
    private List<String> hobbies;

    @NotBlank(message="{vo.UserVo.ACCOUNT_NOT_EMPTY}")
    private String account;

    @NotNull(message="{vo.UserVo.PLATENO_NOT_EMPTY}")
    private String plateNo;

    @NotBlank(message="{vo.UserVo.ADDRESS_NOT_EMPTY}")
    private String address;

    @Size(min=6, max=20, message="{vo.UserVo.PASSWORD_SIZE}")
    @NotBlank(message="{vo.UserVo.PASSWORD_NOT_EMPTY}")
    private String password;

    @Email(message="{vo.UserVo.EMAIL_ERROR_FORMAT}")
    @NotBlank(message="{vo.UserVo.EMAIL_NOT_EMPTY}")
    private String email;
}

3.2  AppController类

package com.anron.controller;

import com.anron.dto.BaseDto;
import com.anron.util.WebControllerUtil;
import com.anron.vo.UserVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import javax.servlet.http.HttpServletRequest;

/**
 * @Author: Anron
 * @Date: 2020/3/29 17:32
 */
@Slf4j
@Controller
@RequestMapping(value = "/app")
public class AppController {

    @RequestMapping(value = "/addUser.do")
    @ResponseBody
    public BaseDto addUser(@RequestBody @Validated UserVo vo, BindingResult bindingResult, HttpServletRequest request) {
        log.info("---addUser start---vo:{}", vo.toString());
        WebControllerUtil.buildErrorMsg(bindingResult, request);
        return new BaseDto(true);
    }
}

3.3  BaseDto类

package com.anron.dto;

import lombok.Data;
import java.io.Serializable;

/**
 * @Author: Anron
 * @Date: 2020/3/29 17:34
 */
@Data
public class BaseDto implements Serializable {
    private static final long serialVersionUID = -1423147470994861814L;

    private String code;
    private String message;

    public BaseDto(boolean success) {
        if (success) {
            this.code = "0";
            this.message = "OK";
        }else {
            this.code = "500";
            this.message = "";
        }
    }
}

3.4  WebControllerUtil类

package com.anron.util;

import com.anron.exception.ServiceException;
import org.springframework.validation.BindingResult;
import org.springframework.validation.ObjectError;
import javax.servlet.http.HttpServletRequest;

/**
 * @Author: Anron
 * @Date: 2020/3/29 17:37
 */
public class WebControllerUtil {

    public static void buildErrorMsg(BindingResult bindingResult, HttpServletRequest request) {
        if (bindingResult.hasErrors()) {
            String errorMsg = "";
            for (ObjectError error : bindingResult.getAllErrors()) {
                errorMsg += error.getDefaultMessage() + ",";
            }
            throw new ServiceException(errorMsg.substring(0, errorMsg.length() - 1));
        }
    }
}

3.5  ServiceException类

package com.anron.exception;

import lombok.Data;

/**
 * @Author: Anron
 * @Date: 2020/3/29 17:38
 */
@Data
public class ServiceException extends RuntimeException {
    private static final long serialVersionUID = 5412240839931206939L;

    private int code;
    private String msg;

    public ServiceException(String msg){
        super();
        this.code = 501;
        this.msg = msg;
    }
}

3.6  ControllerExceptionHandler类

package com.anron.exception;

import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.nio.charset.StandardCharsets;

/**
 * @Author: Anron
 * @Date: 2020/3/29 17:46
 */
@ControllerAdvice
public class ControllerExceptionHandler {
    private static final int RESPONSE_STATUS = 200;

    @ExceptionHandler(ServiceException.class)
    public String handleException(HttpServletRequest request, HttpServletResponse response, ServiceException e) throws Exception {
        response.getOutputStream().write(e.toString().getBytes(StandardCharsets.UTF_8));
        response.setCharacterEncoding("UTF-8");
        response.setContentType("application/json");
        response.setStatus(RESPONSE_STATUS);
        response.getOutputStream().flush();
        return null;
    }
}

四、创建资源文件

4.1 ValidationMessages.properties

vo.UserVo.NAME_NOT_EMPTY=姓名不能为空
vo.UserVo.AGE_NOT_EMPTY=年龄不能为空
vo.UserVo.AGE_MUST_GREATERTHAN_18=年龄必须大于等于18岁
vo.UserVo.HOBILLES_NOT_EMPTY=兴趣爱好不能为空
vo.UserVo.ACCOUNT_NOT_EMPTY=账号不能为空
vo.UserVo.PLATENO_NOT_EMPTY=车牌号码不能为空
vo.UserVo.ADDRESS_NOT_EMPTY=地址不能为空
vo.UserVo.PASSWORD_SIZE=密码的长度应该在6和20之间
vo.UserVo.PASSWORD_NOT_EMPTY=密码不能为空
vo.UserVo.EMAIL_ERROR_FORMAT=邮箱格式错误
vo.UserVo.EMAIL_NOT_EMPTY=邮箱不能为空

4.2 ValidationMessages_zh_TW.properties

vo.UserVo.NAME_NOT_EMPTY=姓名不能為空
vo.UserVo.AGE_NOT_EMPTY=年齡不能為空
vo.UserVo.AGE_MUST_GREATERTHAN_18=年齡必須大於等於18嵗
vo.UserVo.HOBILLES_NOT_EMPTY=興趣愛好不能爲空
vo.UserVo.ACCOUNT_NOT_EMPTY=賬號不能爲空
vo.UserVo.PLATENO_NOT_EMPTY=車牌號碼不能爲空
vo.UserVo.ADDRESS_NOT_EMPTY=地址不能爲空
vo.UserVo.PASSWORD_SIZE=密碼的長度應該在6和20之間
vo.UserVo.PASSWORD_NOT_EMPTY=密碼不能爲空
vo.UserVo.EMAIL_ERROR_FORMAT=郵箱格式錯誤
vo.UserVo.EMAIL_NOT_EMPTY=郵箱不能爲空

4.3 ValidationMessages_en.properties

vo.UserVo.NAME_NOT_EMPTY=The name cannot be empty
vo.UserVo.AGE_NOT_EMPTY=The age cannot be empty
vo.UserVo.AGE_MUST_GREATERTHAN_18=Must be at least 18 years old
vo.UserVo.HOBILLES_NOT_EMPTY=A hobby cannot be empty
vo.UserVo.ACCOUNT_NOT_EMPTY=The account cannot be empty
vo.UserVo.PLATENO_NOT_EMPTY=The license plate number cannot be blank
vo.UserVo.ADDRESS_NOT_EMPTY=The address cannot be empty
vo.UserVo.PASSWORD_SIZE=The length of the password should be between 6 and 20
vo.UserVo.PASSWORD_NOT_EMPTY=The password cannot be empty
vo.UserVo.EMAIL_ERROR_FORMAT=Mailbox format error
vo.UserVo.EMAIL_NOT_EMPTY=The mailbox cannot be empty

五、创建http测试文件

5.1 AppController.addUser.http

POST http://localhost:8080/app/addUser.do
Accept: */*
Cache-Control: no-cache
Content-Type: application/json
Accept-Language: zh-CN;q=0.9,zh;q=0.8

{

}

###
POST http://localhost:8080/app/addUser.do
Accept: */*
Cache-Control: no-cache
Content-Type: application/json
Accept-Language: en,zh-CN;q=0.9,zh;q=0.8

{
"age":17
}


###
POST http://localhost:8080/app/addUser.do
Accept: */*
Cache-Control: no-cache
Content-Type: application/json
Accept-Language: zh-CN;q=0.9,zh;q=0.8

{
"age":18
}

###
POST http://localhost:8080/app/addUser.do
Accept: */*
Cache-Control: no-cache
Content-Type: application/json
Accept-Language: zh-TW;q=0.9,zh;q=0.8

{
"age":18,
"hobbies": []
}

###
POST http://localhost:8080/app/addUser.do
Accept: */*
Cache-Control: no-cache
Content-Type: application/json

{
"age":18,
"hobbies": ["sport", "food"]
}


###@NotEmpty(message="姓名不能为空"),所以"name": " "也通过
POST http://localhost:8080/app/addUser.do
Accept: */*
Cache-Control: no-cache
Content-Type: application/json

{
"age":18,
"hobbies": ["sport", "food"],
"name": " "
}

###@NotBlank(message="账号不能为空"),所以"account": " "不通过
POST http://localhost:8080/app/addUser.do
Accept: */*
Cache-Control: no-cache
Content-Type: application/json

{
"age":18,
"hobbies": ["sport", "food"],
"name": "anron",
"account": " "
}

###
POST http://localhost:8080/app/addUser.do
Accept: */*
Cache-Control: no-cache
Content-Type: application/json

{
"age":18,
"hobbies": ["sport", "food"],
"name": "anron",
"account": "admin"
}

###
POST http://localhost:8080/app/addUser.do
Accept: */*
Cache-Control: no-cache
Content-Type: application/json

{
"age":18,
"hobbies": ["sport", "food"],
"name": "anron",
"account": "admin",
"address": "shenzhen, china"
}

###
POST http://localhost:8080/app/addUser.do
Accept: */*
Cache-Control: no-cache
Content-Type: application/json

{
"age":18,
"hobbies": ["sport", "food"],
"name": "anron",
"account": "admin",
"address": "shenzhen, china",
"plateNo": ""
}

###
POST http://localhost:8080/app/addUser.do
Accept: */*
Cache-Control: no-cache
Content-Type: application/json

{
"age":18,
"hobbies": ["sport", "food"],
"name": "anron",
"account": "admin",
"address": "shenzhen, china",
"plateNo": "",
"password": "12"
}

###
POST http://localhost:8080/app/addUser.do
Accept: */*
Cache-Control: no-cache
Content-Type: application/json

{
"age":18,
"hobbies": ["sport", "food"],
"name": "anron",
"account": "admin",
"address": "shenzhen, china",
"plateNo": "",
"password": "123456"
}

###
POST http://localhost:8080/app/addUser.do
Accept: */*
Cache-Control: no-cache
Content-Type: application/json

{
"age":18,
"hobbies": ["sport", "food"],
"name": "anron",
"account": "admin",
"address": "shenzhen, china",
"plateNo": "",
"password": "123456",
"email": "error email address"
}

###
POST http://localhost:8080/app/addUser.do
Accept: */*
Cache-Control: no-cache
Content-Type: application/json

{
"age":18,
"hobbies": ["sport", "food"],
"name": "anron",
"account": "admin",
"address": "shenzhen, china",
"plateNo": "",
"password": "123456",
"email": "anron@gmail.com"
}

 

项目代码结构如下图:

  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
### 回答1: 要校验多个列表是否相同,可以按照以下步骤: 1. 定义一个自定义注解,用于标注需要校验的列表。例如: ```java @Target({ElementType.FIELD}) @Retention(RetentionPolicy.RUNTIME) @Documented @Constraint(validatedBy = ListValidator.class) public @interface SameList { String message() default "Lists are not same"; Class<?>[] groups() default {}; Class<? extends Payload>[] payload() default {}; } ``` 2. 定义一个校验器,用于校验被@SameList注解标注的字段。例如: ```java public class ListValidator implements ConstraintValidator<SameList, List<?>> { @Override public boolean isValid(List<?> value, ConstraintValidatorContext context) { if (value == null || value.size() == 0) { return true; } // 判断多个列表是否相同 // ... return true; // 返回校验结果 } } ``` 3. 在需要校验的实体类中,使用@SameList注解标注需要校验的列表。例如: ```java public class MyEntity { @SameList private List<String> list1; @SameList private List<Integer> list2; // getters and setters } ``` 4. 在需要进行校验的地方,使用Spring Boot提供的@Valid注解进行校验。例如: ```java @RestController public class MyController { @PostMapping("/myapi") public ResponseEntity<?> myApi(@RequestBody @Valid MyEntity myEntity) { // 处理请求 return ResponseEntity.ok().build(); } } ``` 在以上示例中,@Valid注解将会触发Spring Boot自动校验MyEntity对象中被@SameList注解标注的字段。如果列表不相同,则校验将失败,并且会抛出异常。否则,校验将会通过,程序将会继续执行。 ### 回答2: 可以通过比较多个List的大小、元素以及顺序来校验它们是否一样。下面是一个使用Spring Boot校验多个List是否一样的示例代码: ```java import java.util.ArrayList; import java.util.List; public class ListComparator { public static boolean compareLists(List<?> list1, List<?> list2) { if (list1 == null && list2 == null) { return true; } if ((list1 == null && list2 != null) || (list1 != null && list2 == null)) { return false; } if (list1.size() != list2.size()) { return false; } for (int i = 0; i < list1.size(); i++) { if (!list1.get(i).equals(list2.get(i))) { return false; } } return true; } public static void main(String[] args) { List<Integer> list1 = new ArrayList<>(); list1.add(1); list1.add(2); list1.add(3); List<Integer> list2 = new ArrayList<>(); list2.add(1); list2.add(2); list2.add(3); List<Integer> list3 = new ArrayList<>(); list3.add(1); list3.add(2); list3.add(4); System.out.println(compareLists(list1, list2)); // 输出 true System.out.println(compareLists(list1, list3)); // 输出 false } } ``` 以上代码中的`compareLists`方法用于比较两个List是否一样,在比较过程中,首先检查两个List是否同时为空或同时不为空,然后比较它们的大小是否一致,最后逐个比较元素是否相等。在`main`方法中,我们创建了几个不同的List,并使用`compareLists`方法进行比较,最终输出比较结果。在本示例中,`list1`和`list2`的元素相同,而`list1`和`list3`的元素不同,所以比较结果分别为true和false。 以上是通过比较List的大小、元素以及顺序来校验多个List是否一样的方法,你也可以根据实际需求自定义校验规则。 ### 回答3: 在Spring Boot中,我们可以使用CollectionUtils工具类来校验多个List是否一样。 首先,我们需要导入spring-boot-starter-validation依赖,该依赖包含了Hibernate Validator校验框架。 然后,我们可以定义一个自定义的校验注解,用于校验多个List是否一样。例如: ```java @Target({ElementType.TYPE, ElementType.ANNOTATION_TYPE}) @Retention(RetentionPolicy.RUNTIME) @Constraint(validatedBy = ListEqualsValidator.class) public @interface ListEquals { String message() default "Lists are not equal"; Class<?>[] groups() default {}; Class<? extends Payload>[] payload() default {}; } ``` 接下来,我们需要实现一个校验器ListEqualsValidator,用于校验多个List是否一样。例如: ```java public class ListEqualsValidator implements ConstraintValidator<ListEquals, List<?>> { @Override public boolean isValid(List<?> value, ConstraintValidatorContext context) { return CollectionUtils.isEqualCollection(value); } } ``` 最后,我们可以在需要校验的类上使用@ListEquals注解进行校验。例如: ```java @ListEquals public class MyListValidation { private List<String> list1; private List<String> list2; // getter and setter } ``` 在使用时,我们可以通过调用Validator进行校验。例如: ```java @Autowired private Validator validator; public void validate(MyListValidation myListValidation) { Set<ConstraintViolation<MyListValidation>> violations = validator.validate(myListValidation); if (!violations.isEmpty()) { // 校验不通过,做相应处理 } } ``` 以上就是使用Spring Boot校验多个List是否一样的简单步骤。
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值