diff --git a/.github/workflows/deploy-docs.yml b/.github/workflows/deploy-docs.yml index 9b9ff7d..3755f5e 100644 --- a/.github/workflows/deploy-docs.yml +++ b/.github/workflows/deploy-docs.yml @@ -49,6 +49,7 @@ jobs: - name: 部署文档 uses: JamesIves/github-pages-deploy-action@v4 with: - # 这是文档部署到的分支名称 - branch: gh-pages folder: document/web-docs/docs/.vuepress/dist + repository-name: stick-i/spel-validator-gh-pages + branch: gh-pages + token: ${{ secrets.GH_PAGES_TOKEN }} diff --git a/README.md b/README.md index fd35582..66957a4 100644 --- a/README.md +++ b/README.md @@ -217,7 +217,6 @@ JDK8+ - `vX.Y.Z`:版本分支,用于汇总及验证新版本的功能,已经发布的版本会将分支删除。 - `dev-num-desc`:开发分支,用于开发新功能,每个dev分支都应当对应一个issue,功能开发完成后通过PR合入 `vX.Y.Z` 分支,并删除当前分支。 - `docs`:文档分支,修改文档的内容将提交到这里。 -- `gh-pages`:GitHub Pages 分支,用于发布在线文档。 ## License diff --git a/document/web-docs/docs/.vuepress/configs/head.ts b/document/web-docs/docs/.vuepress/configs/head.ts index 4a39471..31a904d 100644 --- a/document/web-docs/docs/.vuepress/configs/head.ts +++ b/document/web-docs/docs/.vuepress/configs/head.ts @@ -20,18 +20,18 @@ export const head: HeadConfig[] = [ }, ], ['link', {rel: 'manifest', href: '/manifest.webmanifest'}], - ['meta', {name: 'application-name', content: 'VuePress'}], - ['meta', {name: 'apple-mobile-web-app-title', content: 'VuePress'}], + ['meta', {name: 'application-name', content: 'SpEL Validator'}], + ['meta', {name: 'apple-mobile-web-app-title', content: 'SpEL Validator'}], ['meta', {name: 'apple-mobile-web-app-status-bar-style', content: 'black'}], [ 'link', - {rel: 'apple-touch-icon', href: `/images/icons/apple-touch-icon.png`}, + {rel: 'apple-touch-icon', href: `/images/logo.png`}, ], [ 'link', { rel: 'mask-icon', - href: '/images/icons/safari-pinned-tab.svg', + href: '/images/logo.png', color: '#3eaf7c', }, ], diff --git a/document/web-docs/docs/.vuepress/public/images/icons/android-chrome-192x192.png b/document/web-docs/docs/.vuepress/public/images/icons/android-chrome-192x192.png deleted file mode 100644 index ddd0439..0000000 Binary files a/document/web-docs/docs/.vuepress/public/images/icons/android-chrome-192x192.png and /dev/null differ diff --git a/document/web-docs/docs/.vuepress/public/images/icons/android-chrome-384x384.png b/document/web-docs/docs/.vuepress/public/images/icons/android-chrome-384x384.png deleted file mode 100644 index 86e1fd5..0000000 Binary files a/document/web-docs/docs/.vuepress/public/images/icons/android-chrome-384x384.png and /dev/null differ diff --git a/document/web-docs/docs/.vuepress/public/images/icons/apple-touch-icon.png b/document/web-docs/docs/.vuepress/public/images/icons/apple-touch-icon.png deleted file mode 100644 index 208915f..0000000 Binary files a/document/web-docs/docs/.vuepress/public/images/icons/apple-touch-icon.png and /dev/null differ diff --git a/document/web-docs/docs/.vuepress/public/images/icons/favicon-16x16.png b/document/web-docs/docs/.vuepress/public/images/icons/favicon-16x16.png deleted file mode 100644 index ca5047e..0000000 Binary files a/document/web-docs/docs/.vuepress/public/images/icons/favicon-16x16.png and /dev/null differ diff --git a/document/web-docs/docs/.vuepress/public/images/icons/favicon-32x32.png b/document/web-docs/docs/.vuepress/public/images/icons/favicon-32x32.png deleted file mode 100644 index e275ce9..0000000 Binary files a/document/web-docs/docs/.vuepress/public/images/icons/favicon-32x32.png and /dev/null differ diff --git a/document/web-docs/docs/.vuepress/public/images/icons/mstile-150x150.png b/document/web-docs/docs/.vuepress/public/images/icons/mstile-150x150.png deleted file mode 100644 index d0b1439..0000000 Binary files a/document/web-docs/docs/.vuepress/public/images/icons/mstile-150x150.png and /dev/null differ diff --git a/document/web-docs/docs/guide/custom.md b/document/web-docs/docs/guide/custom.md index 0511189..6699495 100644 --- a/document/web-docs/docs/guide/custom.md +++ b/document/web-docs/docs/guide/custom.md @@ -1,54 +1,106 @@ # 自定义约束注解 -如果你使用过 `javax.validation` 的自定义约束注解,那么你会发现 `SpEL Validator` 的自定义约束注解几乎与 `javax.validation` -一致。 +::: tip +如果你使用过 `javax.validation` 的自定义约束注解,那么你会发现 `SpEL Validator` 的自定义约束注解几乎与 `javax.validation` 一致。 +::: -下面以 `@SpelNotNull` 为例,展示如何实现自定义约束注解。 - -**以下内容还没写完** +下面以 `@SpelNotBlank` 为例,展示如何实现自定义约束注解。 ## 创建约束注解类 +每个约束注释必须包含以下属性: +- `String message() default "";` 用于指定约束校验失败时的错误消息。 +- `String condition() default "";` 用于指定约束开启条件的SpEL表达式。 +- `String[] group() default {};` 用于指定分组条件的SpEL表达式。 + ```java -@Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER}) -@Retention(RetentionPolicy.RUNTIME) @Documented -@Constraint(validatedBy = SpelNotNullValidator.class) -public @interface SpelNotNull { +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.FIELD) +@Repeatable(SpelNotBlank.List.class) +public @interface SpelNotBlank { - String message() default "{javax.validation.constraints.NotNull.message}"; + String message() default "不能为空字符串"; - Class[] groups() default {}; + String condition() default ""; - Class[] payload() default {}; + String[] group() default {}; - String condition() default ""; + @Target(FIELD) + @Retention(RUNTIME) + @Documented + @interface List { + + SpelNotBlank[] value(); + + } } ``` ## 创建约束验证器 +创建类 `SpelNotBlankValidator`,实现 `SpelConstraintValidator` 接口,其中泛型 `T` 为要校验的约束注解类,在这里是 `SpelNotBlank`。 + +实现 `isValid` 方法,校验逻辑在该方法中实现。 + +`isValid` 方法的参数说明如下: +- `annotation`:当前约束注解的实例。 +- `obj`:当前校验的根对象。 +- `field`:当前校验的字段。 + ```java -public class SpelNotNullValidator implements ConstraintValidator { +public class SpelNotBlankValidator implements SpelConstraintValidator { + + @Override + public FieldValidResult isValid(SpelNotBlank annotation, Object obj, Field field) throws IllegalAccessException { + CharSequence fieldValue = (CharSequence) field.get(obj); + return new FieldValidResult(StringUtils.hasText(fieldValue)); + } + +} +``` + +一般情况下,只需要校验当前字段的值,通过 `field.get(obj)` 即可获取。 + +有些约束注解可能仅支持特定类型的字段,可以通过重写 `supportType()` 方法来指定支持的类型。默认情况下,支持所有类型。 - private String condition; +```java +public class SpelNotBlankValidator implements SpelConstraintValidator { @Override - public void initialize(SpelNotNull constraintAnnotation) { - this.condition = constraintAnnotation.condition(); + public FieldValidResult isValid(SpelNotBlank annotation, Object obj, Field field) throws IllegalAccessException { + CharSequence fieldValue = (CharSequence) field.get(obj); + return new FieldValidResult(StringUtils.hasText(fieldValue)); } + private static final Set> SUPPORT_TYPE = Collections.singleton(CharSequence.class); + @Override - public boolean isValid(Object value, ConstraintValidatorContext context) { - if (value == null) { - return false; - } - if (StringUtils.hasText(condition)) { - return SpelUtils.evaluate(condition, value, Boolean.class); - } - return true; + public Set> supportType() { + return SUPPORT_TYPE; } } ``` + +## 关联注解和验证器 + +在 `SpelNotBlank` 注解上添加 `@SpelConstraint` 注解,指定该注解的验证器为 `SpelNotBlankValidator`。 + +```java +@Documented +@Retention(RUNTIME) +@Target(FIELD) +@Repeatable(SpelNotBlank.List.class) +@SpelConstraint(validatedBy = SpelNotBlankValidator.class) // 关联验证器 +public @interface SpelNotBlank { + // ... +} +``` + +## 使用自定义约束注解 + +完成上面的步骤,就可以在需要校验的字段上使用 `@SpelNotBlank` 注解了,使用方法就和内置的约束注解一样,[使用指南](user-guide.md)。 + +已经大功告成了,这里我就不举例了。 diff --git a/document/web-docs/docs/guide/getting-started.md b/document/web-docs/docs/guide/getting-started.md index fd7c535..6a53120 100644 --- a/document/web-docs/docs/guide/getting-started.md +++ b/document/web-docs/docs/guide/getting-started.md @@ -1,6 +1,8 @@ # 快速开始 -- 支持JDK8+ +:::tip +本章仅介绍如何快速上手 SpEL Validator 的基本使用,更详细的使用说明请参考 [使用指南](user-guide.md)。 +::: ## 添加依赖 diff --git a/document/web-docs/docs/guide/spel.md b/document/web-docs/docs/guide/spel.md index 2cd7fef..e04a473 100644 --- a/document/web-docs/docs/guide/spel.md +++ b/document/web-docs/docs/guide/spel.md @@ -2,14 +2,57 @@ 本章只介绍一些重要的 SpEL 表达式用法,更详细的使用说明请参考官方文档。 -官方文档:[Spring Expression Language (SpEL)](https://docs.spring.io/spring-framework/reference/core/expressions.html) +官方文档:[Spring Expression Language (SpEL)](https://docs.spring.io/spring-framework/reference/core/expressions/language-ref.html) ::: tip -如果你的 IDEA 版本比较新,那么不出意外的话,IDEA 能够识别到表达式,并且会给出提示,也具备引用的功能。 +如果你的 IDEA 版本比较新,理论上来说,IDEA 应该能够识别到表达式,并且会给出提示,也具备引用的功能。 ::: +## 基本操作符 + +> 此部分由GPT生成,进行了部分删减。 + +1. **算术操作符** + - `+` 加法 + - `-` 减法 + - `*` 乘法 + - `/` 除法 + - `%` 取模 + +2. **关系操作符** + - `==` 等于 + - `!=` 不等于 + - `<` 小于 + - `<=` 小于等于 + - `>` 大于 + - `>=` 大于等于 + +3. **逻辑操作符** + - `&&` 逻辑与 + - `||` 逻辑或 + - `!` 逻辑非 + +4. **条件操作符(三元操作符)** + - `? :` 条件表达式,类似于 Java 中的 `? :` + +5. **成员访问** + - `.` 属性访问 + - `[]` 属性访问(使用字符串键) + +6. **集合操作符** + - `in` 判断元素是否在集合中 + - `!in` 判断元素是否不在集合中 + +7. **空安全操作符** + - `?.` 空安全属性访问 + - `:?` 空安全方法调用 + +8. **空合并操作符** + - `?:` 当左侧表达式为 null 时,返回右侧表达式的值 + + ## 调用静态方法 调用静态方法的语法为:`T(全类名).方法名(参数)`。 diff --git a/document/web-docs/docs/guide/user-guide.md b/document/web-docs/docs/guide/user-guide.md index 91ccb65..cf7922b 100644 --- a/document/web-docs/docs/guide/user-guide.md +++ b/document/web-docs/docs/guide/user-guide.md @@ -8,6 +8,10 @@ ::: +## 支持的版本 + +- JDK8+ + ## 添加依赖 Latest Version: