精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

在 Spring Boot 中使用 JSON Schem 實現復雜對象、可變結構參數校驗!

開發 前端
聲明式?的 JSON Schema 把“數據結構約束”從業務代碼中抽離,使得?接口契約?與?實現?分離,降低了后期變更的風險。統一的校驗入口(如自定義注解 + 參數解析器)讓所有入口點的校驗行為保持一致,避免遺漏。

1. 為什么要在 Spring Boot 中使用 JSON Schem進行校驗

1.1 傳統校驗方式的局限

? 手寫 POJO + @Valid:只能校驗映射到 Java 對象的字段,面對 深層嵌套、可變結構(如數組中對象字段不統一)時往往需要大量的自定義 DTO 與轉換代碼。

? 手動解析 + if 判斷:代碼冗余、易遺漏、錯誤信息不統一,維護成本隨業務增長呈指數級上升。

1.2 JSON Schema 的優勢

優勢

說明

聲明式

通過 JSON 文檔描述結構、約束、默認值,業務代碼無需關心細節。

可組合

支持 $ref 引用、allOf/anyOf/oneOf 組合,能夠復用公共子結構。

跨語言

同一套 Schema 可在前端、后端、測試腳本等多端共享,保證全鏈路一致性。

錯誤定位精準

校驗器會返回錯誤路徑(JSON Pointer),便于快速定位問題字段。

可擴展

支持自定義關鍵字,滿足業務特有的校驗需求(如唯一性、業務規則校驗)。

在微服務架構中,接口契約往往以 JSON Schema 形式保存于 API 文檔中心(如 Swagger、OpenAPI),將其直接用于運行時校驗是最自然的落地方式。

2. JSON Schema 基礎概念與核心關鍵字

2.1 基本結構

{
  "$schema":"http://json-schema.org/draft-07/schema#",
"title":"用戶信息",
"type":"object",
"properties":{
    "id":   {"type":"integer","minimum":1},
    "name":{"type":"string","minLength":1},
    "email":{"type":"string","format":"email"},
    "roles":{
      "type":"array",
      "items":{"type":"string","enum":["ADMIN","USER","GUEST"]},
      "minItems":1,
      "uniqueItems":true
    }
},
"required":["id","name","email"]
}

? type:限定數據類型(object、array、string、number、boolean、null)。

? properties:對象屬性的子 Schema。

? required:必須出現的屬性列表。

? enum:枚舉值集合。

? format:預定義格式(email、date-time、uri 等)。

2.2 常用關鍵字速查

關鍵字

作用

示例

minimum

 / maximum

數值范圍

"minimum": 0

exclusiveMinimum

 / exclusiveMaximum

開區間

"exclusiveMinimum": 0

minLength

 / maxLength

字符串長度

"minLength": 3

pattern

正則匹配

"pattern": "^[A-Z]{3}\\d{4}$"

minItems

 / maxItems

數組元素個數

"minItems": 1

uniqueItems

數組元素唯一性

"uniqueItems": true

additionalProperties

是否允許未聲明屬性

"additionalProperties": false

dependencies

屬性間依賴

"dependencies": { "creditCard": ["billingAddress"] }

allOf

 / anyOf / oneOf / not

組合約束

"allOf": [{...}, {...}]

$ref

引用外部或內部 Schema

"$ref": "#/definitions/Address"

default

默認值(僅在生成時有意義)

"default": "UNKNOWN"

2.3 版本兼容性

? Draft-07 是目前最廣泛支持的版本,幾乎所有 Java 校驗庫均兼容。

? 若項目需要 2020?12 或 2023?09 的新特性(如 unevaluatedProperties),需要確認所選庫已實現對應草案。

3. Spring Boot 項目準備與依賴選型

3.1 項目結構(示例)

src/main/java
 └─ com.example.demo
      ├─ controller
      ├─ service
      ├─ validator   // 自定義校驗器
      └─ config      // Spring 配置
src/main/resources
 └─ schemas
      └─ user-schema.json

3.2 主流 JSON Schema 校驗庫對比

Maven 坐標

主要特性

備注

NetworkNT json-schema-validator

com.networknt:json-schema-validator

完全實現 Draft?07、支持 $ref、自定義關鍵字、緩存

社區活躍,文檔完整

Everit JSON Schema

org.everit.json:org.everit.json.schema

輕量、異常信息友好、支持 Draft?07

依賴 org.json

Justify

org.leadpony.justify:justify

支持 Draft?07、流式校驗、低內存占用

適合大文件校驗

Jackson-module-jsonSchema

com.fasterxml.jackson.module:jackson-module-jsonSchema

與 Jackson 緊耦合、生成 Schema 為主

生成能力強,校驗功能相對弱

推薦:在 Spring Boot 項目中使用 NetworkNT,因為它提供了 JsonSchemaFactory、Validator、ValidationMessage 等易于集成的 API,并且對 $ref 的解析支持良好。

3.3 Maven 依賴示例

<dependencies>
    <!-- Spring Boot Web -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>

    <!-- JSON Schema Validator (NetworkNT) -->
    <dependency>
        <groupId>com.networknt</groupId>
        <artifactId>json-schema-validator</artifactId>
        <version>1.0.86</version>
    </dependency>

    <!-- Jackson (已隨 Spring Boot 引入) -->
    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-databind</artifactId>
    </dependency>

    <!-- Lombok(可選) -->
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <optional>true</optional>
    </dependency>
</dependencies>

注意:json-schema-validator 依賴 jackson-databind 進行 JSON 讀取,確保版本兼容。

4. 基于 json-schema-validator(NetworkNT)實現自動校驗

4.1 加載 Schema

package com.example.demo.config;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.networknt.schema.JsonSchema;
import com.networknt.schema.JsonSchemaFactory;
import com.networknt.schema.SpecVersion;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.io.InputStream;

@Configuration
publicclassJsonSchemaConfig {

    privatefinalObjectMappermapper=newObjectMapper();

    /** 讀取 classpath 下的 schema 文件并返回 JsonSchema 實例 */
    @Bean
    public JsonSchema userSchema()throws Exception {
        try (InputStreamis= getClass().getResourceAsStream("/schemas/user-schema.json")) {
            JsonNodeschemaNode= mapper.readTree(is);
            JsonSchemaFactoryfactory= JsonSchemaFactory.builder(JsonSchemaFactory.getInstance(SpecVersion.VersionFlag.V7))
                    .objectMapper(mapper)
                    .build();
            return factory.getSchema(schemaNode);
        }
    }
}

? SpecVersion.VersionFlag.V7 指定使用 Draft?07。

? 通過 @Bean 將 JsonSchema 注入 Spring 容器,后續可直接 @Autowired 使用。

4.2 編寫校驗工具類

package com.example.demo.validator;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.networknt.schema.JsonSchema;
import com.networknt.schema.ValidationMessage;
import org.springframework.stereotype.Component;

import java.util.Set;

@Component
publicclassJsonValidator {

    privatefinalObjectMappermapper=newObjectMapper();

    /** 校驗 JSON 字符串是否符合給定的 Schema,返回錯誤集合 */
    public Set<ValidationMessage> validate(String json, JsonSchema schema)throws Exception {
        JsonNodenode= mapper.readTree(json);
        return schema.validate(node);
    }

    /** 將錯誤集合轉為統一的錯誤信息字符串(可自行改造為錯誤對象) */
    public String formatErrors(Set<ValidationMessage> errors) {
        StringBuildersb=newStringBuilder();
        for (ValidationMessage msg : errors) {
            sb.append("路徑 ").append(msg.getPath())
              .append(" : ").append(msg.getMessage())
              .append("; ");
        }
        return sb.toString();
    }
}

? ValidationMessage#getPath() 返回 JSON Pointer(如 /roles/0),幫助前端定位。

? validate 方法拋出異常僅用于 JSON 解析錯誤,業務校驗錯誤通過返回集合處理。

4.3 在 Controller 中使用

package com.example.demo.controller;

import com.example.demo.validator.JsonValidator;
import com.networknt.schema.JsonSchema;
import com.networknt.schema.ValidationMessage;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.util.Set;

@RestController
@RequestMapping("/api/users")
publicclassUserController {

    @Autowired
    private JsonSchema userSchema;          // 注入的 Schema Bean

    @Autowired
    private JsonValidator validator;       // 校驗工具

    @PostMapping
    public ResponseEntity<?> createUser(@RequestBody String rawJson) {
        try {
            Set<ValidationMessage> errors = validator.validate(rawJson, userSchema);
            if (!errors.isEmpty()) {
                // 返回 400 并附帶錯誤詳情
                return ResponseEntity.badRequest()
                        .body(validator.formatErrors(errors));
            }

            // 業務處理:將 JSON 反序列化為 POJO、持久化等
            // User user = objectMapper.readValue(rawJson, User.class);
            // userService.save(user);

            return ResponseEntity.ok("校驗通過,業務處理完成");
        } catch (Exception e) {
            // JSON 解析異常或其他內部錯誤
            return ResponseEntity.status(500).body("服務器內部錯誤:" + e.getMessage());
        }
    }
}

? 核心思路:把原始請求體保留為字符串,先交給校驗器;只有在校驗通過后才進行業務層的對象映射與持久化。

? 這樣可以 避免因反序列化錯誤導致的異常泄露,并且錯誤信息直接對應 JSON Schema 定義。

5. 自定義關鍵字與擴展校驗邏輯

5.1 業務場景示例

假設業務要求 用戶名在同一租戶內唯一,這屬于跨記錄的業務規則,JSON Schema 本身不提供此類校驗。我們可以通過 自定義關鍵字 uniqueInTenant 來實現。

5.2 實現自定義關鍵字

package com.example.demo.config;

import com.networknt.schema.*;
import com.networknt.schema.keyword.Keyword;
import com.networknt.schema.keyword.KeywordFactory;
import org.springframework.stereotype.Component;

import java.util.Collections;
import java.util.Set;

/** 自定義關鍵字工廠 */
@Component
publicclassCustomKeywordFactoryimplementsKeywordFactory {

    @Override
    public Set<String> getKeywords() {
        return Collections.singleton("uniqueInTenant");
    }

    @Override
    public Keyword createKeyword(String keyword, JsonNode node) {
        returnnewUniqueInTenantKeyword(node);
    }

    /** 關鍵字實現類 */
    staticclassUniqueInTenantKeywordimplementsKeyword {
        privatefinal JsonNode schemaNode;

        UniqueInTenantKeyword(JsonNode schemaNode) {
            this.schemaNode = schemaNode;
        }

        @Override
        public ValidationResult validate(JsonNode node, JsonNode rootNode, String at) {
            // 這里的 node 為待校驗的字段值(如 username)
            Stringusername= node.asText();
            // 假設有一個租戶 ID 已經在上下文中獲取
            StringtenantId= ValidationContext.getCurrentTenantId();

            // 調用業務服務檢查唯一性(這里用偽代碼演示)
            booleanexists= UserService.isUsernameExistsInTenant(username, tenantId);
            if (exists) {
                return ValidationResult.error(at, "用戶名在當前租戶內已存在");
            }
            return ValidationResult.ok();
        }

        @Override
        public String getKeyword() {
            return"uniqueInTenant";
        }
    }
}

5.3 將自定義關鍵字注冊到 Factory

@Bean
public JsonSchemaFactory jsonSchemaFactory(ObjectMapper mapper, CustomKeywordFactory customFactory) {
    return JsonSchemaFactory.builder(JsonSchemaFactory.getInstance(SpecVersion.VersionFlag.V7))
            .objectMapper(mapper)
            .addKeyword(customFactory)   // 注冊自定義關鍵字
            .build();
}

5.4 在 Schema 中使用

{
  "$schema":"http://json-schema.org/draft-07/schema#",
"title":"用戶注冊",
"type":"object",
"properties":{
    "username":{
      "type":"string",
      "minLength":3,
      "uniqueInTenant":true   // 自定義關鍵字
    },
    "password":{
      "type":"string",
      "minLength":8
    }
},
"required":["username","password"]
}

注意:自定義關鍵字的實現必須是 無副作用 的純函數式校驗,否則可能導致并發安全問題。

6. 全局異常處理與錯誤信息統一返回

6.1 統一錯誤響應結構

{
  "timestamp":"2025-10-11T14:23:45.123+08:00",
"status":400,
"error":"Bad Request",
"message":"請求參數校驗失敗",
"details":[
    {"path":"/email","msg":"必須是合法的 email 地址"},
    {"path":"/roles/0","msg":"不允許的枚舉值"}
]
}

6.2 實現 @ControllerAdvice

package com.example.demo.exception;

import com.networknt.schema.ValidationMessage;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.time.ZonedDateTime;
import java.util.List;
import java.util.stream.Collectors;

@RestControllerAdvice
publicclassGlobalExceptionHandler {

    @ExceptionHandler(ValidationException.class)
    public ResponseEntity<ErrorResponse> handleValidation(ValidationException ex) {
        List<FieldError> fieldErrors = ex.getErrors().stream()
                .map(v -> newFieldError(v.getPath(), v.getMessage()))
                .collect(Collectors.toList());

        ErrorResponseresp=newErrorResponse(
                ZonedDateTime.now(),
                HttpStatus.BAD_REQUEST.value(),
                "Bad Request",
                "請求參數校驗失敗",
                fieldErrors
        );
        returnnewResponseEntity<>(resp, HttpStatus.BAD_REQUEST);
    }

    // 其它異常統一處理...
}

/** 自定義異常包裝 ValidationMessage 集合 */
classValidationExceptionextendsRuntimeException {
    privatefinal Set<ValidationMessage> errors;
    publicValidationException(Set<ValidationMessage> errors) {
        this.errors = errors;
    }
    public Set<ValidationMessage> getErrors() { return errors; }
}

/** 錯誤響應 DTO */
recordErrorResponse(
        ZonedDateTime timestamp,
        int status,
        String error,
        String message,
        List<FieldError> details) {}

recordFieldError(String path, String msg) {}

6.3 在業務層拋出統一異常

Set<ValidationMessage> errors = validator.validate(rawJson, userSchema);
if (!errors.isEmpty()) {
    throw new ValidationException(errors);
}

這樣,所有校驗錯誤都會統一走 GlobalExceptionHandler,前端只需要解析一次統一結構即可。

7. 在 Controller 中使用校驗注解的完整示例

7.1 定義自定義注解

package com.example.demo.annotation;

import org.springframework.core.annotation.AliasFor;
import java.lang.annotation.*;

@Target({ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public@interface JsonValidated {
    /** 指定使用的 Schema Bean 名稱 */
    @AliasFor("value")
    String schema()default"";

    @AliasFor("schema")
    String value()default"";
}

7.2 實現參數解析攔截器

package com.example.demo.resolver;

import com.example.demo.annotation.JsonValidated;
import com.example.demo.exception.ValidationException;
import com.example.demo.validator.JsonValidator;
import com.networknt.schema.JsonSchema;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.MethodParameter;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.support.WebDataBinderFactory;
import org.springframework.web.context.request.*;
import org.springframework.web.method.support.*;

import java.util.Set;

@Component
publicclassJsonValidatedArgumentResolverimplementsHandlerMethodArgumentResolver {

    @Autowired
    private JsonValidator validator;

    @Autowired
    private ApplicationContext ctx;   // 用于獲取 Schema Bean

    @Override
    publicbooleansupportsParameter(MethodParameter parameter) {
        return parameter.hasParameterAnnotation(JsonValidated.class)
                && parameter.getParameterType().equals(String.class);
    }

    @Override
    public Object resolveArgument(MethodParameter parameter,
                                  ModelAndViewContainer mavContainer,
                                  NativeWebRequest webRequest,
                                  WebDataBinderFactory binderFactory)throws Exception {

        JsonValidatedann= parameter.getParameterAnnotation(JsonValidated.class);
        StringschemaBeanName= ann.schema();
        JsonSchemaschema= (JsonSchema) ctx.getBean(schemaBeanName);

        Stringbody= webRequest.getNativeRequest(HttpServletRequest.class)
                .getReader()
                .lines()
                .reduce("", (acc, line) -> acc + line);

        Set<ValidationMessage> errors = validator.validate(body, schema);
        if (!errors.isEmpty()) {
            thrownewValidationException(errors);
        }
        return body;   // 校驗通過后返回原始 JSON 字符串
    }
}

7.3 注冊解析器

@Configuration
publicclassWebConfigimplementsWebMvcConfigurer {

    @Autowired
    private JsonValidatedArgumentResolver jsonResolver;

    @Override
    publicvoidaddArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {
        resolvers.add(jsonResolver);
    }
}

7.4 使用示例

@PostMapping("/register")
public ResponseEntity<?> register(@JsonValidated("userSchema") String userJson) {
    // 此時 userJson 已經通過 userSchema 校驗
    // 直接反序列化業務對象
    UserDto dto = objectMapper.readValue(userJson, UserDto.class);
    userService.register(dto);
    return ResponseEntity.ok("注冊成功");
}

通過自定義注解 + 參數解析器,校驗邏輯與業務代碼徹底解耦,控制器只關心業務本身。

8. 單元測試與集成測試最佳實踐

8.1 單元測試校驗工具

@SpringBootTest
classJsonValidatorTest {

    @Autowired
    private JsonValidator validator;

    @Autowired
    @Qualifier("userSchema")
    private JsonSchema schema;

    @Test
    voidvalidJsonShouldPass()throws Exception {
        Stringjson="""
        {
          "id": 10,
          "name": "張三",
          "email": "zhangsan@example.com",
          "roles": ["ADMIN"]
        }
        """;
        Set<ValidationMessage> errors = validator.validate(json, schema);
        assertTrue(errors.isEmpty());
    }

    @Test
    voidinvalidJsonShouldReturnErrors()throws Exception {
        Stringjson="""
        {
          "id": -1,
          "name": "",
          "email": "not-an-email",
          "roles": []
        }
        """;
        Set<ValidationMessage> errors = validator.validate(json, schema);
        assertFalse(errors.isEmpty());
        // 斷言具體錯誤路徑
        assertTrue(errors.stream().anyMatch(v -> v.getPath().equals("$.id")));
        assertTrue(errors.stream().anyMatch(v -> v.getPath().equals("$.email")));
    }
}

8.2 集成測試 Controller

@AutoConfigureMockMvc
@SpringBootTest
classUserControllerTest {

    @Autowired
    private MockMvc mvc;

    @Test
    voidcreateUserWhenInvalidShouldReturn400()throws Exception {
        Stringpayload="""
        {
          "id": 0,
          "name": "",
          "email": "bad",
          "roles": ["UNKNOWN"]
        }
        """;

        mvc.perform(post("/api/users")
                .contentType(MediaType.APPLICATION_JSON)
                .content(payload))
           .andExpect(status().isBadRequest())
           .andExpect(jsonPath("$.details[?(@.path=='/email')].msg")
                     .value("must be a valid email address"));
    }
}

? 使用 MockMvc 可以完整走一遍 請求 → 校驗 → 異常處理 → 響應 流程,確保錯誤信息的結構與內容符合約定。

9. 性能考量與緩存策略

9.1 Schema 加載成本

? 一次性加載:在啟動階段把所有 Schema 讀取為 JsonSchema 對象并放入 Spring 容器(如前文 @Bean),后續直接復用,避免每次請求重新解析。

? 緩存 JsonSchema:JsonSchemaFactory 本身提供內部緩存(基于 $id),但顯式緩存可以更好控制生命周期。

9.2 校驗過程的 CPU 與內存占用

? CPU:校驗本質是遍歷 JSON 樹并匹配關鍵字,復雜度與 JSON 大小呈線性關系。對大文件(>10?MB)建議使用 流式校驗(Justify)或分塊校驗。

? 內存:ObjectMapper.readTree 會把整個 JSON 讀取為樹結構,若業務只需要校驗而不需要后續對象映射,可在校驗后直接丟棄樹對象,減輕 GC 壓力。

9.3 并發場景下的優化

場景

優化手段

高并發短請求

采用 線程安全的 ObjectMapper(Spring Boot 默認已配置),避免每次創建實例。

大批量數據校驗

使用 批量緩存:一次性校驗一個數組,返回每條記錄的錯誤集合,減少線程切換。

多租戶環境

將租戶相關的自定義關鍵字實現 無狀態,通過 ThreadLocal 傳遞租戶上下文,避免在校驗器內部進行 I/O 查詢。

10. 進階特性:條件校驗、動態模式、格式化校驗

10.1 條件校驗(if/then/else)

{
  "type":"object",
"properties":{
    "type":{"enum":["PERSON","COMPANY"]},
    "personInfo":{"$ref":"#/definitions/person"},
    "companyInfo":{"$ref":"#/definitions/company"}
},
"required":["type"],
"if":{
    "properties":{"type":{"const":"PERSON"}}
},
"then":{
    "required":["personInfo"]
},
"else":{
    "required":["companyInfo"]
},
"definitions":{
    "person":{"type":"object","properties":{"name":{"type":"string"}}},
    "company":{"type":"object","properties":{"name":{"type":"string"}}}
}
}

? if/then/else 讓同一對象在不同業務分支下擁有不同必填字段,極大提升 單一 Schema 的表達能力。

10.2 動態模式(patternProperties)

{
  "type":"object",
"patternProperties":{
    "^prop_[0-9]+$":{"type":"string"}
},
"additionalProperties":false
}

? 適用于 鍵名可變、但鍵值類型統一的場景(如動態屬性表、標簽集合)。

10.3 自定義格式(format)

JSON Schema 預定義的 format 包括 email、date-time、uri 等。若業務需要 手機號、身份證號 等自定義格式,可通過 自定義 FormatValidator 注入到 JsonSchemaFactory:

JsonSchemaFactory factory = JsonSchemaFactory.builder()
        .formatValidator("phone", value -> 
            Pattern.matches("^1[3-9]\\d{9}$", value) ? Optional.empty()
                                                   : Optional.of("不是合法的手機號"))
        .build();

隨后在 Schema 中使用:

{
  "type": "string",
  "format": "phone"
}

11. 常見問題排查與調優技巧

問題

可能原因

解決方案

校驗報 null 指針

JSON 讀取為 null(空請求體)或 Schema 中 type 與實際不匹配

在 Controller 首先判斷請求體是否為空;在 Schema 明確 type 為 null 時使用 nullable:true(Draft?07 通過 type 數組實現)。

錯誤路徑不準確

使用了 additionalProperties:false 并在子對象中出現未聲明字段

將 additionalProperties:true 或在子對象中添加 patternProperties 捕獲動態字段。

自定義關鍵字不生效

未把自定義 KeywordFactory 注入到 JsonSchemaFactory

確認 JsonSchemaFactory 的構造器已調用 addKeyword(customFactory),并且 Bean 已被 Spring 管理。

性能瓶頸在 JSON 解析

大文件每次都完整讀取為樹結構

改用 流式校驗(Justify)或 分塊讀取(Jackson JsonParser)配合 Validator 的 validate(JsonParser) 方法。

多租戶唯一校驗失效

ValidationContext

 中租戶信息未正確傳遞

使用 ThreadLocal 或 Spring RequestContextHolder 在攔截器層面注入租戶 ID,確保自定義關鍵字能夠獲取到。

錯誤信息中文亂碼

ValidationMessage

 默認使用英文描述

在 JsonSchemaFactory 中通過 Locale 參數或自行翻譯 ValidationMessage#getMessage()

12. 結語:讓 JSON 校驗成為項目的安全防線

? 聲明式 的 JSON Schema 把“數據結構約束”從業務代碼中抽離,使得 接口契約 與 實現 分離,降低了后期變更的風險。

? 統一的校驗入口(如自定義注解 + 參數解析器)讓所有入口點的校驗行為保持一致,避免遺漏。

? 自定義關鍵字 與 格式校驗 能夠把業務規則直接嵌入 Schema,進一步提升系統的防御能力。

? 通過 緩存、流式校驗 與 錯誤信息統一化,我們可以在保持高吞吐的同時,提供友好的錯誤反饋。

責任編輯:武曉燕 來源: JAVA日知錄
相關推薦

2024-08-06 11:17:58

SpringJSON數據

2021-08-10 15:11:27

Spring Boot參數校驗

2021-08-12 10:32:50

Spring Boot參數校驗分組校驗

2023-11-26 09:10:34

WebSocketgreeting?在線用戶

2023-07-17 18:42:47

gRPCDemo項目

2022-02-08 17:07:54

Spring BooSpring Aop日志記錄

2025-05-27 07:07:29

2010-01-05 16:33:35

使用JSON

2011-05-25 13:22:05

PHPJSON

2023-03-30 07:48:46

接口鑒權SpringBoot

2009-06-15 16:23:39

Eclipse中使用SEclipse RCP

2022-11-10 07:53:54

Spring參數校驗

2024-12-03 08:00:00

2022-07-26 16:54:08

QuartzJava

2011-03-11 09:20:35

jQueryjavascript

2024-09-05 09:35:58

CGLIBSpring動態代理

2023-03-09 12:04:38

Spring文件校驗

2023-09-27 08:14:56

2024-11-01 10:40:32

2017-12-27 15:16:35

Spring BootFlyway數據庫
點贊
收藏

51CTO技術棧公眾號

5858s免费视频成人| 日韩电影免费一区| 欧美成人a视频| 妞干网在线观看视频| 深夜福利在线观看直播| 日韩中文字幕区一区有砖一区| 亚洲人线精品午夜| 天天操天天干天天做| 欧美卡一卡二| 91免费在线播放| 国产一区二中文字幕在线看| 久草视频手机在线观看| 亚洲区小说区图片区qvod| 欧美理论电影在线| 免费成人午夜视频| 免费在线看a| 99精品国产视频| 国产有码在线一区二区视频| 国产精品白浆一区二小说| 国内成人精品| 亚洲精品在线网站| jizz欧美性11| 三妻四妾的电影电视剧在线观看| 亚洲欧洲三级电影| 欧美黑人xxxxx| 国产夫妻自拍av| 日韩主播视频在线| 97视频色精品| 久久精品黄色片| 成人羞羞视频在线看网址| 亚洲国产福利在线| 樱花草www在线| 日韩欧美精品电影| 精品久久久久久久久久久久久| 亚洲精品白虎| 玖玖综合伊人| 99国产精品久久久久久久久久久| 91在线中文字幕| 在线观看国产黄| 欧美在线综合| 98视频在线噜噜噜国产| a级片在线观看免费| 99成人超碰| 最近日韩中文字幕中文| 法国伦理少妇愉情| 精品久久对白| 欧美成人福利视频| 日韩av福利在线观看| 国产精品久久久久久吹潮| 欧美性高潮在线| 青青青国产在线观看| 四虎亚洲成人| 一区二区三区久久| 路边理发店露脸熟妇泻火| 久久久久久国产精品免费无遮挡| 国产欧美日本一区视频| 欧美日韩在线一二三| 天天爱天天干天天操| 成人精品一区二区三区中文字幕| 亚洲最大成人在线| 国产99视频在线| 国产精品一级二级三级| 91九色在线观看| a级片在线播放| 国产福利一区在线| 粉嫩精品一区二区三区在线观看 | 91超碰中文字幕久久精品| 日本一区二区欧美| 国产九九精品| 国产精品第1页| 成人黄色激情视频| 老色鬼精品视频在线观看播放| 国产精品久久久久999| 在线观看国产成人| 国产精品888| 国产精品swag| 欧美孕妇孕交| 国产精品毛片久久久久久久| 一区二区国产日产| а√天堂资源地址在线下载| 一区二区三区在线免费| 亚洲人精品午夜射精日韩 | 热久久精品国产| 日本精品另类| 宅男噜噜噜66一区二区66| 视频区 图片区 小说区| 高潮久久久久久久久久久久久久 | 第三区美女视频在线| 国产精品水嫩水嫩| 久久久无码中文字幕久...| 免费电影网站在线视频观看福利| 午夜精品久久久久久久久久久 | 亚洲精品小说| 欧美黑人性视频| 你懂的国产视频| 久久婷婷av| 国产在线一区二区三区| 亚洲第一大网站| 久久午夜色播影院免费高清| 亚洲精品一区二区三区蜜桃久| 成人av福利| 午夜精品一区二区三区电影天堂 | 成人毛片免费看| 久久九九国产精品怡红院 | 男插女视频网站| 久久这里只有精品一区二区| 亚洲区在线播放| 侵犯稚嫩小箩莉h文系列小说| 很黄很黄激情成人| 国产精品爱啪在线线免费观看| 精品国产无码一区二区| 久久丝袜美腿综合| av中文字幕av| 国产精品字幕| 亚洲成人久久网| 99久久99久久精品免费| 亚洲三级影院| 91老司机在线| 欧美捆绑视频| 亚洲一区二区三区爽爽爽爽爽| 国产精彩免费视频| 久久视频社区| 在线性视频日韩欧美| 日韩欧美不卡视频| 国产乱码精品一区二区三区忘忧草| 久久久久久九九| 四虎亚洲精品| 欧美高清www午色夜在线视频| 国产草草浮力影院| 国产精品theporn| 国产久一一精品| 青青草免费在线视频| 亚洲综合免费观看高清完整版| 五月天激情视频在线观看| 亚洲精品亚洲人成在线| 欧美极品在线播放| 国产黄色高清视频| 国产精品久久久爽爽爽麻豆色哟哟| 国产男女免费视频| 亚洲国产视频二区| 久久综合电影一区| 一区二区视频免费| 日本一区二区免费在线| 国产女女做受ⅹxx高潮| 精品av导航| 欧美激情欧美狂野欧美精品| 国产白浆在线观看| 综合网在线视频| 日韩av.com| 日韩美女一区二区三区在线观看| 青青草精品毛片| 天天综合网在线| 亚洲国产一区在线观看| 日本少妇xxx| 综合激情在线| 亚洲中国色老太| 国产网站在线免费观看| 69堂亚洲精品首页| 成人免费精品动漫网站| 精品一区二区三区在线观看| 中文字幕日韩精品一区二区| 国产极品一区| 久热国产精品视频| 国内老熟妇对白xxxxhd| 中文字幕在线不卡一区| 91aaa精品| 欧美精品一卡| 国产伦一区二区三区色一情| www视频在线观看| 亚洲国产精品资源| 男人日女人网站| 国产欧美精品国产国产专区| 男女污污的视频| 国产国产精品| 国产成人精品日本亚洲11 | 热99在线视频| www在线免费观看| 欧美三级在线播放| 丝袜 亚洲 另类 欧美 重口| 国产91对白在线观看九色| 国产日韩亚洲欧美在线| 日韩极品少妇| 国产在线98福利播放视频| 国产黄a三级三级三级av在线看 | 97热精品视频官网| 国产高清一区在线观看| 欧美麻豆精品久久久久久| 久久久无码一区二区三区| 99精品视频一区二区三区| 99热这里只有精品在线播放| 999久久久国产精品| 91高跟黑色丝袜呻吟在线观看| 岛国片av在线| 亚洲午夜精品视频| 国产特级黄色片| 岛国av一区二区在线在线观看| 中文字幕免费在线看线人动作大片| 激情伊人五月天久久综合| 国产亚洲黄色片| 精品美女久久| av激情久久| 外国成人直播| 久久6精品影院| 九色视频在线播放| 日韩一二三区不卡| 夜夜爽妓女8888视频免费观看| 成人欧美一区二区三区小说| 国产美女喷水视频| 国产大陆a不卡| 男人插女人下面免费视频| 欧美日韩免费| 日韩免费av电影| 超碰地址久久| 成人写真福利网| 日本免费久久| 欧美精品第一页在线播放| av大片在线看| 亚洲国产精品久久久久秋霞蜜臀| 国产一区二区三区四区视频| 粉嫩老牛aⅴ一区二区三区| 男的操女的网站| 久久久精品黄色| 美女久久久久久久久| 韩日av一区二区| 黄色av免费在线播放| 国语精品一区| 亚洲天堂av免费在线观看| 国产成人一区二区三区影院| 国产精品国产三级国产专区53 | 国产第一区电影| av蜜臀在线| 欧美高清第一页| 国产一二区在线观看| 中文字幕免费精品一区高清| 天堂av在线资源| 亚洲成色777777在线观看影院| 国产又粗又猛又爽又黄91| 欧洲精品在线观看| 欧美一区免费看| 欧美性xxxx在线播放| 日韩精品乱码久久久久久| 亚洲综合色网站| 免费一级片在线观看| 中文字幕一区二区三区在线播放| 国产毛片久久久久久久| 2021久久国产精品不只是精品| 国产情侣久久久久aⅴ免费| 国产不卡视频在线观看| 波多野结衣在线免费观看| 国产在线播放一区| 国产福利在线免费| 麻豆91在线观看| 国产小视频精品| 久久精品av麻豆的观看方式| 国产wwwxx| 奇米色一区二区| 欧美第一页浮力影院| 久久99热这里只有精品| 91女神在线观看| 精油按摩中文字幕久久| 中文字幕色网站| 国产精品1024| 国产免费a级片| 成人avav影音| 亚洲av无码国产精品久久| 久久久国产午夜精品| 草草影院第一页| 欧美激情在线一区二区三区| 91禁男男在线观看| 亚洲同性同志一二三专区| 免费人成年激情视频在线观看| 亚洲午夜视频在线| 日韩特级黄色片| 在线观看不卡视频| 国产日韩欧美一区二区东京热| 欧美一级片在线看| 天堂在线资源库| 国产午夜精品一区二区三区| 色多多视频在线观看| 欧美大胆a视频| 国产在线美女| 国产精品高潮粉嫩av| 99综合99| 国产一级二级三级精品| 免费成人高清在线视频theav| 日韩一区二区三区高清| 亚洲一区 二区 三区| 韩日视频在线观看| 久久最新视频| 亚洲制服在线观看| 26uuu成人网一区二区三区| 日韩视频在线观看免费视频| 自拍偷拍亚洲欧美日韩| 丝袜亚洲另类欧美| 欧美日本亚洲| 欧美韩日高清| 国产成a人亚洲精v品在线观看| 国产精品永久| 无尽裸体动漫2d在线观看| 懂色av一区二区夜夜嗨| 国产成人av一区二区三区不卡| 中文字幕亚洲在| 欧美一二三区视频| 欧美日韩国产精品自在自线| 国产综合在线播放| 国产一级揄自揄精品视频| 自拍亚洲图区| 国产精品电影一区| 亚洲天堂中文字幕在线观看| 欧美日韩一区二区视频在线| 伊人久久大香线蕉精品组织观看| 91猫先生在线| 国产一区欧美二区| 黄免费在线观看| 亚洲一区二区av在线| 中文字幕日韩国产| 亚洲国产精品嫩草影院久久| 黄色网址在线免费| 国产精欧美一区二区三区| 国产精品45p| 亚洲成人在线视频网站| 国产精品久久久久久久免费软件 | 国产精品不卡| 免费av网址在线| 成人小视频免费观看| 强制高潮抽搐sm调教高h| 色综合咪咪久久| 日本激情一区二区| 裸体女人亚洲精品一区| julia一区二区三区中文字幕| 精品一区二区三区免费毛片| 欧美a级在线| 日韩高清第一页| 欧美经典一区二区三区| 天堂网中文字幕| 亚洲第一二三四五区| 日韩电影免费观看| 亚洲淫片在线视频| 99免费精品| 亚洲最大综合网| 久久综合久久久久88| 日韩av一二三区| 欧美mv日韩mv国产网站| av网址在线播放| 91免费人成网站在线观看18| 91偷拍一区二区三区精品| 能看的毛片网站| 久久久久久久久久看片| 亚洲另类在线观看| 亚洲精品久久久久久久久久久久久| 日韩成人伦理| 国产精品国产精品国产专区蜜臀ah| 欧美日韩福利| 野花视频免费在线观看| 亚洲老司机在线| 国产ts变态重口人妖hd| 欧美日韩福利视频| 国产精品一线| 黄色av网址在线播放| aa级大片欧美| 成人免费看片98欧美| 日韩极品精品视频免费观看| 刘亦菲一区二区三区免费看| 噜噜噜噜噜久久久久久91| 亚洲作爱视频| 法国空姐电影在线观看| 欧美亚洲一区二区三区四区| 97最新国自产拍视频在线完整在线看| 国产精品电影观看| 91亚洲国产| 国内自拍偷拍视频| 欧美午夜片欧美片在线观看| 九色网友自拍视频手机在线| 国产精品高潮呻吟久久av黑人| 色中色综合网| 国产男女无遮挡猛进猛出| 亚洲一二三四区不卡| 亚洲aⅴ在线观看| 国产精品扒开腿爽爽爽视频 | 国产性猛交xxxx免费看久久| 日韩精品一区二区三区av| 一区二区三区四区国产| 国产精品一区二区黑丝| 欧美激情亚洲综合| 在线播放日韩专区| 精品国产18久久久久久二百| 亚洲精品久久久久久久蜜桃臀| xfplay精品久久| 一区二区三区精| 久久久人成影片一区二区三区观看| 天堂99x99es久久精品免费| 在线黄色免费观看| 亚洲一区二区三区四区在线观看 | 欧美一区二区三区色| 成人影音在线| 先锋影音一区二区三区| 国产二区国产一区在线观看| 成人在线免费看视频| 久久久精品免费视频| 久久久久影视|