參數校驗:簡單的就逐個手動寫代碼校驗,推薦用Valid,使用hibernate-validator提供的,如果參數不能通過校驗,報400錯誤,請求格式不正確:
步驟1:在參數對象的屬性上添加校驗注解如@NotBlank
步驟2:用@Valid注解controller方法的參數對象
常用校驗注解(
通過注解的message屬性自定義校驗錯誤的信息
):
@NotNull值不能為空
@Null值必須為空
@Pattern(regx=)字符串必須匹配正則表達式
@Size(min=,max=)集合元素數量必須在min和max之間
@CreditCardNumber(ignoreNonDigitCharacters=)字符串必須是信用卡號(按美國的標准校驗)
@Email字符串必須是email地址
@Length(min=,max=)字符串長度
@NotBlank字符串必須有字符
@NotEmpty字符串不為null,集合有元素
@Range(min=,max=)數字范圍
@SafeHtml字符串必須是安全的html
@URL字符串是合法的URL
@AssertFalse值必須是false
@AssertTrue值必須是true
@DecimalMax(value=,inclusive=)值必須小於等於(inclusive=true)/小於(inclusive=false)value指定的值,可以注解在字符串類型屬性上
@DecimalMin(value=,inclusive=)值必須大於等於(inclusive=true)/大於(inclusive=false)value指定的值,可以注解在字符串類型屬性上
@Digits(integer=,fraction=)數字格式檢查,integer指定整數部分最大長度,fraction指定小數部分最大長度
@Future值必須是未來的日期
@Past值必須是過去的日期
@Max(value=)值必須小於等於value指定的值,不能注解在字符串類型屬性上
@Min(value=)值必須大於等於value指定的值,不能注解在字符串類型屬性上
當參數校驗未通過,controller不會進入,某些場景,如參數校驗出錯,需要記錄業務日志,可在controller方法添加BindingResult參數,即可攜帶錯誤信息進入controller方法
BindingResult對象封裝了參數校驗的錯誤信息,其hasErrors方法表示有錯誤,使用getAllErrors然后stream流化遍歷獲取單條錯誤信息(錯誤信息可以定制):
例如:
import
lombok.
Data
;
import
javax.validation.constraints.
NotBlank
;
@Data
public class
User {
@NotBlank
(
message
=
"用戶名不能為空"
)
private
String
username
;
}
@GetMapping
(
"/user"
)
public
User
user
(
@Valid
User user
,
BindingResult errors) {
if
(errors.hasErrors()) {
errors.getAllErrors().stream().forEach(
// error -> System.out.println(error.getDefaultMessage())
error -> {
FieldError fieldError = (FieldError)error
; //Error是Object類型,轉換成FieldError可以獲取校驗錯誤的屬性字段
System.
out
.println(fieldError.getField() +
" : "
+ error.getDefaultMessage())
;
}
)
;
}
return
user
;
}
復雜的業務場景比如校驗傳入的username是否已經在數據庫中存在,需要自定義校驗邏輯,步驟(其實就是自定義校驗注解及其校驗邏輯):
1.寫校驗類
2.寫校驗注解
3.在屬性上使用(使用同系統提供的注解如@NotNull)
校驗類:
package
com.example.security.valid
;
import
javax.validation.ConstraintValidator
;
import
javax.validation.ConstraintValidatorContext
;
/**
* 自定義校驗類,實現ConstraintValidator接口,兩個泛型分別是自定義的校驗注解MyConstraint和注解生效的屬性類型
* Object可以放在任何類型的屬性上,String只能校驗String類型的屬性,如此
* initialize方法是校驗器初始化執行,isValid是校驗邏輯,value是屬性值,context校驗上下文,里面包含校驗注解里面的信息
* 返回true校驗通過,false校驗失敗,是javax.validation包提供的
*
* 該類里面可以通過@Autowire注入spring管理的bean。Spring會將實現了ConstraintValidator接口的類搞成bean,所以這個類不需要加@Component。
*/
public class
MyConstraintValidtor
implements
ConstraintValidator<
MyConstraint
,
Object> {
@Override
public void
initialize
(
MyConstraint
constraintAnnotation) {
System.
out
.println(
"MyConstraintValidtor initialize"
)
;
}
@Override
public boolean
isValid
(Object t
,
ConstraintValidatorContext constraintValidatorContext) {
return
t.equals(
"123456"
)
;
}
}
校驗注解:
package
com.example.security.valid
;
import
javax.validation.
Constraint
;
import
javax.validation.Payload
;
import
java.lang.annotation.*
;
/**
* 參考系統提供的校驗注解可知,message,groups,payload這3個屬性必須提供
*
@Constraint(validatedBy
= MyConstraintValidtor.class)指定該注解的校驗類
*/
@Target
({ElementType.
METHOD
,
ElementType.
FIELD
})
@Retention
(RetentionPolicy.
RUNTIME
)
@Constraint
(
validatedBy
= MyConstraintValidtor.
class
)
public
@
interface
MyConstraint
{
String
message
()
default
"校驗未通過"
;
Class<?>[]
groups
()
default
{}
;
Class<?
extends
Payload>[]
payload
()
default
{}
;
}