精品欧美一区二区三区在线观看 _久久久久国色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技術棧公眾號

成人在线播放av| 久久久精品国产网站| 国产精品wwwww| 日本欧美在线视频免费观看| 国产精品一区二区在线播放 | 国产精品九九视频| 91精品xxx在线观看| 国产精品理论片| 国产在线精品一区| 91精品国产乱码久久| 亚洲精品国产日韩| 久久午夜a级毛片| 精品中文字幕在线播放 | 国产日韩精品久久| 在线黄色av网站| 日韩网站在线| 美女精品视频一区| 欧美精品日韩在线| 亚瑟一区二区三区四区| 日韩欧美在线一区二区三区| 人妻无码视频一区二区三区| av在线小说| 亚洲男同1069视频| 天天爽天天狠久久久| 亚洲人妻一区二区三区| 国产大陆精品国产| 91九色精品视频| 中文字幕一区二区人妻痴汉电车| 国产欧美日韩一级| 久久99青青精品免费观看| 少妇av片在线观看| 久久99国产成人小视频| 亚洲第一区在线观看| aaaaa黄色片| 成人精品视频在线观看| 色婷婷激情久久| 国产白丝袜美女久久久久| 伊人在我在线看导航| 国产精品对白交换视频| 台湾成人av| 激情在线视频| 国产亚洲短视频| 欧美尤物一区| 九色在线播放| 欧美国产精品专区| 亚洲ai欧洲av| a中文在线播放| 国产精品免费av| 午夜免费电影一区在线观看| a视频网址在线观看| 国产嫩草影院久久久久| 五月天亚洲综合情| jizzjizz在线观看| 国产精品国产三级国产aⅴ原创| 欧美一区二区三区精美影视| 国产在线一二三| 亚洲国产精品av| 亚洲精品国产系列| 国产剧情在线| 亚洲宅男天堂在线观看无病毒| 992tv快乐视频| xxxx视频在线| 狠狠躁夜夜躁人人躁婷婷91| 乱子伦视频在线看| 亚洲成av在线| 欧美一区二区三区四区久久| 亚洲午夜精品在线观看| 6080亚洲理论片在线观看| 亚洲国产成人av在线| 粉嫩av懂色av蜜臀av分享| 五月激激激综合网色播| 在线看日韩欧美| 日韩成人短视频| 好吊一区二区三区| 欧美在线免费观看| 五月婷婷丁香在线| 国产一区二区三区四| 高清视频在线观看一区| 天堂成人在线| 成人欧美一区二区三区在线播放| 一级一片免费播放| а√天堂资源官网在线资源| 在线精品亚洲一区二区不卡| 亚洲一二三av| 黄色美女久久久| 少妇高潮 亚洲精品| 激情视频在线播放| 久久综合图片| 91免费看网站| 九色网友自拍视频手机在线| 亚洲免费观看在线观看| 无码人妻丰满熟妇区96| 日韩第二十一页| 亚洲国产日韩精品在线| 91制片厂在线| 一本一道久久综合狠狠老精东影业| 国产精品福利在线观看网址| 国产成人精品一区二区无码呦| 91色九色蝌蚪| 视色,视色影院,视色影库,视色网 日韩精品福利片午夜免费观看 | 国产av第一区| 欧美动物xxx| 欧美一级电影网站| 亚洲精品国产熟女久久久| 午夜精品剧场| 国产精品视频久| 天天综合在线视频| 亚洲综合一二三区| www.久久91| 九九热精品视频在线观看| 欧美高清在线视频观看不卡| 中文天堂在线资源| 久久亚洲精品小早川怜子| 91免费版看片| 婷婷精品久久久久久久久久不卡| 日韩成人在线视频观看| 免费人成在线观看| 久久成人麻豆午夜电影| 欧美婷婷久久| 久草在线中文最新视频| 日韩美女天天操| 日本不卡一二区| 蜜臀国产一区二区三区在线播放| 久久久com| 丁香花高清在线观看完整版| 3d动漫精品啪啪一区二区竹菊| 日韩毛片无码永久免费看| 夜夜精品视频| 国产欧美日韩亚洲| 色婷婷av在线| 日韩一区二区中文字幕| 小嫩苞一区二区三区| 日韩国产欧美在线观看| 久久久久久艹| 天天综合av| 精品视频在线观看日韩| 国产 欧美 日韩 在线| 成人av在线网| 欧美深夜福利视频| 欧美人与动xxxxz0oz| 久久久视频在线| 亚洲精品久久久狠狠狠爱 | 久久99国产精品一区| 日韩色性视频| 久久久97精品| 99精品国产99久久久久久97| 综合久久久久久久| 992kp免费看片| 欧美日韩hd| 99视频在线播放| 国产精品偷拍| 日韩av中文字幕在线免费观看| 国产精品16p| 成人精品国产一区二区4080| 日韩精品在线视频免费观看| 高清日韩欧美| 欧美亚洲另类激情另类| 神马精品久久| 欧美伊人久久久久久午夜久久久久| 97人妻人人揉人人躁人人| 三级久久三级久久| 在线不卡日本| 清纯唯美激情亚洲| 91av在线播放| 91在线视频| 欧美大片一区二区三区| 日本视频www| 26uuu精品一区二区三区四区在线| 久久久久人妻精品一区三寸| 成人3d精品动漫精品一二三| 国产在线久久久| 日本一本在线免费福利| 日韩电影中文 亚洲精品乱码| 国产情侣自拍av| 中文一区在线播放| 师生出轨h灌满了1v1| 99精品国产一区二区青青牛奶 | 亚洲黄色大片| 日本一区不卡| 日韩一区二区三区精品| 69久久夜色精品国产69乱青草| 国产系列在线观看| 日韩三级在线观看| 日韩久久中文字幕| 日韩毛片高清在线播放| 97人妻精品一区二区三区免费| 久久福利精品| 99久久99久久精品| 九色精品国产蝌蚪| 99国产在线观看| 成人看片网站| 欧美精品videosex牲欧美| 精品一二三区视频| 日韩欧美一区二区三区在线| 国产免费av一区| 亚洲综合一区二区三区| www..com.cn蕾丝视频在线观看免费版 | 国产成人高潮免费观看精品| 手机av免费在线| 亚洲人午夜精品| 国产综合视频在线| 欧美日韩激情一区| 国产精品视频一区在线观看| 亚洲色图19p| 少妇人妻好深好紧精品无码| 国产成人精品网址| 中文字幕国产免费| 另类国产ts人妖高潮视频| 色哺乳xxxxhd奶水米仓惠香| 免费欧美激情| 国语精品免费视频| 精品一区二区三区中文字幕视频| 国产99久久精品一区二区永久免费| 亚洲欧美成人影院| 日韩在线观看免费高清| 你懂得网站在线| 欧美精品一区二区精品网| 国产视频在线免费观看| 欧美亚州韩日在线看免费版国语版| av大片免费在线观看| 一区二区三区国产精品| 波兰性xxxxx极品hd| 中文av字幕一区| 人妻无码一区二区三区| 成人小视频免费在线观看| 欧美污在线观看| 精品一区二区三区蜜桃| 欧美三级理论片| 秋霞午夜av一区二区三区 | 美腿丝袜亚洲色图| 日韩欧美xxxx| 亚洲伊人观看| 国产综合av在线| 在线日韩欧美| 水蜜桃色314在线观看| 欧美国产三区| 欧美一级爱爱视频| 欧美激情第8页| 大地资源网在线观看免费官网| 亚洲情侣在线| 激情五月五月婷婷| 欧美成人嫩草网站| 欧美成人精品免费| 在线观看的日韩av| 国产a级片网站| 亚洲精选成人| 日日橹狠狠爱欧美超碰| 国产日韩高清一区二区三区在线| 免费观看美女裸体网站| 99视频精品| 国产福利视频在线播放| 老司机精品久久| 久久午夜夜伦鲁鲁一区二区| 老司机精品视频在线| 亚洲一区精品视频在线观看| 国产一区二区三区美女| 韩国三级与黑人| 波多野结衣亚洲一区| 毛茸茸多毛bbb毛多视频| 国产午夜亚洲精品不卡| 亚洲一二三精品| 亚洲免费观看高清| 一区二区三区免费高清视频| 精品久久久一区| 波多野结衣在线电影| 欧美日韩精品三区| www.污视频| 日韩av一区在线观看| 国产免费永久在线观看| 久久精品福利视频| 日本中文字幕中出在线| 日本午夜人人精品| 亚洲天堂网站| 国产日韩精品久久| 成人直播大秀| 日韩免费在线观看av| 免费亚洲网站| 最新av免费在线观看| 成人丝袜高跟foot| 中文字幕第24页| 亚洲自拍欧美精品| 在线观看日本网站| 制服丝袜亚洲色图| 欧美伦理影视网| 蜜臀久久99精品久久久无需会员 | 香蕉av777xxx色综合一区| 国产九九热视频| gogo大胆日本视频一区| 精品伦精品一区二区三区视频密桃| 亚洲天堂久久久久久久| 亚洲久久在线观看| 91精品欧美一区二区三区综合在 | 久久久久久亚洲| 69堂免费精品视频在线播放| 97人人模人人爽视频一区二区| 亚洲免费成人av在线| 国产经典久久久| 日韩国产欧美视频| 久久午夜夜伦鲁鲁片| 亚洲乱码国产乱码精品精可以看| 91美女免费看| 欧美不卡视频一区| 香蕉视频免费在线播放| 91成人在线播放| 亚洲精品观看| 亚洲一区二三| 日韩 欧美一区二区三区| 天天躁日日躁狠狠躁免费麻豆| 国产精品区一区二区三| 超碰中文字幕在线| 亚洲成人黄色网址| 成人免费看片| 91精品久久久久久久久久久| 亚洲精品白浆高清| 午夜免费福利小电影| 国产大片一区二区| 午夜激情福利网| 欧美日韩国产首页| 国产免费视频在线| 热久久这里只有| 亚洲+小说+欧美+激情+另类| 99久久免费观看| 国产精品中文有码| 日韩在线视频网址| 在线不卡的av| 香港伦理在线| 国产精品永久在线| 欧美日韩国产高清电影| 成人在线观看黄| 久久综合九色综合欧美亚洲| 天天操天天射天天爽| 日韩精品最新网址| 在线中文字幕视频观看| 亚洲一区二区三区久久 | 六月丁香久久丫| 可以看毛片的网址| 成人深夜视频在线观看| 久久综合色综合| 精品日韩一区二区三区免费视频| 中日韩高清电影网| 91在线观看网站| 黄色工厂这里只有精品| 在线看黄色的网站| 亚洲高清免费在线| 日本激情一区二区三区| 久久久久久久电影一区| 99ri日韩精品视频| 欧美大片在线播放| 久久蜜桃av一区二区天堂 | 强行糟蹋人妻hd中文| 日韩亚洲欧美综合| av中文在线资源| 麻豆成人av| 蜜桃精品在线观看| 久久久久久视频| 精品国产免费久久| 涩涩涩在线视频| 日韩一区不卡| 韩国精品一区二区| 免费看一级一片| 日韩精品在线视频| 91精品xxx在线观看| 在线视频不卡一区二区三区| 国产麻豆精品视频| 国产黄色片视频| 亚洲欧美日韩网| 欧美三级电影网址| 成人区一区二区| 久久久久久久综合| 国产精品怡红院| 久久久久久久久久国产精品| 妖精视频一区二区三区免费观看| 天天综合网日韩| 一区二区在线免费| 青青青草网站免费视频在线观看| 国产精品久久久久久超碰| 夜间精品视频| 免费无码一区二区三区| 欧美亚洲自拍偷拍| 女子免费在线观看视频www| 久久久精品国产一区二区三区| 麻豆视频观看网址久久| 久久久久久天堂| 国产午夜精品美女视频明星a级| 91麻豆精品国产91久久久更新资源速度超快| 8x8ⅹ国产精品一区二区二区| 91美女蜜桃在线| 亚洲一区二区激情| 韩日欧美一区二区| 久久影院100000精品| 一级特级黄色片| 欧美一区日本一区韩国一区| 在线视频cao| 超碰10000| 国产三级精品视频| 好吊视频一二三区| 国产中文日韩欧美| 亚洲欧美bt| 久久久久久久极品内射| 中文字幕久久精品|