一、概述
虽然前端系统对后台 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"
}
项目代码结构如下图:
作者:anron
来源链接:
https://blog.csdn.net/anron/article/details/105180879