使用驗(yàn)證建議可以很容易地驗(yàn)證 Micronaut 控制器傳入的數(shù)據(jù)。
Micronaut 為具有 micronaut-validation 依賴項(xiàng)的 javax.validation 注解提供原生支持:
Gradle |
Maven |
implementation("io.micronaut:micronaut-validation")
|
<dependency>
<groupId>io.micronaut</groupId>
<artifactId>micronaut-validation</artifactId>
</dependency>
|
或者完全符合 micronaut-hibernate-validator 依賴的 JSR 380:
Gradle |
Maven |
implementation("io.micronaut.beanvalidation:micronaut-hibernate-validator")
|
<dependency>
<groupId>io.micronaut.beanvalidation</groupId>
<artifactId>micronaut-hibernate-validator</artifactId>
</dependency>
|
我們可以在類級(jí)別使用 javax.validation 注釋和 Validated 注釋來(lái)驗(yàn)證參數(shù)。
示例
Java |
Groovy |
Kotlin |
import io.micronaut.http.HttpResponse;
import io.micronaut.http.annotation.Controller;
import io.micronaut.http.annotation.Get;
import io.micronaut.validation.Validated;
import javax.validation.constraints.NotBlank;
import java.util.Collections;
@Validated // (1)
@Controller("/email")
public class EmailController {
@Get("/send")
public HttpResponse send(@NotBlank String recipient, // (2)
@NotBlank String subject) { // (2)
return HttpResponse.ok(Collections.singletonMap("msg", "OK"));
}
}
|
import io.micronaut.http.HttpResponse
import io.micronaut.http.annotation.Controller
import io.micronaut.http.annotation.Get
import io.micronaut.validation.Validated
import javax.validation.constraints.NotBlank
@Validated // (1)
@Controller("/email")
class EmailController {
@Get("/send")
HttpResponse send(@NotBlank String recipient, // (2)
@NotBlank String subject) { // (2)
HttpResponse.ok(msg: "OK")
}
}
|
import io.micronaut.http.HttpResponse
import io.micronaut.http.annotation.Controller
import io.micronaut.http.annotation.Get
import io.micronaut.validation.Validated
import javax.validation.constraints.NotBlank
@Validated // (1)
@Controller("/email")
open class EmailController {
@Get("/send")
open fun send(@NotBlank recipient: String, // (2)
@NotBlank subject: String): HttpResponse<*> { // (2)
return HttpResponse.ok(mapOf("msg" to "OK"))
}
}
|
使用 Validated 注釋控制器
主題和收件人不能為空。
如果發(fā)生驗(yàn)證錯(cuò)誤,則拋出 javax.validation.ConstraintViolationException。默認(rèn)情況下,集成的 io.micronaut.validation.exception.ConstraintExceptionHandler 處理異常,導(dǎo)致如下測(cè)試所示的行為:
示例測(cè)試
Java |
Groovy |
Kotlin |
@Test
public void testParametersAreValidated() {
HttpClientResponseException e = Assertions.assertThrows(HttpClientResponseException.class, () ->
client.toBlocking().exchange("/email/send?subject=Hi&recipient="));
HttpResponse<?> response = e.getResponse();
assertEquals(HttpStatus.BAD_REQUEST, response.getStatus());
response = client.toBlocking().exchange("/email/send?subject=Hi&recipient=me@micronaut.example");
assertEquals(HttpStatus.OK, response.getStatus());
}
|
def "test parameter validation"() {
when:
client.toBlocking().exchange('/email/send?subject=Hi&recipient=')
then:
def e = thrown(HttpClientResponseException)
def response = e.response
response.status == HttpStatus.BAD_REQUEST
when:
response = client.toBlocking().exchange('/email/send?subject=Hi&recipient=me@micronaut.example')
then:
response.status == HttpStatus.OK
}
|
"test params are validated"() {
val e = shouldThrow<HttpClientResponseException> {
client.toBlocking().exchange<Any>("/email/send?subject=Hi&recipient=")
}
var response = e.response
response.status shouldBe HttpStatus.BAD_REQUEST
response = client.toBlocking().exchange<Any>("/email/send?subject=Hi&recipient=me@micronaut.example")
response.status shouldBe HttpStatus.OK
}
|
要使用您自己的 ExceptionHandler 來(lái)處理約束異常,請(qǐng)使用 @Replaces(ConstraintExceptionHandler.class) 對(duì)其進(jìn)行注釋
通常您可能希望使用 POJO 作為控制器方法參數(shù)。
Java |
Groovy |
Kotlin |
import io.micronaut.core.annotation.Introspected;
import javax.validation.constraints.NotBlank;
@Introspected
public class Email {
@NotBlank // (1)
String subject;
@NotBlank // (1)
String recipient;
public String getSubject() {
return subject;
}
public void setSubject(String subject) {
this.subject = subject;
}
public String getRecipient() {
return recipient;
}
public void setRecipient(String recipient) {
this.recipient = recipient;
}
}
|
import io.micronaut.core.annotation.Introspected
import javax.validation.constraints.NotBlank
@Introspected
class Email {
@NotBlank // (1)
String subject
@NotBlank // (1)
String recipient
}
|
import io.micronaut.core.annotation.Introspected
import javax.validation.constraints.NotBlank
@Introspected
open class Email {
@NotBlank // (1)
var subject: String? = null
@NotBlank // (1)
var recipient: String? = null
}
|
您可以在 POJO 中使用 javax.validation 注釋。
使用 Validated 注釋您的控制器,并使用 @Valid 注釋綁定 POJO。
例子
Java |
Groovy |
Kotlin |
import io.micronaut.http.HttpResponse;
import io.micronaut.http.annotation.Body;
import io.micronaut.http.annotation.Controller;
import io.micronaut.http.annotation.Post;
import io.micronaut.validation.Validated;
import javax.validation.Valid;
import java.util.Collections;
@Validated // (1)
@Controller("/email")
public class EmailController {
@Post("/send")
public HttpResponse send(@Body @Valid Email email) { // (2)
return HttpResponse.ok(Collections.singletonMap("msg", "OK"));
}
}
|
import io.micronaut.http.HttpResponse
import io.micronaut.http.annotation.Body
import io.micronaut.http.annotation.Controller
import io.micronaut.http.annotation.Post
import io.micronaut.validation.Validated
import javax.validation.Valid
@Validated // (1)
@Controller("/email")
class EmailController {
@Post("/send")
HttpResponse send(@Body @Valid Email email) { // (2)
HttpResponse.ok(msg: "OK")
}
}
|
import io.micronaut.http.HttpResponse
import io.micronaut.http.annotation.Body
import io.micronaut.http.annotation.Controller
import io.micronaut.http.annotation.Post
import io.micronaut.validation.Validated
import javax.validation.Valid
@Validated // (1)
@Controller("/email")
open class EmailController {
@Post("/send")
open fun send(@Body @Valid email: Email): HttpResponse<*> { // (2)
return HttpResponse.ok(mapOf("msg" to "OK"))
}
}
|
用 Validated 注釋控制器
注釋 POJO 以使用 @Valid 進(jìn)行驗(yàn)證
POJO 的驗(yàn)證顯示在以下測(cè)試中:
Java |
Groovy |
Kotlin |
@Test
public void testPojoValidation() {
HttpClientResponseException e = assertThrows(HttpClientResponseException.class, () -> {
Email email = new Email();
email.subject = "Hi";
email.recipient = "";
client.toBlocking().exchange(HttpRequest.POST("/email/send", email));
});
HttpResponse<?> response = e.getResponse();
assertEquals(HttpStatus.BAD_REQUEST, response.getStatus());
Email email = new Email();
email.subject = "Hi";
email.recipient = "me@micronaut.example";
response = client.toBlocking().exchange(HttpRequest.POST("/email/send", email));
assertEquals(HttpStatus.OK, response.getStatus());
}
|
def "invoking /email/send parse parameters in a POJO and validates"() {
when:
Email email = new Email(subject: 'Hi', recipient: '')
client.toBlocking().exchange(HttpRequest.POST('/email/send', email))
then:
def e = thrown(HttpClientResponseException)
def response = e.response
response.status == HttpStatus.BAD_REQUEST
when:
email = new Email(subject: 'Hi', recipient: 'me@micronaut.example')
response = client.toBlocking().exchange(HttpRequest.POST('/email/send', email))
then:
response.status == HttpStatus.OK
}
|
"test pojo validation" {
val e = shouldThrow<HttpClientResponseException> {
val email = Email()
email.subject = "Hi"
email.recipient = ""
client.toBlocking().exchange<Email, Any>(HttpRequest.POST("/email/send", email))
}
var response = e.response
response.status shouldBe HttpStatus.BAD_REQUEST
val email = Email()
email.subject = "Hi"
email.recipient = "me@micronaut.example"
response = client.toBlocking().exchange<Email, Any>(HttpRequest.POST("/email/send", email))
response.status shouldBe HttpStatus.OK
}
|
Bean 注入在 Hibernate Validator 配置的自定義約束中受支持。
驗(yàn)證組
您可以使用驗(yàn)證組使用驗(yàn)證組來(lái)強(qiáng)制約束的子集。
Java |
Groovy |
Kotlin |
import javax.validation.groups.Default;
public interface FinalValidation extends Default {} // (1)
|
import javax.validation.groups.Default
interface FinalValidation extends Default {} // (1)
|
import javax.validation.groups.Default
interface FinalValidation : Default {} // (1)
|
定義自定義驗(yàn)證組。這一個(gè)擴(kuò)展了默認(rèn)值,因此使用該組完成的任何驗(yàn)證都將包括默認(rèn)組中的約束。
Java |
Groovy |
Kotlin |
import io.micronaut.core.annotation.Introspected;
import javax.validation.constraints.NotBlank;
@Introspected
public class Email {
@NotBlank // (1)
String subject;
@NotBlank(groups = FinalValidation.class) // (2)
String recipient;
public String getSubject() {
return subject;
}
public void setSubject(String subject) {
this.subject = subject;
}
public String getRecipient() {
return recipient;
}
public void setRecipient(String recipient) {
this.recipient = recipient;
}
}
|
import io.micronaut.core.annotation.Introspected
import javax.validation.constraints.NotBlank
@Introspected
class Email {
@NotBlank // (1)
String subject
@NotBlank(groups = FinalValidation) // (2)
String recipient
}
|
import io.micronaut.core.annotation.Introspected
import javax.validation.constraints.NotBlank
@Introspected
open class Email {
@NotBlank // (1)
var subject: String? = null
@NotBlank(groups = [FinalValidation::class]) // (2)
var recipient: String? = null
}
|
使用默認(rèn)驗(yàn)證組指定約束。只有在默認(rèn)處于活動(dòng)狀態(tài)時(shí)才會(huì)強(qiáng)制執(zhí)行此約束。
使用自定義 FinalValidation 驗(yàn)證組指定約束。只有在 FinalValidation 處于活動(dòng)狀態(tài)時(shí)才會(huì)強(qiáng)制執(zhí)行此約束。
使用 Validated 注釋您的控制器,指定將激活的驗(yàn)證組或讓它默認(rèn)為 Default。還要用@Valid 注釋綁定的POJO。
示例
Java |
Groovy |
Kotlin |
import io.micronaut.http.HttpResponse;
import io.micronaut.http.annotation.Body;
import io.micronaut.http.annotation.Controller;
import io.micronaut.http.annotation.Post;
import io.micronaut.validation.Validated;
import javax.validation.Valid;
import java.util.Collections;
@Validated // (1)
@Controller("/email")
public class EmailController {
@Post("/createDraft")
public HttpResponse createDraft(@Body @Valid Email email) { // (2)
return HttpResponse.ok(Collections.singletonMap("msg", "OK"));
}
@Post("/send")
@Validated(groups = FinalValidation.class) // (3)
public HttpResponse send(@Body @Valid Email email) { // (4)
return HttpResponse.ok(Collections.singletonMap("msg", "OK"));
}
}
|
import io.micronaut.http.HttpResponse
import io.micronaut.http.annotation.Body
import io.micronaut.http.annotation.Controller
import io.micronaut.http.annotation.Post
import io.micronaut.validation.Validated
import javax.validation.Valid
@Validated // (1)
@Controller("/email")
class EmailController {
@Post("/createDraft")
HttpResponse createDraft(@Body @Valid Email email) { // (2)
HttpResponse.ok(msg: "OK")
}
@Post("/send")
@Validated(groups = [FinalValidation]) // (3)
HttpResponse send(@Body @Valid Email email) { // (4)
HttpResponse.ok(msg: "OK")
}
}
|
import io.micronaut.http.HttpResponse
import io.micronaut.http.annotation.Body
import io.micronaut.http.annotation.Controller
import io.micronaut.http.annotation.Post
import io.micronaut.validation.Validated
import javax.validation.Valid
@Validated // (1)
@Controller("/email")
open class EmailController {
@Post("/createDraft")
open fun createDraft(@Body @Valid email: Email): HttpResponse<*> { // (2)
return HttpResponse.ok(mapOf("msg" to "OK"))
}
@Post("/send")
@Validated(groups = [FinalValidation::class]) // (3)
open fun send(@Body @Valid email: Email): HttpResponse<*> { // (4)
return HttpResponse.ok(mapOf("msg" to "OK"))
}
}
|
在不指定組的情況下使用 Validated 注釋意味著默認(rèn)組將處于活動(dòng)狀態(tài)。由于這是在類上定義的,因此它將適用于所有方法。
默認(rèn)驗(yàn)證組中的約束將被強(qiáng)制執(zhí)行,從類繼承。效果是調(diào)用此方法時(shí)不會(huì)強(qiáng)制執(zhí)行 email.recipient 上的 @NotBlank。
指定組意味著調(diào)用此方法時(shí)將強(qiáng)制執(zhí)行這些驗(yàn)證組。請(qǐng)注意,F(xiàn)inalValidation 擴(kuò)展了 Default,因此將強(qiáng)制執(zhí)行來(lái)自兩個(gè)組的約束。
Default 和 FinalValidation 驗(yàn)證組中的約束將被強(qiáng)制執(zhí)行,因?yàn)?nbsp;FinalValidation 擴(kuò)展了 Default。效果是當(dāng)調(diào)用此方法時(shí),將強(qiáng)制執(zhí)行電子郵件中的兩個(gè) @NotBlank 約束。
使用默認(rèn)驗(yàn)證組的 POJO 驗(yàn)證顯示在以下測(cè)試中:
Java |
Groovy |
Kotlin |
@Test
public void testPojoValidation_defaultGroup() {
HttpClientResponseException e = assertThrows(HttpClientResponseException.class, () -> {
Email email = new Email();
email.subject = "";
email.recipient = "";
client.toBlocking().exchange(HttpRequest.POST("/email/createDraft", email));
});
HttpResponse<?> response = e.getResponse();
assertEquals(HttpStatus.BAD_REQUEST, response.getStatus());
Email email = new Email();
email.subject = "Hi";
email.recipient = "";
response = client.toBlocking().exchange(HttpRequest.POST("/email/createDraft", email));
assertEquals(HttpStatus.OK, response.getStatus());
}
|
def "invoking /email/createDraft parse parameters in a POJO and validates using default validation groups"() {
when:
Email email = new Email(subject: '', recipient: '')
client.toBlocking().exchange(HttpRequest.POST('/email/createDraft', email))
then:
def e = thrown(HttpClientResponseException)
def response = e.response
response.status == HttpStatus.BAD_REQUEST
when:
email = new Email(subject: 'Hi', recipient: '')
response = client.toBlocking().exchange(HttpRequest.POST('/email/createDraft', email))
then:
response.status == HttpStatus.OK
}
|
"test pojo validation using default validation groups" {
val e = shouldThrow<HttpClientResponseException> {
val email = Email()
email.subject = ""
email.recipient = ""
client.toBlocking().exchange<Email, Any>(HttpRequest.POST("/email/createDraft", email))
}
var response = e.response
response.status shouldBe HttpStatus.BAD_REQUEST
val email = Email()
email.subject = "Hi"
email.recipient = ""
response = client.toBlocking().exchange<Email, Any>(HttpRequest.POST("/email/createDraft", email))
response.status shouldBe HttpStatus.OK
}
|
以下測(cè)試顯示了使用自定義 FinalValidation 驗(yàn)證組對(duì) POJO 的驗(yàn)證:
Java |
Groovy |
Kotlin |
@Test
public void testPojoValidation_finalValidationGroup() {
HttpClientResponseException e = assertThrows(HttpClientResponseException.class, () -> {
Email email = new Email();
email.subject = "Hi";
email.recipient = "";
client.toBlocking().exchange(HttpRequest.POST("/email/send", email));
});
HttpResponse<?> response = e.getResponse();
assertEquals(HttpStatus.BAD_REQUEST, response.getStatus());
Email email = new Email();
email.subject = "Hi";
email.recipient = "me@micronaut.example";
response = client.toBlocking().exchange(HttpRequest.POST("/email/send", email));
assertEquals(HttpStatus.OK, response.getStatus());
}
|
def "invoking /email/send parse parameters in a POJO and validates using FinalValidation validation group"() {
when:
Email email = new Email(subject: 'Hi', recipient: '')
client.toBlocking().exchange(HttpRequest.POST('/email/send', email))
then:
def e = thrown(HttpClientResponseException)
def response = e.response
response.status == HttpStatus.BAD_REQUEST
when:
email = new Email(subject: 'Hi', recipient: 'me@micronaut.example')
response = client.toBlocking().exchange(HttpRequest.POST('/email/send', email))
then:
response.status == HttpStatus.OK
}
|
"test pojo validation using FinalValidation validation group" {
val e = shouldThrow<HttpClientResponseException> {
val email = Email()
email.subject = "Hi"
email.recipient = ""
client.toBlocking().exchange<Email, Any>(HttpRequest.POST("/email/send", email))
}
var response = e.response
response.status shouldBe HttpStatus.BAD_REQUEST
val email = Email()
email.subject = "Hi"
email.recipient = "me@micronaut.example"
response = client.toBlocking().exchange<Email, Any>(HttpRequest.POST("/email/send", email))
response.status shouldBe HttpStatus.OK
}
|
更多建議: