缘起

做SpringBoot项目时需要验证request参数,e.g:

这样的需求太常见了,几乎每个Controller接口都要验证,对于普通的校验规则如果手动校验,重复又繁琐,而且特别不优雅。试想,谁想在每个方法前都要排上一长串校验方法呢?

public String hello(@RequestParam("name") String name) throws Exception {validateNotNull(name);validateNotBlank(name);...// business logic
}

所以,一个常见的需求出现了:有没有可以自动校验Controller层请求参数的框架?
使得我们可以使用更加轻便的方式(例如注解)进行参数校验,而不用吭哧吭哧地手写校验逻辑。
答案是有的,Java设计者们和Java社区早就遇到了个问题,并且提出了解决方案。

这就是Bean Validation。

Bean Validation

Bean Validation规范在2009年就被提出,主要用来解决Java bean的验证问题,这在Bean Validation的Description中描述得很清楚:

This JSR will define a meta-data model and API for JavaBeanTM validation based on annotations, with overrides and extended meta-data through the use of XML validation descriptors.

可以看到,Bean Validation解决的问题比之前描述的场景更为普遍:不仅仅是Controller层参数,而是使用注解进行任意Java Bean的验证问题。

Bean Validation自提出至今已经历经了JSR303,JSR349和JSR380三个提案(详见:JSR:Bean Validation,有关JSR请读者自行了解,简单地说,就是Java官方给出的规范建议,但不提供实现)。
根据JSR,Java EE 提供了javax.validation.api(java EE改名为jakarta EE后,javax.validation.api也更名为jakarta.validation.api),而Apache Hibernate根据该api提供了hibernate-validator,平常我们说的Validate框架99.99%指的就是hibernate-validator。
简单捋一下,就是:

#mermaid-svg-v87RZAQeUuqERsl3 .label{font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family);fill:#333;color:#333}#mermaid-svg-v87RZAQeUuqERsl3 .label text{fill:#333}#mermaid-svg-v87RZAQeUuqERsl3 .node rect,#mermaid-svg-v87RZAQeUuqERsl3 .node circle,#mermaid-svg-v87RZAQeUuqERsl3 .node ellipse,#mermaid-svg-v87RZAQeUuqERsl3 .node polygon,#mermaid-svg-v87RZAQeUuqERsl3 .node path{fill:#ECECFF;stroke:#9370db;stroke-width:1px}#mermaid-svg-v87RZAQeUuqERsl3 .node .label{text-align:center;fill:#333}#mermaid-svg-v87RZAQeUuqERsl3 .node.clickable{cursor:pointer}#mermaid-svg-v87RZAQeUuqERsl3 .arrowheadPath{fill:#333}#mermaid-svg-v87RZAQeUuqERsl3 .edgePath .path{stroke:#333;stroke-width:1.5px}#mermaid-svg-v87RZAQeUuqERsl3 .flowchart-link{stroke:#333;fill:none}#mermaid-svg-v87RZAQeUuqERsl3 .edgeLabel{background-color:#e8e8e8;text-align:center}#mermaid-svg-v87RZAQeUuqERsl3 .edgeLabel rect{opacity:0.9}#mermaid-svg-v87RZAQeUuqERsl3 .edgeLabel span{color:#333}#mermaid-svg-v87RZAQeUuqERsl3 .cluster rect{fill:#ffffde;stroke:#aa3;stroke-width:1px}#mermaid-svg-v87RZAQeUuqERsl3 .cluster text{fill:#333}#mermaid-svg-v87RZAQeUuqERsl3 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family);font-size:12px;background:#ffffde;border:1px solid #aa3;border-radius:2px;pointer-events:none;z-index:100}#mermaid-svg-v87RZAQeUuqERsl3 .actor{stroke:#ccf;fill:#ECECFF}#mermaid-svg-v87RZAQeUuqERsl3 text.actor>tspan{fill:#000;stroke:none}#mermaid-svg-v87RZAQeUuqERsl3 .actor-line{stroke:grey}#mermaid-svg-v87RZAQeUuqERsl3 .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333}#mermaid-svg-v87RZAQeUuqERsl3 .messageLine1{stroke-width:1.5;stroke-dasharray:2, 2;stroke:#333}#mermaid-svg-v87RZAQeUuqERsl3 #arrowhead path{fill:#333;stroke:#333}#mermaid-svg-v87RZAQeUuqERsl3 .sequenceNumber{fill:#fff}#mermaid-svg-v87RZAQeUuqERsl3 #sequencenumber{fill:#333}#mermaid-svg-v87RZAQeUuqERsl3 #crosshead path{fill:#333;stroke:#333}#mermaid-svg-v87RZAQeUuqERsl3 .messageText{fill:#333;stroke:#333}#mermaid-svg-v87RZAQeUuqERsl3 .labelBox{stroke:#ccf;fill:#ECECFF}#mermaid-svg-v87RZAQeUuqERsl3 .labelText,#mermaid-svg-v87RZAQeUuqERsl3 .labelText>tspan{fill:#000;stroke:none}#mermaid-svg-v87RZAQeUuqERsl3 .loopText,#mermaid-svg-v87RZAQeUuqERsl3 .loopText>tspan{fill:#000;stroke:none}#mermaid-svg-v87RZAQeUuqERsl3 .loopLine{stroke-width:2px;stroke-dasharray:2, 2;stroke:#ccf;fill:#ccf}#mermaid-svg-v87RZAQeUuqERsl3 .note{stroke:#aa3;fill:#fff5ad}#mermaid-svg-v87RZAQeUuqERsl3 .noteText,#mermaid-svg-v87RZAQeUuqERsl3 .noteText>tspan{fill:#000;stroke:none}#mermaid-svg-v87RZAQeUuqERsl3 .activation0{fill:#f4f4f4;stroke:#666}#mermaid-svg-v87RZAQeUuqERsl3 .activation1{fill:#f4f4f4;stroke:#666}#mermaid-svg-v87RZAQeUuqERsl3 .activation2{fill:#f4f4f4;stroke:#666}#mermaid-svg-v87RZAQeUuqERsl3 .mermaid-main-font{font-family:"trebuchet ms", verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-v87RZAQeUuqERsl3 .section{stroke:none;opacity:0.2}#mermaid-svg-v87RZAQeUuqERsl3 .section0{fill:rgba(102,102,255,0.49)}#mermaid-svg-v87RZAQeUuqERsl3 .section2{fill:#fff400}#mermaid-svg-v87RZAQeUuqERsl3 .section1,#mermaid-svg-v87RZAQeUuqERsl3 .section3{fill:#fff;opacity:0.2}#mermaid-svg-v87RZAQeUuqERsl3 .sectionTitle0{fill:#333}#mermaid-svg-v87RZAQeUuqERsl3 .sectionTitle1{fill:#333}#mermaid-svg-v87RZAQeUuqERsl3 .sectionTitle2{fill:#333}#mermaid-svg-v87RZAQeUuqERsl3 .sectionTitle3{fill:#333}#mermaid-svg-v87RZAQeUuqERsl3 .sectionTitle{text-anchor:start;font-size:11px;text-height:14px;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-v87RZAQeUuqERsl3 .grid .tick{stroke:#d3d3d3;opacity:0.8;shape-rendering:crispEdges}#mermaid-svg-v87RZAQeUuqERsl3 .grid .tick text{font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-v87RZAQeUuqERsl3 .grid path{stroke-width:0}#mermaid-svg-v87RZAQeUuqERsl3 .today{fill:none;stroke:red;stroke-width:2px}#mermaid-svg-v87RZAQeUuqERsl3 .task{stroke-width:2}#mermaid-svg-v87RZAQeUuqERsl3 .taskText{text-anchor:middle;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-v87RZAQeUuqERsl3 .taskText:not([font-size]){font-size:11px}#mermaid-svg-v87RZAQeUuqERsl3 .taskTextOutsideRight{fill:#000;text-anchor:start;font-size:11px;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-v87RZAQeUuqERsl3 .taskTextOutsideLeft{fill:#000;text-anchor:end;font-size:11px}#mermaid-svg-v87RZAQeUuqERsl3 .task.clickable{cursor:pointer}#mermaid-svg-v87RZAQeUuqERsl3 .taskText.clickable{cursor:pointer;fill:#003163 !important;font-weight:bold}#mermaid-svg-v87RZAQeUuqERsl3 .taskTextOutsideLeft.clickable{cursor:pointer;fill:#003163 !important;font-weight:bold}#mermaid-svg-v87RZAQeUuqERsl3 .taskTextOutsideRight.clickable{cursor:pointer;fill:#003163 !important;font-weight:bold}#mermaid-svg-v87RZAQeUuqERsl3 .taskText0,#mermaid-svg-v87RZAQeUuqERsl3 .taskText1,#mermaid-svg-v87RZAQeUuqERsl3 .taskText2,#mermaid-svg-v87RZAQeUuqERsl3 .taskText3{fill:#fff}#mermaid-svg-v87RZAQeUuqERsl3 .task0,#mermaid-svg-v87RZAQeUuqERsl3 .task1,#mermaid-svg-v87RZAQeUuqERsl3 .task2,#mermaid-svg-v87RZAQeUuqERsl3 .task3{fill:#8a90dd;stroke:#534fbc}#mermaid-svg-v87RZAQeUuqERsl3 .taskTextOutside0,#mermaid-svg-v87RZAQeUuqERsl3 .taskTextOutside2{fill:#000}#mermaid-svg-v87RZAQeUuqERsl3 .taskTextOutside1,#mermaid-svg-v87RZAQeUuqERsl3 .taskTextOutside3{fill:#000}#mermaid-svg-v87RZAQeUuqERsl3 .active0,#mermaid-svg-v87RZAQeUuqERsl3 .active1,#mermaid-svg-v87RZAQeUuqERsl3 .active2,#mermaid-svg-v87RZAQeUuqERsl3 .active3{fill:#bfc7ff;stroke:#534fbc}#mermaid-svg-v87RZAQeUuqERsl3 .activeText0,#mermaid-svg-v87RZAQeUuqERsl3 .activeText1,#mermaid-svg-v87RZAQeUuqERsl3 .activeText2,#mermaid-svg-v87RZAQeUuqERsl3 .activeText3{fill:#000 !important}#mermaid-svg-v87RZAQeUuqERsl3 .done0,#mermaid-svg-v87RZAQeUuqERsl3 .done1,#mermaid-svg-v87RZAQeUuqERsl3 .done2,#mermaid-svg-v87RZAQeUuqERsl3 .done3{stroke:grey;fill:#d3d3d3;stroke-width:2}#mermaid-svg-v87RZAQeUuqERsl3 .doneText0,#mermaid-svg-v87RZAQeUuqERsl3 .doneText1,#mermaid-svg-v87RZAQeUuqERsl3 .doneText2,#mermaid-svg-v87RZAQeUuqERsl3 .doneText3{fill:#000 !important}#mermaid-svg-v87RZAQeUuqERsl3 .crit0,#mermaid-svg-v87RZAQeUuqERsl3 .crit1,#mermaid-svg-v87RZAQeUuqERsl3 .crit2,#mermaid-svg-v87RZAQeUuqERsl3 .crit3{stroke:#f88;fill:red;stroke-width:2}#mermaid-svg-v87RZAQeUuqERsl3 .activeCrit0,#mermaid-svg-v87RZAQeUuqERsl3 .activeCrit1,#mermaid-svg-v87RZAQeUuqERsl3 .activeCrit2,#mermaid-svg-v87RZAQeUuqERsl3 .activeCrit3{stroke:#f88;fill:#bfc7ff;stroke-width:2}#mermaid-svg-v87RZAQeUuqERsl3 .doneCrit0,#mermaid-svg-v87RZAQeUuqERsl3 .doneCrit1,#mermaid-svg-v87RZAQeUuqERsl3 .doneCrit2,#mermaid-svg-v87RZAQeUuqERsl3 .doneCrit3{stroke:#f88;fill:#d3d3d3;stroke-width:2;cursor:pointer;shape-rendering:crispEdges}#mermaid-svg-v87RZAQeUuqERsl3 .milestone{transform:rotate(45deg) scale(0.8, 0.8)}#mermaid-svg-v87RZAQeUuqERsl3 .milestoneText{font-style:italic}#mermaid-svg-v87RZAQeUuqERsl3 .doneCritText0,#mermaid-svg-v87RZAQeUuqERsl3 .doneCritText1,#mermaid-svg-v87RZAQeUuqERsl3 .doneCritText2,#mermaid-svg-v87RZAQeUuqERsl3 .doneCritText3{fill:#000 !important}#mermaid-svg-v87RZAQeUuqERsl3 .activeCritText0,#mermaid-svg-v87RZAQeUuqERsl3 .activeCritText1,#mermaid-svg-v87RZAQeUuqERsl3 .activeCritText2,#mermaid-svg-v87RZAQeUuqERsl3 .activeCritText3{fill:#000 !important}#mermaid-svg-v87RZAQeUuqERsl3 .titleText{text-anchor:middle;font-size:18px;fill:#000;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-v87RZAQeUuqERsl3 g.classGroup text{fill:#9370db;stroke:none;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family);font-size:10px}#mermaid-svg-v87RZAQeUuqERsl3 g.classGroup text .title{font-weight:bolder}#mermaid-svg-v87RZAQeUuqERsl3 g.clickable{cursor:pointer}#mermaid-svg-v87RZAQeUuqERsl3 g.classGroup rect{fill:#ECECFF;stroke:#9370db}#mermaid-svg-v87RZAQeUuqERsl3 g.classGroup line{stroke:#9370db;stroke-width:1}#mermaid-svg-v87RZAQeUuqERsl3 .classLabel .box{stroke:none;stroke-width:0;fill:#ECECFF;opacity:0.5}#mermaid-svg-v87RZAQeUuqERsl3 .classLabel .label{fill:#9370db;font-size:10px}#mermaid-svg-v87RZAQeUuqERsl3 .relation{stroke:#9370db;stroke-width:1;fill:none}#mermaid-svg-v87RZAQeUuqERsl3 .dashed-line{stroke-dasharray:3}#mermaid-svg-v87RZAQeUuqERsl3 #compositionStart{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-v87RZAQeUuqERsl3 #compositionEnd{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-v87RZAQeUuqERsl3 #aggregationStart{fill:#ECECFF;stroke:#9370db;stroke-width:1}#mermaid-svg-v87RZAQeUuqERsl3 #aggregationEnd{fill:#ECECFF;stroke:#9370db;stroke-width:1}#mermaid-svg-v87RZAQeUuqERsl3 #dependencyStart{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-v87RZAQeUuqERsl3 #dependencyEnd{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-v87RZAQeUuqERsl3 #extensionStart{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-v87RZAQeUuqERsl3 #extensionEnd{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-v87RZAQeUuqERsl3 .commit-id,#mermaid-svg-v87RZAQeUuqERsl3 .commit-msg,#mermaid-svg-v87RZAQeUuqERsl3 .branch-label{fill:lightgrey;color:lightgrey;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-v87RZAQeUuqERsl3 .pieTitleText{text-anchor:middle;font-size:25px;fill:#000;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-v87RZAQeUuqERsl3 .slice{font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-v87RZAQeUuqERsl3 g.stateGroup text{fill:#9370db;stroke:none;font-size:10px;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-v87RZAQeUuqERsl3 g.stateGroup text{fill:#9370db;fill:#333;stroke:none;font-size:10px}#mermaid-svg-v87RZAQeUuqERsl3 g.statediagram-cluster .cluster-label text{fill:#333}#mermaid-svg-v87RZAQeUuqERsl3 g.stateGroup .state-title{font-weight:bolder;fill:#000}#mermaid-svg-v87RZAQeUuqERsl3 g.stateGroup rect{fill:#ECECFF;stroke:#9370db}#mermaid-svg-v87RZAQeUuqERsl3 g.stateGroup line{stroke:#9370db;stroke-width:1}#mermaid-svg-v87RZAQeUuqERsl3 .transition{stroke:#9370db;stroke-width:1;fill:none}#mermaid-svg-v87RZAQeUuqERsl3 .stateGroup .composit{fill:white;border-bottom:1px}#mermaid-svg-v87RZAQeUuqERsl3 .stateGroup .alt-composit{fill:#e0e0e0;border-bottom:1px}#mermaid-svg-v87RZAQeUuqERsl3 .state-note{stroke:#aa3;fill:#fff5ad}#mermaid-svg-v87RZAQeUuqERsl3 .state-note text{fill:black;stroke:none;font-size:10px}#mermaid-svg-v87RZAQeUuqERsl3 .stateLabel .box{stroke:none;stroke-width:0;fill:#ECECFF;opacity:0.7}#mermaid-svg-v87RZAQeUuqERsl3 .edgeLabel text{fill:#333}#mermaid-svg-v87RZAQeUuqERsl3 .stateLabel text{fill:#000;font-size:10px;font-weight:bold;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-v87RZAQeUuqERsl3 .node circle.state-start{fill:black;stroke:black}#mermaid-svg-v87RZAQeUuqERsl3 .node circle.state-end{fill:black;stroke:white;stroke-width:1.5}#mermaid-svg-v87RZAQeUuqERsl3 #statediagram-barbEnd{fill:#9370db}#mermaid-svg-v87RZAQeUuqERsl3 .statediagram-cluster rect{fill:#ECECFF;stroke:#9370db;stroke-width:1px}#mermaid-svg-v87RZAQeUuqERsl3 .statediagram-cluster rect.outer{rx:5px;ry:5px}#mermaid-svg-v87RZAQeUuqERsl3 .statediagram-state .divider{stroke:#9370db}#mermaid-svg-v87RZAQeUuqERsl3 .statediagram-state .title-state{rx:5px;ry:5px}#mermaid-svg-v87RZAQeUuqERsl3 .statediagram-cluster.statediagram-cluster .inner{fill:white}#mermaid-svg-v87RZAQeUuqERsl3 .statediagram-cluster.statediagram-cluster-alt .inner{fill:#e0e0e0}#mermaid-svg-v87RZAQeUuqERsl3 .statediagram-cluster .inner{rx:0;ry:0}#mermaid-svg-v87RZAQeUuqERsl3 .statediagram-state rect.basic{rx:5px;ry:5px}#mermaid-svg-v87RZAQeUuqERsl3 .statediagram-state rect.divider{stroke-dasharray:10,10;fill:#efefef}#mermaid-svg-v87RZAQeUuqERsl3 .note-edge{stroke-dasharray:5}#mermaid-svg-v87RZAQeUuqERsl3 .statediagram-note rect{fill:#fff5ad;stroke:#aa3;stroke-width:1px;rx:0;ry:0}:root{--mermaid-font-family: '"trebuchet ms", verdana, arial';--mermaid-font-family: "Comic Sans MS", "Comic Sans", cursive}#mermaid-svg-v87RZAQeUuqERsl3 .error-icon{fill:#522}#mermaid-svg-v87RZAQeUuqERsl3 .error-text{fill:#522;stroke:#522}#mermaid-svg-v87RZAQeUuqERsl3 .edge-thickness-normal{stroke-width:2px}#mermaid-svg-v87RZAQeUuqERsl3 .edge-thickness-thick{stroke-width:3.5px}#mermaid-svg-v87RZAQeUuqERsl3 .edge-pattern-solid{stroke-dasharray:0}#mermaid-svg-v87RZAQeUuqERsl3 .edge-pattern-dashed{stroke-dasharray:3}#mermaid-svg-v87RZAQeUuqERsl3 .edge-pattern-dotted{stroke-dasharray:2}#mermaid-svg-v87RZAQeUuqERsl3 .marker{fill:#333}#mermaid-svg-v87RZAQeUuqERsl3 .marker.cross{stroke:#333}:root { --mermaid-font-family: "trebuchet ms", verdana, arial;}#mermaid-svg-v87RZAQeUuqERsl3 {color: rgba(0, 0, 0, 0.75);font: ;}

Java Bean的校验需求
Bean Validation JSR 提案
Bean Validation API
hibernate-validator 实现

其中的Bean Validation JSR只提出规范,不涉及coding,Bean Validation API是Java官方根据JSR设计的API,并不提供实现。而hibernate-validator是Apache Hibernate基金会根据Bean Validation API提供的实现。

走进hibernate-validator

SpringMVC默认集成hibernate-validator

翻看我们的SpringBoot项目,好像没有专门import hibernate-validator,但是还是可以直接用@NotNull,@NotBlank等注解,难道真的没有引入吗?
其实排查起来很简单:

mvn dependency:tree
  • Ctr + Shift + F

    一般情况下,对于SpringBoot项目,默认集成了spring-boot-starter-validation,后者默认集成了hibernate-validator框架,不需要单独引入。当然你,在实测中发现这也和版本有关,有些版本的SpringBoot并没有集成,需要单独引入。
    不管是自动继承还是手动引入,SpringBoot(SpringMVC)默认支持hibernate-validator框架。

hibernate-validator支持哪些校验规则

上文提到:

#mermaid-svg-0Q7DYgI42lRlnQ27 .label{font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family);fill:#333;color:#333}#mermaid-svg-0Q7DYgI42lRlnQ27 .label text{fill:#333}#mermaid-svg-0Q7DYgI42lRlnQ27 .node rect,#mermaid-svg-0Q7DYgI42lRlnQ27 .node circle,#mermaid-svg-0Q7DYgI42lRlnQ27 .node ellipse,#mermaid-svg-0Q7DYgI42lRlnQ27 .node polygon,#mermaid-svg-0Q7DYgI42lRlnQ27 .node path{fill:#ECECFF;stroke:#9370db;stroke-width:1px}#mermaid-svg-0Q7DYgI42lRlnQ27 .node .label{text-align:center;fill:#333}#mermaid-svg-0Q7DYgI42lRlnQ27 .node.clickable{cursor:pointer}#mermaid-svg-0Q7DYgI42lRlnQ27 .arrowheadPath{fill:#333}#mermaid-svg-0Q7DYgI42lRlnQ27 .edgePath .path{stroke:#333;stroke-width:1.5px}#mermaid-svg-0Q7DYgI42lRlnQ27 .flowchart-link{stroke:#333;fill:none}#mermaid-svg-0Q7DYgI42lRlnQ27 .edgeLabel{background-color:#e8e8e8;text-align:center}#mermaid-svg-0Q7DYgI42lRlnQ27 .edgeLabel rect{opacity:0.9}#mermaid-svg-0Q7DYgI42lRlnQ27 .edgeLabel span{color:#333}#mermaid-svg-0Q7DYgI42lRlnQ27 .cluster rect{fill:#ffffde;stroke:#aa3;stroke-width:1px}#mermaid-svg-0Q7DYgI42lRlnQ27 .cluster text{fill:#333}#mermaid-svg-0Q7DYgI42lRlnQ27 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family);font-size:12px;background:#ffffde;border:1px solid #aa3;border-radius:2px;pointer-events:none;z-index:100}#mermaid-svg-0Q7DYgI42lRlnQ27 .actor{stroke:#ccf;fill:#ECECFF}#mermaid-svg-0Q7DYgI42lRlnQ27 text.actor>tspan{fill:#000;stroke:none}#mermaid-svg-0Q7DYgI42lRlnQ27 .actor-line{stroke:grey}#mermaid-svg-0Q7DYgI42lRlnQ27 .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333}#mermaid-svg-0Q7DYgI42lRlnQ27 .messageLine1{stroke-width:1.5;stroke-dasharray:2, 2;stroke:#333}#mermaid-svg-0Q7DYgI42lRlnQ27 #arrowhead path{fill:#333;stroke:#333}#mermaid-svg-0Q7DYgI42lRlnQ27 .sequenceNumber{fill:#fff}#mermaid-svg-0Q7DYgI42lRlnQ27 #sequencenumber{fill:#333}#mermaid-svg-0Q7DYgI42lRlnQ27 #crosshead path{fill:#333;stroke:#333}#mermaid-svg-0Q7DYgI42lRlnQ27 .messageText{fill:#333;stroke:#333}#mermaid-svg-0Q7DYgI42lRlnQ27 .labelBox{stroke:#ccf;fill:#ECECFF}#mermaid-svg-0Q7DYgI42lRlnQ27 .labelText,#mermaid-svg-0Q7DYgI42lRlnQ27 .labelText>tspan{fill:#000;stroke:none}#mermaid-svg-0Q7DYgI42lRlnQ27 .loopText,#mermaid-svg-0Q7DYgI42lRlnQ27 .loopText>tspan{fill:#000;stroke:none}#mermaid-svg-0Q7DYgI42lRlnQ27 .loopLine{stroke-width:2px;stroke-dasharray:2, 2;stroke:#ccf;fill:#ccf}#mermaid-svg-0Q7DYgI42lRlnQ27 .note{stroke:#aa3;fill:#fff5ad}#mermaid-svg-0Q7DYgI42lRlnQ27 .noteText,#mermaid-svg-0Q7DYgI42lRlnQ27 .noteText>tspan{fill:#000;stroke:none}#mermaid-svg-0Q7DYgI42lRlnQ27 .activation0{fill:#f4f4f4;stroke:#666}#mermaid-svg-0Q7DYgI42lRlnQ27 .activation1{fill:#f4f4f4;stroke:#666}#mermaid-svg-0Q7DYgI42lRlnQ27 .activation2{fill:#f4f4f4;stroke:#666}#mermaid-svg-0Q7DYgI42lRlnQ27 .mermaid-main-font{font-family:"trebuchet ms", verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-0Q7DYgI42lRlnQ27 .section{stroke:none;opacity:0.2}#mermaid-svg-0Q7DYgI42lRlnQ27 .section0{fill:rgba(102,102,255,0.49)}#mermaid-svg-0Q7DYgI42lRlnQ27 .section2{fill:#fff400}#mermaid-svg-0Q7DYgI42lRlnQ27 .section1,#mermaid-svg-0Q7DYgI42lRlnQ27 .section3{fill:#fff;opacity:0.2}#mermaid-svg-0Q7DYgI42lRlnQ27 .sectionTitle0{fill:#333}#mermaid-svg-0Q7DYgI42lRlnQ27 .sectionTitle1{fill:#333}#mermaid-svg-0Q7DYgI42lRlnQ27 .sectionTitle2{fill:#333}#mermaid-svg-0Q7DYgI42lRlnQ27 .sectionTitle3{fill:#333}#mermaid-svg-0Q7DYgI42lRlnQ27 .sectionTitle{text-anchor:start;font-size:11px;text-height:14px;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-0Q7DYgI42lRlnQ27 .grid .tick{stroke:#d3d3d3;opacity:0.8;shape-rendering:crispEdges}#mermaid-svg-0Q7DYgI42lRlnQ27 .grid .tick text{font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-0Q7DYgI42lRlnQ27 .grid path{stroke-width:0}#mermaid-svg-0Q7DYgI42lRlnQ27 .today{fill:none;stroke:red;stroke-width:2px}#mermaid-svg-0Q7DYgI42lRlnQ27 .task{stroke-width:2}#mermaid-svg-0Q7DYgI42lRlnQ27 .taskText{text-anchor:middle;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-0Q7DYgI42lRlnQ27 .taskText:not([font-size]){font-size:11px}#mermaid-svg-0Q7DYgI42lRlnQ27 .taskTextOutsideRight{fill:#000;text-anchor:start;font-size:11px;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-0Q7DYgI42lRlnQ27 .taskTextOutsideLeft{fill:#000;text-anchor:end;font-size:11px}#mermaid-svg-0Q7DYgI42lRlnQ27 .task.clickable{cursor:pointer}#mermaid-svg-0Q7DYgI42lRlnQ27 .taskText.clickable{cursor:pointer;fill:#003163 !important;font-weight:bold}#mermaid-svg-0Q7DYgI42lRlnQ27 .taskTextOutsideLeft.clickable{cursor:pointer;fill:#003163 !important;font-weight:bold}#mermaid-svg-0Q7DYgI42lRlnQ27 .taskTextOutsideRight.clickable{cursor:pointer;fill:#003163 !important;font-weight:bold}#mermaid-svg-0Q7DYgI42lRlnQ27 .taskText0,#mermaid-svg-0Q7DYgI42lRlnQ27 .taskText1,#mermaid-svg-0Q7DYgI42lRlnQ27 .taskText2,#mermaid-svg-0Q7DYgI42lRlnQ27 .taskText3{fill:#fff}#mermaid-svg-0Q7DYgI42lRlnQ27 .task0,#mermaid-svg-0Q7DYgI42lRlnQ27 .task1,#mermaid-svg-0Q7DYgI42lRlnQ27 .task2,#mermaid-svg-0Q7DYgI42lRlnQ27 .task3{fill:#8a90dd;stroke:#534fbc}#mermaid-svg-0Q7DYgI42lRlnQ27 .taskTextOutside0,#mermaid-svg-0Q7DYgI42lRlnQ27 .taskTextOutside2{fill:#000}#mermaid-svg-0Q7DYgI42lRlnQ27 .taskTextOutside1,#mermaid-svg-0Q7DYgI42lRlnQ27 .taskTextOutside3{fill:#000}#mermaid-svg-0Q7DYgI42lRlnQ27 .active0,#mermaid-svg-0Q7DYgI42lRlnQ27 .active1,#mermaid-svg-0Q7DYgI42lRlnQ27 .active2,#mermaid-svg-0Q7DYgI42lRlnQ27 .active3{fill:#bfc7ff;stroke:#534fbc}#mermaid-svg-0Q7DYgI42lRlnQ27 .activeText0,#mermaid-svg-0Q7DYgI42lRlnQ27 .activeText1,#mermaid-svg-0Q7DYgI42lRlnQ27 .activeText2,#mermaid-svg-0Q7DYgI42lRlnQ27 .activeText3{fill:#000 !important}#mermaid-svg-0Q7DYgI42lRlnQ27 .done0,#mermaid-svg-0Q7DYgI42lRlnQ27 .done1,#mermaid-svg-0Q7DYgI42lRlnQ27 .done2,#mermaid-svg-0Q7DYgI42lRlnQ27 .done3{stroke:grey;fill:#d3d3d3;stroke-width:2}#mermaid-svg-0Q7DYgI42lRlnQ27 .doneText0,#mermaid-svg-0Q7DYgI42lRlnQ27 .doneText1,#mermaid-svg-0Q7DYgI42lRlnQ27 .doneText2,#mermaid-svg-0Q7DYgI42lRlnQ27 .doneText3{fill:#000 !important}#mermaid-svg-0Q7DYgI42lRlnQ27 .crit0,#mermaid-svg-0Q7DYgI42lRlnQ27 .crit1,#mermaid-svg-0Q7DYgI42lRlnQ27 .crit2,#mermaid-svg-0Q7DYgI42lRlnQ27 .crit3{stroke:#f88;fill:red;stroke-width:2}#mermaid-svg-0Q7DYgI42lRlnQ27 .activeCrit0,#mermaid-svg-0Q7DYgI42lRlnQ27 .activeCrit1,#mermaid-svg-0Q7DYgI42lRlnQ27 .activeCrit2,#mermaid-svg-0Q7DYgI42lRlnQ27 .activeCrit3{stroke:#f88;fill:#bfc7ff;stroke-width:2}#mermaid-svg-0Q7DYgI42lRlnQ27 .doneCrit0,#mermaid-svg-0Q7DYgI42lRlnQ27 .doneCrit1,#mermaid-svg-0Q7DYgI42lRlnQ27 .doneCrit2,#mermaid-svg-0Q7DYgI42lRlnQ27 .doneCrit3{stroke:#f88;fill:#d3d3d3;stroke-width:2;cursor:pointer;shape-rendering:crispEdges}#mermaid-svg-0Q7DYgI42lRlnQ27 .milestone{transform:rotate(45deg) scale(0.8, 0.8)}#mermaid-svg-0Q7DYgI42lRlnQ27 .milestoneText{font-style:italic}#mermaid-svg-0Q7DYgI42lRlnQ27 .doneCritText0,#mermaid-svg-0Q7DYgI42lRlnQ27 .doneCritText1,#mermaid-svg-0Q7DYgI42lRlnQ27 .doneCritText2,#mermaid-svg-0Q7DYgI42lRlnQ27 .doneCritText3{fill:#000 !important}#mermaid-svg-0Q7DYgI42lRlnQ27 .activeCritText0,#mermaid-svg-0Q7DYgI42lRlnQ27 .activeCritText1,#mermaid-svg-0Q7DYgI42lRlnQ27 .activeCritText2,#mermaid-svg-0Q7DYgI42lRlnQ27 .activeCritText3{fill:#000 !important}#mermaid-svg-0Q7DYgI42lRlnQ27 .titleText{text-anchor:middle;font-size:18px;fill:#000;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-0Q7DYgI42lRlnQ27 g.classGroup text{fill:#9370db;stroke:none;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family);font-size:10px}#mermaid-svg-0Q7DYgI42lRlnQ27 g.classGroup text .title{font-weight:bolder}#mermaid-svg-0Q7DYgI42lRlnQ27 g.clickable{cursor:pointer}#mermaid-svg-0Q7DYgI42lRlnQ27 g.classGroup rect{fill:#ECECFF;stroke:#9370db}#mermaid-svg-0Q7DYgI42lRlnQ27 g.classGroup line{stroke:#9370db;stroke-width:1}#mermaid-svg-0Q7DYgI42lRlnQ27 .classLabel .box{stroke:none;stroke-width:0;fill:#ECECFF;opacity:0.5}#mermaid-svg-0Q7DYgI42lRlnQ27 .classLabel .label{fill:#9370db;font-size:10px}#mermaid-svg-0Q7DYgI42lRlnQ27 .relation{stroke:#9370db;stroke-width:1;fill:none}#mermaid-svg-0Q7DYgI42lRlnQ27 .dashed-line{stroke-dasharray:3}#mermaid-svg-0Q7DYgI42lRlnQ27 #compositionStart{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-0Q7DYgI42lRlnQ27 #compositionEnd{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-0Q7DYgI42lRlnQ27 #aggregationStart{fill:#ECECFF;stroke:#9370db;stroke-width:1}#mermaid-svg-0Q7DYgI42lRlnQ27 #aggregationEnd{fill:#ECECFF;stroke:#9370db;stroke-width:1}#mermaid-svg-0Q7DYgI42lRlnQ27 #dependencyStart{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-0Q7DYgI42lRlnQ27 #dependencyEnd{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-0Q7DYgI42lRlnQ27 #extensionStart{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-0Q7DYgI42lRlnQ27 #extensionEnd{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-0Q7DYgI42lRlnQ27 .commit-id,#mermaid-svg-0Q7DYgI42lRlnQ27 .commit-msg,#mermaid-svg-0Q7DYgI42lRlnQ27 .branch-label{fill:lightgrey;color:lightgrey;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-0Q7DYgI42lRlnQ27 .pieTitleText{text-anchor:middle;font-size:25px;fill:#000;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-0Q7DYgI42lRlnQ27 .slice{font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-0Q7DYgI42lRlnQ27 g.stateGroup text{fill:#9370db;stroke:none;font-size:10px;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-0Q7DYgI42lRlnQ27 g.stateGroup text{fill:#9370db;fill:#333;stroke:none;font-size:10px}#mermaid-svg-0Q7DYgI42lRlnQ27 g.statediagram-cluster .cluster-label text{fill:#333}#mermaid-svg-0Q7DYgI42lRlnQ27 g.stateGroup .state-title{font-weight:bolder;fill:#000}#mermaid-svg-0Q7DYgI42lRlnQ27 g.stateGroup rect{fill:#ECECFF;stroke:#9370db}#mermaid-svg-0Q7DYgI42lRlnQ27 g.stateGroup line{stroke:#9370db;stroke-width:1}#mermaid-svg-0Q7DYgI42lRlnQ27 .transition{stroke:#9370db;stroke-width:1;fill:none}#mermaid-svg-0Q7DYgI42lRlnQ27 .stateGroup .composit{fill:white;border-bottom:1px}#mermaid-svg-0Q7DYgI42lRlnQ27 .stateGroup .alt-composit{fill:#e0e0e0;border-bottom:1px}#mermaid-svg-0Q7DYgI42lRlnQ27 .state-note{stroke:#aa3;fill:#fff5ad}#mermaid-svg-0Q7DYgI42lRlnQ27 .state-note text{fill:black;stroke:none;font-size:10px}#mermaid-svg-0Q7DYgI42lRlnQ27 .stateLabel .box{stroke:none;stroke-width:0;fill:#ECECFF;opacity:0.7}#mermaid-svg-0Q7DYgI42lRlnQ27 .edgeLabel text{fill:#333}#mermaid-svg-0Q7DYgI42lRlnQ27 .stateLabel text{fill:#000;font-size:10px;font-weight:bold;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-0Q7DYgI42lRlnQ27 .node circle.state-start{fill:black;stroke:black}#mermaid-svg-0Q7DYgI42lRlnQ27 .node circle.state-end{fill:black;stroke:white;stroke-width:1.5}#mermaid-svg-0Q7DYgI42lRlnQ27 #statediagram-barbEnd{fill:#9370db}#mermaid-svg-0Q7DYgI42lRlnQ27 .statediagram-cluster rect{fill:#ECECFF;stroke:#9370db;stroke-width:1px}#mermaid-svg-0Q7DYgI42lRlnQ27 .statediagram-cluster rect.outer{rx:5px;ry:5px}#mermaid-svg-0Q7DYgI42lRlnQ27 .statediagram-state .divider{stroke:#9370db}#mermaid-svg-0Q7DYgI42lRlnQ27 .statediagram-state .title-state{rx:5px;ry:5px}#mermaid-svg-0Q7DYgI42lRlnQ27 .statediagram-cluster.statediagram-cluster .inner{fill:white}#mermaid-svg-0Q7DYgI42lRlnQ27 .statediagram-cluster.statediagram-cluster-alt .inner{fill:#e0e0e0}#mermaid-svg-0Q7DYgI42lRlnQ27 .statediagram-cluster .inner{rx:0;ry:0}#mermaid-svg-0Q7DYgI42lRlnQ27 .statediagram-state rect.basic{rx:5px;ry:5px}#mermaid-svg-0Q7DYgI42lRlnQ27 .statediagram-state rect.divider{stroke-dasharray:10,10;fill:#efefef}#mermaid-svg-0Q7DYgI42lRlnQ27 .note-edge{stroke-dasharray:5}#mermaid-svg-0Q7DYgI42lRlnQ27 .statediagram-note rect{fill:#fff5ad;stroke:#aa3;stroke-width:1px;rx:0;ry:0}:root{--mermaid-font-family: '"trebuchet ms", verdana, arial';--mermaid-font-family: "Comic Sans MS", "Comic Sans", cursive}#mermaid-svg-0Q7DYgI42lRlnQ27 .error-icon{fill:#522}#mermaid-svg-0Q7DYgI42lRlnQ27 .error-text{fill:#522;stroke:#522}#mermaid-svg-0Q7DYgI42lRlnQ27 .edge-thickness-normal{stroke-width:2px}#mermaid-svg-0Q7DYgI42lRlnQ27 .edge-thickness-thick{stroke-width:3.5px}#mermaid-svg-0Q7DYgI42lRlnQ27 .edge-pattern-solid{stroke-dasharray:0}#mermaid-svg-0Q7DYgI42lRlnQ27 .edge-pattern-dashed{stroke-dasharray:3}#mermaid-svg-0Q7DYgI42lRlnQ27 .edge-pattern-dotted{stroke-dasharray:2}#mermaid-svg-0Q7DYgI42lRlnQ27 .marker{fill:#333}#mermaid-svg-0Q7DYgI42lRlnQ27 .marker.cross{stroke:#333}:root { --mermaid-font-family: "trebuchet ms", verdana, arial;}#mermaid-svg-0Q7DYgI42lRlnQ27 {color: rgba(0, 0, 0, 0.75);font: ;}

Java Bean的校验需求
Bean Validation JSR 提案
Bean Validation API
hibernate-validator 实现

Java Validation自提出到现在也已经有十多年了,以最新的JSR380为例,从上往下捋下来是这样的:
JSR380 ——> Bean Validation 2.0 ——> hibernate-valiidatot 6.0 +
所以与其问hibernate-validator支持哪些校验规则不如问Bean Validation 2.0规定了哪些API。查看官方文档Built-in Constraint definitions可以看到,Bean Validation 2.0拥有22种“内建约束(built-in constraints)”:

8.1. @Null constraint
8.2. @NotNull constraint
8.3. @AssertTrue constraint
8.4. @AssertFalse constraint
8.5. @Min constraint
8.6. @Max constraint
8.7. @DecimalMin constraint
8.8. @DecimalMax constraint
8.9. @Negative constraint
8.10. @NegativeOrZero constraint
8.11. @Positive constraint
8.12. @PositiveOrZero constraint
8.13. @Size constraint
8.14. @Digits constraint
8.15. @Past constraint
8.16. @PastOrPresent constraint
8.17. @Future constraint
8.18. @FutureOrPresent constraint
8.19. @Pattern constraint
8.20. @NotEmpty constraint
8.21. @NotBlank constraint
8.22. @Email constraint

每一种约束都有说明。
当然,本地的hibernate-validator也可以查看每个约束文档,引入hibernate-validator包后,搜索任意一个约束如NotNull:

可以看到,22个约束(以注解形式出现)都定义在jakarta.validation-api(也就是java.validation-api)中,版本2.0.2,hibernate-validator就是实现该接口。

Examples


使用@Vadation开启校验(使所有constraints生效),其中的NacosConfig是个Java Bean:

其中的@Valid是个递归校验的注解,使用这个注解在属性上时,会递归地向下校验(有关@Valid请自行了解):

其中的match,talosConfig都使用了@Valid进行递归校验:

其中的serviceName和InstanceIPs使用了自定义注解:@ValidServiceName和@ValidIP。

  • 如果对自定义@Validation注解感兴趣,请自行了解,可参考:Java Bean Validation自定义注解
  • List<@ValidIP String>来源于Bean Validation 2.0增加的容器元素注解支持What’s new in 2.0:

    Ps:如果是对容器中的每个元素进行递归校验,可以使用List<@Valid JavaBean>的方式。
    注意,所有内建的constraints包括@Valid在校验的属性为null自动返回true。如果是自定义注解,也建议在isValid()方法第一行加上:
if(null == xxx) return true;

即统一风格,如果校验对象为null,则默认校验通过。

程序化校验

参见:Programmatic Validation
我写的example:

参考资料

参考:深入了解数据校验:Java Bean Validation 2.0(JSR380)

Spring validation框架简介相关推荐

  1. 【Spring】框架简介

    [Spring]框架简介 Spring是什么 Spring是分层的Java SE/EE应用full-stack轻量级开源框架,以IOC(Inverse Of Control:反转控制)和AOP(Asp ...

  2. spring orm框架简介

    ORM全称对象关系映射(Object/Relation Mapping),指将Java对象状态自动映射到关系数据库中的数据上,从而提供透明化的持久化支持,即把一种形式转化为另一种形式. 对象与关系数据 ...

  3. Spring Validation验证框架参数验证 @Validated 和 @Valid 的区别

    参数验证 @Validated 和 @Valid 的区别 Spring Validation验证框架对参数的验证机制提供了@Validated(Spring's JSR-303 规范,是标准 JSR- ...

  4. @Validated和@Valid区别:Spring validation验证框架对入参实体进行嵌套验证必须在相应属性(字段)加上@Valid而不是@Validated...

    Spring Validation验证框架对参数的验证机制提供了@Validated(Spring's JSR-303规范,是标准JSR-303的一个变种),javax提供了@Valid(标准JSR- ...

  5. 通过Validation框架检查请求参数的基本格式

    通过Validation框架检查请求参数的基本格式 1.1. 添加依赖 Spring Validation框架可用于在服务器端检查请求参数的基本格式(例如是否提交了请求参数.字符串的长度是否正确.数字 ...

  6. Spring框架简介

    Spring框架简介 Spring Framework 是一个开源的Java/Java EE全功能栈(full-stack)的应用程序框架,以Apache许可证形式发布,也有.NET平台上的移植版本. ...

  7. Spring 框架简介及官方压缩包目录

    一.Spring 框架简介及官方压缩包目录 一.什么是spring spring是一个框架, 核心思想 IoC,AOP 简化企业开发,帮助分离对象之间的依赖关系 IoC:Inversion of Co ...

  8. 【Spring框架一】——Spring框架简介

    系列文章目录 Spring框架简介 系列文章目录 前言 一.什么是Spring框架? 二.Spring框架的优势 1.简化开发流程:Spring提供了许多现成的功能,可以使得开发人员在构建应用程序时减 ...

  9. Spring Security(一)- SpringSecurity 框架简介

    文章目录 一.SpringSecurity 框架简介 1. 概要 2. Spring Security 与 Shiro 对比 2.1 Spring Security 2.2 SpringSecurit ...

  10. Spring 系列: Spring 框架简介

    Spring 是一个开源框架,是为了解决企业应用程序开发复杂性而创建的.框架的主要优势之一就是其分层架构,分层架构允许您选择使用哪一个组件,同时为 J2EE 应用程序开发提供集成的框架. 在这篇由三部 ...

最新文章

  1. ipython换行操作_ipython 换行
  2. BASIC-23_蓝桥杯_芯片测试
  3. (Lesson2)根据类名称和属性获得元素-JavaScript面向对象
  4. 未能为服务器,未能为数据库 'TEMPDB' 分配新页
  5. 愚蠢的怪胎技巧:通过命令行管理SkyDrive
  6. 超级好用的使用python批量更新MYsql,速度从一万条需要一天变道一万条需要10分钟左右
  7. Visual C++线程同步技术
  8. 人民邮电报:区块链和工业互联网的融合 将产生叠加倍增效应
  9. 8 年经验面试官解读程序员的技能瓶颈,以及突破瓶颈的忠告 | CSDN 博文精选
  10. EF的注解Annotation和Fluent API
  11. 计算机无线网络连接怎么弄,Win7系统如何设置无线网络连接?
  12. adventureworks mysql_adventureworks
  13. PDF文件怎么转换成CAD格式?教你几种转换方法
  14. 【Spring Security Oauth2】构建资源服务器(二):授权管理(Web授权,注解授权:securedEnabled, prePostEnabled, jsr250Enabled)
  15. dump java崩溃自动 不生成_Java如何生成Heap Dump及OOM问题排查
  16. 广州蓝景分享—遇到网页慢,我们该怎么办?
  17. 颜色在计算机中的存储和显示详解
  18. 文档控件Aspose.words for.java 授权须知
  19. 对计算机网络的保密管理整改措施,保密工作自查整改报告
  20. GRAFANA接入第三方SSO

热门文章

  1. 吾爱破解网站访问出错
  2. 贝叶斯统计:概率思维的魔法
  3. 【清华大学陈渝】第三章 计算机体系结构
  4. 一路走好——稻盛和夫先生
  5. 九位皇子对于皇帝的宝座争斗不休,那么是哪九位呢?
  6. gatk过滤_GATK使用方法详解(原始数据的处理)
  7. IAR for MSP430 7.12.1下载
  8. android手机能安装win10,微软或推可在安卓设备上安装的Win10系统ROM
  9. HFSS Wave Port设置
  10. 计算机桌面搜狗输入图标不见了怎么办,win7搜狗输入法不见了怎么办