init
This commit is contained in:
38
.gitignore
vendored
Normal file
38
.gitignore
vendored
Normal file
@ -0,0 +1,38 @@
|
||||
target/
|
||||
!.mvn/wrapper/maven-wrapper.jar
|
||||
!**/src/main/**/target/
|
||||
!**/src/test/**/target/
|
||||
|
||||
### IntelliJ IDEA ###
|
||||
.idea/modules.xml
|
||||
.idea/jarRepositories.xml
|
||||
.idea/compiler.xml
|
||||
.idea/libraries/
|
||||
*.iws
|
||||
*.iml
|
||||
*.ipr
|
||||
|
||||
### Eclipse ###
|
||||
.apt_generated
|
||||
.classpath
|
||||
.factorypath
|
||||
.project
|
||||
.settings
|
||||
.springBeans
|
||||
.sts4-cache
|
||||
|
||||
### NetBeans ###
|
||||
/nbproject/private/
|
||||
/nbbuild/
|
||||
/dist/
|
||||
/nbdist/
|
||||
/.nb-gradle/
|
||||
build/
|
||||
!**/src/main/**/build/
|
||||
!**/src/test/**/build/
|
||||
|
||||
### VS Code ###
|
||||
.vscode/
|
||||
|
||||
### Mac OS ###
|
||||
.DS_Store
|
8
.idea/.gitignore
generated
vendored
Normal file
8
.idea/.gitignore
generated
vendored
Normal file
@ -0,0 +1,8 @@
|
||||
# 默认忽略的文件
|
||||
/shelf/
|
||||
/workspace.xml
|
||||
# 基于编辑器的 HTTP 客户端请求
|
||||
/httpRequests/
|
||||
# Datasource local storage ignored files
|
||||
/dataSources/
|
||||
/dataSources.local.xml
|
7
.idea/encodings.xml
generated
Normal file
7
.idea/encodings.xml
generated
Normal file
@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="Encoding">
|
||||
<file url="file://$PROJECT_DIR$/src/main/java" charset="UTF-8" />
|
||||
<file url="file://$PROJECT_DIR$/src/main/resources" charset="UTF-8" />
|
||||
</component>
|
||||
</project>
|
6
.idea/git_toolbox_blame.xml
generated
Normal file
6
.idea/git_toolbox_blame.xml
generated
Normal file
@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="GitToolBoxBlameSettings">
|
||||
<option name="version" value="2" />
|
||||
</component>
|
||||
</project>
|
10
.idea/material_theme_project_new.xml
generated
Normal file
10
.idea/material_theme_project_new.xml
generated
Normal file
@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="MaterialThemeProjectNewConfig">
|
||||
<option name="metadata">
|
||||
<MTProjectMetadataState>
|
||||
<option name="userId" value="-6730a49d:190ceb01e77:-7fb9" />
|
||||
</MTProjectMetadataState>
|
||||
</option>
|
||||
</component>
|
||||
</project>
|
14
.idea/misc.xml
generated
Normal file
14
.idea/misc.xml
generated
Normal file
@ -0,0 +1,14 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ExternalStorageConfigurationManager" enabled="true" />
|
||||
<component name="MavenProjectsManager">
|
||||
<option name="originalFiles">
|
||||
<list>
|
||||
<option value="$PROJECT_DIR$/pom.xml" />
|
||||
</list>
|
||||
</option>
|
||||
</component>
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_21" default="true" project-jdk-name="oracle-21.0.2" project-jdk-type="JavaSDK">
|
||||
<output url="file://$PROJECT_DIR$/out" />
|
||||
</component>
|
||||
</project>
|
124
.idea/uiDesigner.xml
generated
Normal file
124
.idea/uiDesigner.xml
generated
Normal file
@ -0,0 +1,124 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="Palette2">
|
||||
<group name="Swing">
|
||||
<item class="com.intellij.uiDesigner.HSpacer" tooltip-text="Horizontal Spacer" icon="/com/intellij/uiDesigner/icons/hspacer.svg" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||
<default-constraints vsize-policy="1" hsize-policy="6" anchor="0" fill="1" />
|
||||
</item>
|
||||
<item class="com.intellij.uiDesigner.VSpacer" tooltip-text="Vertical Spacer" icon="/com/intellij/uiDesigner/icons/vspacer.svg" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||
<default-constraints vsize-policy="6" hsize-policy="1" anchor="0" fill="2" />
|
||||
</item>
|
||||
<item class="javax.swing.JPanel" icon="/com/intellij/uiDesigner/icons/panel.svg" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3" />
|
||||
</item>
|
||||
<item class="javax.swing.JScrollPane" icon="/com/intellij/uiDesigner/icons/scrollPane.svg" removable="false" auto-create-binding="false" can-attach-label="true">
|
||||
<default-constraints vsize-policy="7" hsize-policy="7" anchor="0" fill="3" />
|
||||
</item>
|
||||
<item class="javax.swing.JButton" icon="/com/intellij/uiDesigner/icons/button.svg" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="3" anchor="0" fill="1" />
|
||||
<initial-values>
|
||||
<property name="text" value="Button" />
|
||||
</initial-values>
|
||||
</item>
|
||||
<item class="javax.swing.JRadioButton" icon="/com/intellij/uiDesigner/icons/radioButton.svg" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
|
||||
<initial-values>
|
||||
<property name="text" value="RadioButton" />
|
||||
</initial-values>
|
||||
</item>
|
||||
<item class="javax.swing.JCheckBox" icon="/com/intellij/uiDesigner/icons/checkBox.svg" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
|
||||
<initial-values>
|
||||
<property name="text" value="CheckBox" />
|
||||
</initial-values>
|
||||
</item>
|
||||
<item class="javax.swing.JLabel" icon="/com/intellij/uiDesigner/icons/label.svg" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="0" anchor="8" fill="0" />
|
||||
<initial-values>
|
||||
<property name="text" value="Label" />
|
||||
</initial-values>
|
||||
</item>
|
||||
<item class="javax.swing.JTextField" icon="/com/intellij/uiDesigner/icons/textField.svg" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
|
||||
<preferred-size width="150" height="-1" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JPasswordField" icon="/com/intellij/uiDesigner/icons/passwordField.svg" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
|
||||
<preferred-size width="150" height="-1" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JFormattedTextField" icon="/com/intellij/uiDesigner/icons/formattedTextField.svg" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
|
||||
<preferred-size width="150" height="-1" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JTextArea" icon="/com/intellij/uiDesigner/icons/textArea.svg" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
|
||||
<preferred-size width="150" height="50" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JTextPane" icon="/com/intellij/uiDesigner/icons/textPane.svg" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
|
||||
<preferred-size width="150" height="50" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JEditorPane" icon="/com/intellij/uiDesigner/icons/editorPane.svg" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
|
||||
<preferred-size width="150" height="50" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JComboBox" icon="/com/intellij/uiDesigner/icons/comboBox.svg" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="0" hsize-policy="2" anchor="8" fill="1" />
|
||||
</item>
|
||||
<item class="javax.swing.JTable" icon="/com/intellij/uiDesigner/icons/table.svg" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
|
||||
<preferred-size width="150" height="50" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JList" icon="/com/intellij/uiDesigner/icons/list.svg" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="6" hsize-policy="2" anchor="0" fill="3">
|
||||
<preferred-size width="150" height="50" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JTree" icon="/com/intellij/uiDesigner/icons/tree.svg" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
|
||||
<preferred-size width="150" height="50" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JTabbedPane" icon="/com/intellij/uiDesigner/icons/tabbedPane.svg" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
|
||||
<preferred-size width="200" height="200" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JSplitPane" icon="/com/intellij/uiDesigner/icons/splitPane.svg" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
|
||||
<preferred-size width="200" height="200" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JSpinner" icon="/com/intellij/uiDesigner/icons/spinner.svg" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
|
||||
</item>
|
||||
<item class="javax.swing.JSlider" icon="/com/intellij/uiDesigner/icons/slider.svg" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
|
||||
</item>
|
||||
<item class="javax.swing.JSeparator" icon="/com/intellij/uiDesigner/icons/separator.svg" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3" />
|
||||
</item>
|
||||
<item class="javax.swing.JProgressBar" icon="/com/intellij/uiDesigner/icons/progressbar.svg" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1" />
|
||||
</item>
|
||||
<item class="javax.swing.JToolBar" icon="/com/intellij/uiDesigner/icons/toolbar.svg" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1">
|
||||
<preferred-size width="-1" height="20" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JToolBar$Separator" icon="/com/intellij/uiDesigner/icons/toolbarSeparator.svg" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="0" anchor="0" fill="1" />
|
||||
</item>
|
||||
<item class="javax.swing.JScrollBar" icon="/com/intellij/uiDesigner/icons/scrollbar.svg" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="6" hsize-policy="0" anchor="0" fill="2" />
|
||||
</item>
|
||||
</group>
|
||||
</component>
|
||||
</project>
|
6
.idea/vcs.xml
generated
Normal file
6
.idea/vcs.xml
generated
Normal file
@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="VcsDirectoryMappings">
|
||||
<mapping directory="$PROJECT_DIR$" vcs="Git" />
|
||||
</component>
|
||||
</project>
|
45
pom.xml
Normal file
45
pom.xml
Normal file
@ -0,0 +1,45 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<groupId>com.hua</groupId>
|
||||
<artifactId>utils</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
|
||||
<properties>
|
||||
<maven.compiler.source>21</maven.compiler.source>
|
||||
<maven.compiler.target>21</maven.compiler.target>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<springContext.version>5.2.1.RELEASE</springContext.version>
|
||||
<hutool.version>5.8.26</hutool.version>
|
||||
<reflections.version>0.9.10</reflections.version>
|
||||
<validation.version>2.0.1.Final</validation.version>
|
||||
</properties>
|
||||
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-context</artifactId>
|
||||
<version>${springContext.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>cn.hutool</groupId>
|
||||
<artifactId>hutool-all</artifactId>
|
||||
<version>${hutool.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.reflections</groupId>
|
||||
<artifactId>reflections</artifactId>
|
||||
<version>${reflections.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>javax.validation</groupId>
|
||||
<artifactId>validation-api</artifactId>
|
||||
<version>${validation.version}</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
</project>
|
13
src/main/java/com/hua/annotation/Handles.java
Normal file
13
src/main/java/com/hua/annotation/Handles.java
Normal file
@ -0,0 +1,13 @@
|
||||
package com.hua.annotation;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
/**
|
||||
* @author Hua
|
||||
* @since 2024/7/18 下午2:43
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.TYPE)
|
||||
public @interface Handles {
|
||||
Class<? extends Annotation> value();
|
||||
}
|
42
src/main/java/com/hua/test/valid/Student.java
Normal file
42
src/main/java/com/hua/test/valid/Student.java
Normal file
@ -0,0 +1,42 @@
|
||||
package com.hua.test.valid;
|
||||
|
||||
import com.hua.valid.annotation.ConditionNotNull;
|
||||
|
||||
/**
|
||||
* @author Hua
|
||||
* @since 2024/7/18 下午2:43
|
||||
*/
|
||||
public class Student {
|
||||
|
||||
@ConditionNotNull(test = "teaName == '王老师' and teaAge == 28 and teaSex == 1", message = "老师名字为王老师,年龄为18,性别为1的时候 name不能为null")
|
||||
private String name;
|
||||
|
||||
private int age;
|
||||
|
||||
private int sex;
|
||||
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public int getAge() {
|
||||
return age;
|
||||
}
|
||||
|
||||
public void setAge(int age) {
|
||||
this.age = age;
|
||||
}
|
||||
|
||||
public int getSex() {
|
||||
return sex;
|
||||
}
|
||||
|
||||
public void setSex(int sex) {
|
||||
this.sex = sex;
|
||||
}
|
||||
}
|
56
src/main/java/com/hua/test/valid/Teach.java
Normal file
56
src/main/java/com/hua/test/valid/Teach.java
Normal file
@ -0,0 +1,56 @@
|
||||
package com.hua.test.valid;
|
||||
|
||||
import com.hua.valid.annotation.ValidPlus;
|
||||
|
||||
import javax.validation.Valid;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Hua
|
||||
* @since 2024/7/18 下午2:43
|
||||
*/
|
||||
@ValidPlus
|
||||
public class Teach {
|
||||
|
||||
private String teaName;
|
||||
private int teaAge;
|
||||
|
||||
|
||||
private int teaSex;
|
||||
|
||||
@Valid
|
||||
private List<Student> listStu;
|
||||
|
||||
|
||||
public String getTeaName() {
|
||||
return teaName;
|
||||
}
|
||||
|
||||
public void setTeaName(String teaName) {
|
||||
this.teaName = teaName;
|
||||
}
|
||||
|
||||
public int getTeaAge() {
|
||||
return teaAge;
|
||||
}
|
||||
|
||||
public void setTeaAge(int teaAge) {
|
||||
this.teaAge = teaAge;
|
||||
}
|
||||
|
||||
public int getTeaSex() {
|
||||
return teaSex;
|
||||
}
|
||||
|
||||
public void setTeaSex(int teaSex) {
|
||||
this.teaSex = teaSex;
|
||||
}
|
||||
|
||||
public List<Student> getListStu() {
|
||||
return listStu;
|
||||
}
|
||||
|
||||
public void setListStu(List<Student> listStu) {
|
||||
this.listStu = listStu;
|
||||
}
|
||||
}
|
49
src/main/java/com/hua/test/valid/Test.java
Normal file
49
src/main/java/com/hua/test/valid/Test.java
Normal file
@ -0,0 +1,49 @@
|
||||
package com.hua.test.valid;
|
||||
|
||||
import com.hua.valid.AnnotationHandleFactory;
|
||||
import com.hua.valid.ErrorMessage;
|
||||
import com.hua.valid.HandleDTO;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class Test {
|
||||
public static void main(String[] args) {
|
||||
Teach teach = init();
|
||||
|
||||
ErrorMessage errorMessage = new ErrorMessage();
|
||||
if (!AnnotationHandleFactory.handle(new HandleDTO.HandleDTOBuilder()
|
||||
.setOriginObj(teach)
|
||||
.setAnnotations(teach.getListStu().get(0).getClass().getDeclaredFields()[0].getAnnotations())
|
||||
.setField(teach.getListStu().get(0).getClass().getDeclaredFields()[0])
|
||||
.setFieldValue(teach.getListStu().get(0).getName())
|
||||
.setErrorMessage(errorMessage)
|
||||
.build())) {
|
||||
System.out.println("验证失败: " + errorMessage.getErrorMessage());
|
||||
} else {
|
||||
System.out.println("验证成功");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static Teach init() {
|
||||
Student student = new Student();
|
||||
student.setName("张同学");
|
||||
student.setAge(18);
|
||||
student.setSex(1);
|
||||
|
||||
Student student1 = new Student();
|
||||
student1.setName(null);
|
||||
student1.setAge(19);
|
||||
student1.setSex(2);
|
||||
Teach teach = new Teach();
|
||||
teach.setTeaAge(28);
|
||||
teach.setTeaName("王老师");
|
||||
teach.setTeaSex(1);
|
||||
|
||||
List<Student> student11 = List.of(student1, student);
|
||||
teach.setListStu(student11);
|
||||
return teach;
|
||||
}
|
||||
|
||||
|
||||
}
|
147
src/main/java/com/hua/valid/AnnotationHandleFactory.java
Normal file
147
src/main/java/com/hua/valid/AnnotationHandleFactory.java
Normal file
@ -0,0 +1,147 @@
|
||||
package com.hua.valid;
|
||||
|
||||
import cn.hutool.core.util.ArrayUtil;
|
||||
import com.hua.annotation.Handles;
|
||||
import com.hua.valid.annotation.PackageScanConfig;
|
||||
import org.reflections.Reflections;
|
||||
import org.reflections.scanners.SubTypesScanner;
|
||||
import org.reflections.scanners.TypeAnnotationsScanner;
|
||||
import org.reflections.util.ClasspathHelper;
|
||||
import org.reflections.util.ConfigurationBuilder;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.ServiceLoader;
|
||||
import java.util.Set;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
/**
|
||||
* @author Hua
|
||||
* @since 2024/7/18 下午2:43
|
||||
*/
|
||||
public class AnnotationHandleFactory {
|
||||
|
||||
// 缓存已加载的注解处理器
|
||||
private static final Map<Class<? extends Annotation>, AnnotationHandler> cache = new HashMap<>();
|
||||
private static boolean useSPI = true; // 是否使用SPI加载处理器
|
||||
private static boolean useReflection = false; // 是否使用反射加载处理器
|
||||
private static String[] packagesToScan = {"com.hua.valid"}; // 反射扫描的包路径
|
||||
|
||||
// 静态初始化块,在类加载时进行处理器初始化
|
||||
static {
|
||||
resolvePackageConfig();
|
||||
initializeHandlers();
|
||||
}
|
||||
|
||||
/**
|
||||
* 配置处理器加载方式和扫描路径。
|
||||
*
|
||||
* @param useSpi 是否使用SPI加载处理器。
|
||||
* @param useRef 是否使用反射加载处理器。
|
||||
* @param packages 反射扫描的包路径。
|
||||
*/
|
||||
public static void configure(boolean useSpi, boolean useRef, String[] packages) {
|
||||
useSPI = useSpi;
|
||||
useReflection = useRef;
|
||||
packagesToScan = packages;
|
||||
cache.clear(); // 清除缓存
|
||||
initializeHandlers(); // 重新初始化处理器
|
||||
}
|
||||
|
||||
private static void resolvePackageConfig() {
|
||||
Reflections reflections = new Reflections(new ConfigurationBuilder()
|
||||
.setUrls(ClasspathHelper.forJavaClassPath())
|
||||
.setScanners(new TypeAnnotationsScanner(), new SubTypesScanner()));
|
||||
|
||||
// 查找所有应用了PackageScanConfig注解的类
|
||||
Set<Class<?>> configClasses = reflections.getTypesAnnotatedWith(PackageScanConfig.class);
|
||||
if (configClasses.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
PackageScanConfig config = configClasses.stream().findFirst().get().getAnnotation(PackageScanConfig.class);
|
||||
useSPI = config.useSPI();
|
||||
useReflection = config.useReflection();
|
||||
packagesToScan = config.packages();
|
||||
}
|
||||
|
||||
// 初始化处理器,根据配置决定使用SPI或反射加载
|
||||
private static void initializeHandlers() {
|
||||
if (useSPI) {
|
||||
loadHandlersViaSPI();
|
||||
}
|
||||
if (useReflection) {
|
||||
loadHandlersViaReflection();
|
||||
}
|
||||
}
|
||||
|
||||
// 通过SPI加载注解处理器
|
||||
private static void loadHandlersViaSPI() {
|
||||
ServiceLoader<AnnotationHandler> loadedHandlers = ServiceLoader.load(AnnotationHandler.class);
|
||||
loadedHandlers.forEach(handler -> {
|
||||
Handles handles = handler.getClass().getAnnotation(Handles.class);
|
||||
if (handles != null) {
|
||||
cache.put(handles.value(), handler);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 通过反射加载注解处理器
|
||||
private static void loadHandlersViaReflection() {
|
||||
// 单独的方法用于加载处理器
|
||||
Consumer<Reflections> loadHandlers = (reflections) -> {
|
||||
reflections.getTypesAnnotatedWith(Handles.class).forEach(cls -> {
|
||||
try {
|
||||
AnnotationHandler handler = (AnnotationHandler) cls.getDeclaredConstructor().newInstance();
|
||||
Handles handlesAnnotation = cls.getAnnotation(Handles.class);
|
||||
cache.put(handlesAnnotation.value(), handler);
|
||||
} catch (ReflectiveOperationException e) {
|
||||
// 推荐使用日志记录异常,而非仅仅打印堆栈信息
|
||||
e.printStackTrace();
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
if (ArrayUtil.isEmpty(packagesToScan)) {
|
||||
Reflections reflections = new Reflections(new ConfigurationBuilder()
|
||||
.setUrls(ClasspathHelper.forJavaClassPath())
|
||||
.setScanners(new TypeAnnotationsScanner(), new SubTypesScanner()));
|
||||
loadHandlers.accept(reflections);
|
||||
} else {
|
||||
for (String pkg : packagesToScan) {
|
||||
Reflections reflections = new Reflections(new ConfigurationBuilder()
|
||||
.forPackages(pkg)
|
||||
.setScanners(new SubTypesScanner(), new TypeAnnotationsScanner()));
|
||||
loadHandlers.accept(reflections);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 根据注解类型获取对应的处理器。
|
||||
*
|
||||
* @param annotation 注解实例。
|
||||
* @return 对应的注解处理器,如果未找到返回null。
|
||||
*/
|
||||
public static AnnotationHandler getHandler(Annotation annotation) {
|
||||
return cache.get(annotation.annotationType());
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理给定的注解数据对象。
|
||||
*
|
||||
* @param handleDTO 包含注解信息的数据传输对象。
|
||||
* @return 处理结果,成功或失败。
|
||||
*/
|
||||
public static boolean handle(HandleDTO handleDTO) {
|
||||
for (Annotation annotation : handleDTO.getAnnotations()) {
|
||||
AnnotationHandler handler = getHandler(annotation);
|
||||
if (handler != null) {
|
||||
handleDTO.setCurrentAnnotation(annotation);
|
||||
return handler.handle(handleDTO);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
5
src/main/java/com/hua/valid/AnnotationHandler.java
Normal file
5
src/main/java/com/hua/valid/AnnotationHandler.java
Normal file
@ -0,0 +1,5 @@
|
||||
package com.hua.valid;
|
||||
|
||||
public interface AnnotationHandler {
|
||||
boolean handle(HandleDTO handleDTO);
|
||||
}
|
32
src/main/java/com/hua/valid/ConditionNotNullHandler.java
Normal file
32
src/main/java/com/hua/valid/ConditionNotNullHandler.java
Normal file
@ -0,0 +1,32 @@
|
||||
package com.hua.valid;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.hua.annotation.Handles;
|
||||
import com.hua.valid.annotation.ConditionNotNull;
|
||||
import org.springframework.expression.ExpressionParser;
|
||||
import org.springframework.expression.spel.standard.SpelExpressionParser;
|
||||
|
||||
/**
|
||||
* @author Hua
|
||||
* @since 2024/7/18 下午2:43
|
||||
*/
|
||||
@Handles(ConditionNotNull.class)
|
||||
public class ConditionNotNullHandler implements AnnotationHandler {
|
||||
@Override
|
||||
public boolean handle(HandleDTO handleDTO) {
|
||||
ConditionNotNull conditionValidate = (ConditionNotNull) handleDTO.getCurrentAnnotation();
|
||||
String test = conditionValidate.test();
|
||||
if (StrUtil.isEmpty(test)) {
|
||||
return true;
|
||||
}
|
||||
ExpressionParser parser = new SpelExpressionParser();
|
||||
|
||||
Boolean value = parser.parseExpression(test).getValue(handleDTO.getOriginObj(), Boolean.class);
|
||||
if (Boolean.TRUE.equals(value) && handleDTO.getFieldValue() == null) {
|
||||
handleDTO.getErrorMessage().addErrorObj(conditionValidate.message(), handleDTO.getField());
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
69
src/main/java/com/hua/valid/ConditionValidateImpl.java
Normal file
69
src/main/java/com/hua/valid/ConditionValidateImpl.java
Normal file
@ -0,0 +1,69 @@
|
||||
package com.hua.valid;
|
||||
|
||||
import cn.hutool.core.util.ReflectUtil;
|
||||
import com.hua.valid.annotation.ValidPlus;
|
||||
|
||||
import javax.validation.ConstraintValidator;
|
||||
import javax.validation.ConstraintValidatorContext;
|
||||
import javax.validation.Valid;
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Hua
|
||||
* @since 2024/7/18 下午2:43
|
||||
*/
|
||||
public class ConditionValidateImpl implements ConstraintValidator<ValidPlus, Object> {
|
||||
|
||||
@Override
|
||||
public void initialize(ValidPlus constraintAnnotation) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isValid(Object o, ConstraintValidatorContext constraintValidatorContext) {
|
||||
ErrorMessage errorMessage = new ErrorMessage();
|
||||
validObj(o, errorMessage, o);
|
||||
if(errorMessage.isError()) {
|
||||
constraintValidatorContext.disableDefaultConstraintViolation();
|
||||
constraintValidatorContext.buildConstraintViolationWithTemplate(errorMessage.getErrorMessage()).addConstraintViolation();
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private void validObj(Object o, ErrorMessage errorMessage, Object originObj) {
|
||||
|
||||
if (o instanceof List<?> list) {
|
||||
for (Object obj : list) {
|
||||
validObj(obj, errorMessage,originObj);
|
||||
}
|
||||
return;
|
||||
}
|
||||
Field[] fields = ReflectUtil.getFields(o.getClass());
|
||||
for (Field field : fields) {
|
||||
Valid annotation = field.getAnnotation(Valid.class);
|
||||
if (annotation != null) {
|
||||
validObj(ReflectUtil.getFieldValue(o,field),errorMessage, originObj);
|
||||
}
|
||||
Annotation[] annotations = field.getAnnotations();
|
||||
if (annotations == null || annotations.length == 0) {
|
||||
continue;
|
||||
}
|
||||
Object fieldValue = ReflectUtil.getFieldValue(o, field);
|
||||
Annotation formatAnnotation = field.getAnnotation(ValidPlus.class);
|
||||
if (formatAnnotation == null) {
|
||||
throw new RuntimeException("Format annotation is missing on the field.");
|
||||
}
|
||||
HandleDTO handleDTO = new HandleDTO.HandleDTOBuilder().setOriginObj(originObj)
|
||||
.setAnnotations(annotations)
|
||||
.setAnnotations(annotations)
|
||||
.setField(field)
|
||||
.setErrorMessage(errorMessage)
|
||||
.setFieldValue(fieldValue).build();
|
||||
AnnotationHandleFactory.handle(handleDTO);
|
||||
}
|
||||
}
|
||||
}
|
57
src/main/java/com/hua/valid/ErrorMessage.java
Normal file
57
src/main/java/com/hua/valid/ErrorMessage.java
Normal file
@ -0,0 +1,57 @@
|
||||
package com.hua.valid;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* @author Hua
|
||||
* @since 2024/7/18 下午2:43
|
||||
*/
|
||||
public class ErrorMessage {
|
||||
|
||||
private final List<ErrorObj> listErrorObj = new ArrayList<>();
|
||||
|
||||
public void addErrorObj(String errorMessage, Field errorField){
|
||||
ErrorObj errorObj = new ErrorObj(errorMessage, errorField);
|
||||
listErrorObj.add(errorObj);
|
||||
|
||||
}
|
||||
|
||||
public boolean isError() {
|
||||
return listErrorObj.size() > 0;
|
||||
}
|
||||
|
||||
public String getErrorMessage(){
|
||||
return listErrorObj.stream().map(ErrorObj::getErrorMessage).collect(Collectors.joining(","));
|
||||
}
|
||||
|
||||
|
||||
public static class ErrorObj{
|
||||
private String errorMessage;
|
||||
|
||||
private Field errorField;
|
||||
|
||||
public ErrorObj(String errorMessage, Field errorField) {
|
||||
this.errorMessage = errorMessage;
|
||||
this.errorField = errorField;
|
||||
}
|
||||
|
||||
public String getErrorMessage() {
|
||||
return errorMessage;
|
||||
}
|
||||
|
||||
public void setErrorMessage(String errorMessage) {
|
||||
this.errorMessage = errorMessage;
|
||||
}
|
||||
|
||||
public Field getErrorField() {
|
||||
return errorField;
|
||||
}
|
||||
|
||||
public void setErrorField(Field errorField) {
|
||||
this.errorField = errorField;
|
||||
}
|
||||
}
|
||||
}
|
128
src/main/java/com/hua/valid/HandleDTO.java
Normal file
128
src/main/java/com/hua/valid/HandleDTO.java
Normal file
@ -0,0 +1,128 @@
|
||||
package com.hua.valid;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.Field;
|
||||
|
||||
/**
|
||||
* @author Hua
|
||||
* @since 2024/7/18 下午2:43
|
||||
*/
|
||||
public class HandleDTO {
|
||||
|
||||
/**
|
||||
* 要验证的实体类的原始值(有可能 实体类里面嵌套实体的情况)
|
||||
*/
|
||||
private Object originObj;
|
||||
|
||||
/**
|
||||
* 属性上加的所有的注解
|
||||
*/
|
||||
private Annotation[] annotations;
|
||||
|
||||
/**
|
||||
* 当前要处理的注解
|
||||
*/
|
||||
private Annotation currentAnnotation;
|
||||
/**
|
||||
* 加注解的那个字段
|
||||
*/
|
||||
private Field field;
|
||||
/**
|
||||
* 错误信息
|
||||
*/
|
||||
private ErrorMessage errorMessage;
|
||||
/**
|
||||
* 加注解的那个字段值
|
||||
*/
|
||||
private Object fieldValue;
|
||||
|
||||
public Object getOriginObj() {
|
||||
return originObj;
|
||||
}
|
||||
|
||||
public void setOriginObj(Object originObj) {
|
||||
this.originObj = originObj;
|
||||
}
|
||||
|
||||
public Annotation[] getAnnotations() {
|
||||
return annotations;
|
||||
}
|
||||
|
||||
public void setAnnotations(Annotation[] annotations) {
|
||||
this.annotations = annotations;
|
||||
}
|
||||
|
||||
public Field getField() {
|
||||
return field;
|
||||
}
|
||||
|
||||
public void setField(Field field) {
|
||||
this.field = field;
|
||||
}
|
||||
|
||||
public ErrorMessage getErrorMessage() {
|
||||
return errorMessage;
|
||||
}
|
||||
|
||||
public void setErrorMessage(ErrorMessage errorMessage) {
|
||||
this.errorMessage = errorMessage;
|
||||
}
|
||||
|
||||
public Object getFieldValue() {
|
||||
return fieldValue;
|
||||
}
|
||||
|
||||
public void setFieldValue(Object fieldValue) {
|
||||
this.fieldValue = fieldValue;
|
||||
}
|
||||
|
||||
public Annotation getCurrentAnnotation() {
|
||||
return currentAnnotation;
|
||||
}
|
||||
|
||||
public void setCurrentAnnotation(Annotation currentAnnotation) {
|
||||
this.currentAnnotation = currentAnnotation;
|
||||
}
|
||||
|
||||
public static class HandleDTOBuilder {
|
||||
private final HandleDTO handleDTO;
|
||||
|
||||
public HandleDTOBuilder() {
|
||||
handleDTO = new HandleDTO();
|
||||
}
|
||||
|
||||
public HandleDTOBuilder setOriginObj(Object originObj) {
|
||||
handleDTO.setOriginObj(originObj);
|
||||
return this;
|
||||
}
|
||||
|
||||
public HandleDTOBuilder setAnnotations(Annotation[] annotations) {
|
||||
handleDTO.setAnnotations(annotations);
|
||||
return this;
|
||||
}
|
||||
|
||||
public HandleDTOBuilder setField(Field field) {
|
||||
handleDTO.setField(field);
|
||||
return this;
|
||||
}
|
||||
|
||||
public HandleDTOBuilder setErrorMessage(ErrorMessage errorMessage) {
|
||||
handleDTO.setErrorMessage(errorMessage);
|
||||
return this;
|
||||
}
|
||||
|
||||
public HandleDTOBuilder setFieldValue(Object fieldValue) {
|
||||
handleDTO.setFieldValue(fieldValue);
|
||||
return this;
|
||||
}
|
||||
|
||||
public HandleDTOBuilder setCurrentAnnotation(Annotation currentAnnotation) {
|
||||
handleDTO.setCurrentAnnotation(currentAnnotation);
|
||||
return this;
|
||||
}
|
||||
|
||||
public HandleDTO build() {
|
||||
return handleDTO;
|
||||
}
|
||||
}
|
||||
}
|
16
src/main/java/com/hua/valid/annotation/ConditionNotNull.java
Normal file
16
src/main/java/com/hua/valid/annotation/ConditionNotNull.java
Normal file
@ -0,0 +1,16 @@
|
||||
package com.hua.valid.annotation;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
/**
|
||||
* @author Hua
|
||||
* @since 2024/7/18 下午2:42
|
||||
*/
|
||||
@Documented
|
||||
@Target({ElementType.PARAMETER, ElementType.FIELD})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface ConditionNotNull {
|
||||
String test() default "";
|
||||
|
||||
String message() default "";
|
||||
}
|
@ -0,0 +1,14 @@
|
||||
package com.hua.valid.annotation;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
@Target(ElementType.TYPE) // 类或接口上使用
|
||||
@Retention(RetentionPolicy.RUNTIME) // 在运行时可见
|
||||
public @interface PackageScanConfig {
|
||||
boolean useSPI() default false; // 默认为空数组
|
||||
boolean useReflection() default false; // 默认为空数组
|
||||
String[] packages() default {}; // 默认为空数组
|
||||
}
|
21
src/main/java/com/hua/valid/annotation/ValidPlus.java
Normal file
21
src/main/java/com/hua/valid/annotation/ValidPlus.java
Normal file
@ -0,0 +1,21 @@
|
||||
package com.hua.valid.annotation;
|
||||
|
||||
import com.hua.valid.ConditionValidateImpl;
|
||||
|
||||
import javax.validation.Constraint;
|
||||
import javax.validation.Payload;
|
||||
import java.lang.annotation.*;
|
||||
|
||||
/**
|
||||
* @author Hua
|
||||
* @since 2024/7/18 下午2:43
|
||||
*/
|
||||
@Documented
|
||||
@Target({ElementType.PARAMETER, ElementType.TYPE})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Constraint(validatedBy = ConditionValidateImpl.class)
|
||||
public @interface ValidPlus {
|
||||
String message() default "";
|
||||
Class<?>[] groups() default {};
|
||||
Class<? extends Payload>[] payload() default {};
|
||||
}
|
@ -0,0 +1 @@
|
||||
com.hua.valid.ConditionNotNullHandler
|
Reference in New Issue
Block a user