Micronaut 數(shù)據(jù)驗(yàn)證

2023-03-06 15:00 更新

使用驗(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"))
    }
}
  1. 使用 Validated 注釋控制器

  2. 主題和收件人不能為空。

如果發(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
}
  1. 您可以在 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"))
    }
}
  1. 用 Validated 注釋控制器

  2. 注釋 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)
  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
}
  1. 使用默認(rèn)驗(yàn)證組指定約束。只有在默認(rèn)處于活動(dòng)狀態(tài)時(shí)才會(huì)強(qiáng)制執(zhí)行此約束。

  2. 使用自定義 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"))
    }
}
  1. 在不指定組的情況下使用 Validated 注釋意味著默認(rèn)組將處于活動(dòng)狀態(tài)。由于這是在類上定義的,因此它將適用于所有方法。

  2. 默認(rèn)驗(yàn)證組中的約束將被強(qiáng)制執(zhí)行,從類繼承。效果是調(diào)用此方法時(shí)不會(huì)強(qiáng)制執(zhí)行 email.recipient 上的 @NotBlank。

  3. 指定組意味著調(diào)用此方法時(shí)將強(qiáng)制執(zhí)行這些驗(yàn)證組。請(qǐng)注意,F(xiàn)inalValidation 擴(kuò)展了 Default,因此將強(qiáng)制執(zhí)行來(lái)自兩個(gè)組的約束。

  4. 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
}


以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)