1 入参实体
package com
.company
.web
.dto
;
import javax
.validation
.constraints
.*
;
import java
.io
.Serializable
;
public class QuestionAnswerInputDTO implements Serializable{
@NotNull
@NotBlank(message
= "参数为空")
private String questions
;
@NotNull
@NotBlank(message
= "参数为空answer")
private String answers
;
public void setQuestions(String questions
) {
this.questions
= questions
;
}
public String
getQuestions() {
return questions
;
}
public void setAnswers(String answers
) {
this.answers
= answers
;
}
public String
getAnswers() {
return answers
;
}
}
2 统一返回数据
package com
.company
.web
.vo
.common
;
import com
.company
.web
.enums
.common
.*
;
public class ResponseVO<T> {
private Integer code
;
private String msg
;
private T data
;
public void setCode(Integer code
) {
this.code
= code
;
}
public Integer
getCode() {
return code
;
}
public void setMsg(String msg
) {
this.msg
= msg
;
}
public String
getMsg() {
return msg
;
}
public void setData(T data
) {
this.data
= data
;
}
public T
getData() {
return data
;
}
public ResponseVO(){}
public ResponseVO(Integer code
, String msg
) {
this.code
= code
;
this.msg
= msg
;
}
public ResponseVO(Integer code
, String msg
, T data
) {
this.code
= code
;
this.msg
= msg
;
this.data
= data
;
}
public static ResponseVO
ok() {
return new ResponseVO(EnumsCode
.SUCCESS
.getCode(), EnumsCode
.SUCCESS
.getMsg());
}
public static ResponseVO
ok(Object data
) {
return new ResponseVO(EnumsCode
.SUCCESS
.getCode(), EnumsCode
.SUCCESS
.getMsg(), data
);
}
public static ResponseVO
fail() {
return new ResponseVO(EnumsCode
.FAIL
.getCode(), EnumsCode
.FAIL
.getMsg());
}
public static ResponseVO
invalid() {
return new ResponseVO(EnumsCode
.INVALID
.getCode(), EnumsCode
.FAIL
.getMsg());
}
public static ResponseVO
invalid(String msg
) {
return new ResponseVO(EnumsCode
.INVALID
.getCode(), msg
);
}
public static ResponseVO
empty() {
return new ResponseVO(EnumsCode
.EMPTY
.getCode(), EnumsCode
.EMPTY
.getMsg());
}
public static ResponseVO
exception(Integer code
) {
switch (code
) {
case 4003:
return new ResponseVO(EnumsCode
.ARITHMETICEXCEPTION
.getCode(), EnumsCode
.ARITHMETICEXCEPTION
.getMsg());
case 4004:
return new ResponseVO(EnumsCode
.NULLPOINTEREXCEPTION
.getCode(), EnumsCode
.NULLPOINTEREXCEPTION
.getMsg());
}
return new ResponseVO(EnumsCode
.INVALID
.getCode(), EnumsCode
.INVALID
.getMsg());
}
}
3 数据校验
测试数据:
{
"questions":"",
"answers":"1234"
}
3.1 请求体数据校验
使用Valid类校验.
import javax
.validation
.Valid
;
Usage
package com
.company
.web
.controller
;
import org
.springframework
.web
.bind
.annotation
.CrossOrigin
;
import org
.springframework
.web
.bind
.annotation
.RequestMapping
;
import org
.springframework
.web
.bind
.annotation
.RequestBody
;
import org
.springframework
.web
.bind
.annotation
.RequestParam
;
import org
.springframework
.web
.bind
.annotation
.RestController
;
import org
.springframework
.web
.bind
.annotation
.RequestMethod
;
import org
.springframework
.beans
.factory
.annotation
.Autowired
;
import org
.springframework
.validation
.BindingResult
;
import org
.springframework
.validation
.FieldError
;
import org
.springframework
.validation
.annotation
.Validated
;
import org
.springframework
.validation
.BindException
;
import org
.slf4j
.Logger
;
import org
.slf4j
.LoggerFactory
;
import com
.company
.web
.dto
.*
;
import com
.company
.web
.service
.*
;
import com
.company
.web
.vo
.common
.*
;
import javax
.validation
.Valid
;
import javax
.validation
.constraints
.NotBlank
;
import java
.util
.List
;
@CrossOrigin(origins
= "*", maxAge
= 3600)
@RestController
@RequestMapping("/api/function/test")
public class TransactionalTestController {
static Logger logger
= LoggerFactory
.getLogger(TransactionalTestController
.class);
@Autowired
private IDataSaveService dataSaveService
;
@RequestMapping(value
= "/transactional/rollback/raw", method
= RequestMethod
.POST
)
public ResponseVO
saveDataWithRollback(@RequestBody @Valid QuestionAnswerInputDTO params
) {
}
}
3.2 请求URL数据校验
使用Validated类校验和NotBlank,NotNull等校验在类上使用注解@Validated
import org
.springframework
.validation
.annotation
.Validated
;
import javax
.validation
.constraints
.NotBlank
;
Usage
package com
.company
.web
.controller
;
import org
.springframework
.web
.bind
.annotation
.CrossOrigin
;
import org
.springframework
.web
.bind
.annotation
.RequestMapping
;
import org
.springframework
.web
.bind
.annotation
.RequestBody
;
import org
.springframework
.web
.bind
.annotation
.RequestParam
;
import org
.springframework
.web
.bind
.annotation
.RestController
;
import org
.springframework
.web
.bind
.annotation
.RequestMethod
;
import org
.springframework
.beans
.factory
.annotation
.Autowired
;
import org
.springframework
.validation
.BindingResult
;
import org
.springframework
.validation
.FieldError
;
import org
.springframework
.validation
.annotation
.Validated
;
import org
.springframework
.validation
.BindException
;
import org
.slf4j
.Logger
;
import org
.slf4j
.LoggerFactory
;
import com
.company
.web
.dto
.*
;
import com
.company
.web
.service
.*
;
import com
.company
.web
.vo
.common
.*
;
import javax
.validation
.Valid
;
import javax
.validation
.constraints
.NotBlank
;
import java
.util
.List
;
@CrossOrigin(origins
= "*", maxAge
= 3600)
@RestController
@RequestMapping("/api/function/test")
@Validated
public class TransactionalTestController {
static Logger logger
= LoggerFactory
.getLogger(TransactionalTestController
.class);
@Autowired
private IDataSaveService dataSaveService
;
@RequestMapping(value
= "/transactional/rollback/raw", method
= RequestMethod
.GET
)
public ResponseVO
saveDataWithRollback(@NotBlank(message
= "不能为空") @RequestParam("id") String id
) {
}
}
3.3 统一数据校验
3.3.1 统一异常捕获
package com
.company
.web
.exception
;
import org
.slf4j
.Logger
;
import org
.slf4j
.LoggerFactory
;
import org
.springframework
.web
.bind
.annotation
.RestControllerAdvice
;
import org
.springframework
.web
.bind
.annotation
.ExceptionHandler
;
import org
.springframework
.validation
.BindException
;
import org
.springframework
.validation
.BindingResult
;
import org
.springframework
.validation
.FieldError
;
import org
.springframework
.web
.bind
.annotation
.ResponseBody
;
import org
.springframework
.web
.bind
.MethodArgumentNotValidException
;
import org
.springframework
.web
.servlet
.mvc
.method
.annotation
.ResponseEntityExceptionHandler
;
import com
.company
.web
.vo
.common
.*
;
import java
.util
.List
;
import java
.util
.stream
.Collectors
;
import javax
.validation
.ConstraintViolationException
;
@RestControllerAdvice
public class GlobalExceptionHandler {
static Logger logger
= LoggerFactory
.getLogger(GlobalExceptionHandler
.class);
@ExceptionHandler(BindException
.class)
public ResponseVO
validationExceptionHandler(BindException e
) {
BindingResult bindingResult
= e
.getBindingResult();
List
<FieldError> fieldErrors
= bindingResult
.getFieldErrors();
String errorMsg
= "bindException";
logger
.info("Bind Validataion: {}", errorMsg
);
return ResponseVO
.invalid(errorMsg
);
}
@ExceptionHandler(MethodArgumentNotValidException
.class)
public ResponseVO
methodValidationExceptionHandler(MethodArgumentNotValidException e
) {
BindingResult bindingResult
= e
.getBindingResult();
List
<FieldError> fieldErrors
= bindingResult
.getFieldErrors();
fieldErrors
.forEach(fieldError
-> {
logger
.info("Invalid message: {}", fieldError
.getDefaultMessage());
});
fieldErrors
.stream().map(FieldError
::getDefaultMessage
).collect(Collectors
.toList());
logger
.info("field error: {}", fieldErrors
);
String errorMsg
= fieldErrors
.toString();
logger
.info("Method Validataion: {}", errorMsg
);
return ResponseVO
.empty();
}
@ExceptionHandler(NullPointerException
.class)
public ResponseVO
exceptionHandler(NullPointerException e
) {
String errorMsg
= e
.getMessage();
logger
.info("Null pointer Exception Validataion: {}", errorMsg
);
return ResponseVO
.exception(4004);
}
@ExceptionHandler(ArithmeticException
.class)
public ResponseVO
exceptionHandler(ArithmeticException e
) {
String errorMsg
= e
.getMessage();
logger
.info("Arithmetic Exception Validataion: {}", errorMsg
);
return ResponseVO
.exception(4003);
}
@ExceptionHandler(Exception
.class)
public ResponseVO
exceptionHandler(Exception e
) {
String errorMsg
= e
.getMessage();
logger
.info("Exception Validataion: {}", errorMsg
);
return ResponseVO
.invalid(errorMsg
);
}
}
3.3.2 数据校验
统一数据校验,将捕获的异常交给全局异常处理类省去了try…catch省去了BindingResult
package com
.company
.web
.controller
;
import org
.springframework
.web
.bind
.annotation
.CrossOrigin
;
import org
.springframework
.web
.bind
.annotation
.RequestMapping
;
import org
.springframework
.web
.bind
.annotation
.RequestBody
;
import org
.springframework
.web
.bind
.annotation
.RequestParam
;
import org
.springframework
.web
.bind
.annotation
.RestController
;
import org
.springframework
.web
.bind
.annotation
.RequestMethod
;
import org
.springframework
.beans
.factory
.annotation
.Autowired
;
import org
.springframework
.validation
.BindingResult
;
import org
.springframework
.validation
.FieldError
;
import org
.springframework
.validation
.annotation
.Validated
;
import org
.springframework
.validation
.BindException
;
import org
.slf4j
.Logger
;
import org
.slf4j
.LoggerFactory
;
import com
.company
.web
.dto
.*
;
import com
.company
.web
.service
.*
;
import com
.company
.web
.vo
.common
.*
;
import javax
.validation
.Valid
;
import javax
.validation
.constraints
.NotBlank
;
import java
.util
.List
;
@CrossOrigin(origins
= "*", maxAge
= 3600)
@RestController
@RequestMapping("/api/function/test")
@Validated
public class TransactionalTestController {
static Logger logger
= LoggerFactory
.getLogger(TransactionalTestController
.class);
@Autowired
private IDataSaveService dataSaveService
;
@RequestMapping(value
= "/transactional/rollback/raw", method
= RequestMethod
.POST
)
public ResponseVO
saveDataWithRollback(@RequestBody @Valid QuestionAnswerInputDTO params
) {
Boolean dataSaveFlag
= dataSaveService
.saveQuestionAndAnswerWithTransactionRollback(params
);
if(dataSaveFlag
) {
logger
.info("成功--保存问题和答案");
return ResponseVO
.ok();
}else {
logger
.info("失败--保存问题和答案");
return ResponseVO
.fail();
}
}
}
结果
{
"code": 4001,
"msg": "空数据",
"data": null
}
3.4 独立数据校验
独立数据校验使用try…catch捕获异常使用BindingResult进行数据校验
package com
.company
.web
.controller
;
import org
.springframework
.web
.bind
.annotation
.CrossOrigin
;
import org
.springframework
.web
.bind
.annotation
.RequestMapping
;
import org
.springframework
.web
.bind
.annotation
.RequestBody
;
import org
.springframework
.web
.bind
.annotation
.RequestParam
;
import org
.springframework
.web
.bind
.annotation
.RestController
;
import org
.springframework
.web
.bind
.annotation
.RequestMethod
;
import org
.springframework
.beans
.factory
.annotation
.Autowired
;
import org
.springframework
.validation
.BindingResult
;
import org
.springframework
.validation
.FieldError
;
import org
.springframework
.validation
.annotation
.Validated
;
import org
.springframework
.validation
.BindException
;
import org
.slf4j
.Logger
;
import org
.slf4j
.LoggerFactory
;
import com
.company
.web
.dto
.*
;
import com
.company
.web
.service
.*
;
import com
.company
.web
.vo
.common
.*
;
import javax
.validation
.Valid
;
import javax
.validation
.constraints
.NotBlank
;
import java
.util
.List
;
@CrossOrigin(origins
= "*", maxAge
= 3600)
@RestController
@RequestMapping("/api/function/test")
public class TransactionalTestController {
static Logger logger
= LoggerFactory
.getLogger(TransactionalTestController
.class);
@Autowired
private IDataSaveService dataSaveService
;
@RequestMapping(value
= "/transactional/rollback/raw", method
= RequestMethod
.POST
)
public ResponseVO
saveDataWithRollback(@RequestBody @Valid QuestionAnswerInputDTO params
, BindingResult bindingResult
) {
try {
if(bindingResult
.hasErrors()){
logger
.info("Error:{}", bindingResult
.getAllErrors());
List
<FieldError> fieldErrors
= bindingResult
.getFieldErrors();
fieldErrors
.forEach(fieldError
->{
logger
.error("Error filed: {}. \n Error message: {}", fieldError
.getField(), fieldError
.getDefaultMessage());
});
return ResponseVO
.empty();
}
Boolean dataSaveFlag
= dataSaveService
.saveQuestionAndAnswerWithTransactionRollback(params
);
if(dataSaveFlag
) {
logger
.info("成功--保存问题和答案");
return ResponseVO
.ok();
}else {
logger
.info("失败--保存问题和答案");
return ResponseVO
.fail();
}
}catch(Exception e
) {
e
.printStackTrace();
return ResponseVO
.invalid();
}
}
}
结果
{
"code": 4001,
"msg": "空数据",
"data": null
}
Error:[Field error in object 'questionAnswerInputDTO' on field 'questions': rejected value []; codes [NotBlank.questionAnswerInputDTO.questions,NotBlank.questions,NotBlank.java.lang.String,NotBlank]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [questionAnswerInputDTO.questions,questions]; arguments []; default message [questions]]; default message [参数为空]]
4 小结
数据校验:统一数据校验使用@Valid校验数据和@RestControllerAdvice增强Controller,借助ExceptionHandler捕获异常,省略try…catch数据校验:独立数据校验:使用BindingResult,独立对数据有性进行判断,需要使用try…catch数据校验:请求体校验,使用@Valid校验RequestBody数据校验:URL参数校验,使用@Validated在类上注解,同时使用NotNull等校验RequestParam
[参考文献] [1]https://blog.csdn.net/Xin_101/article/details/109206848