-
Notifications
You must be signed in to change notification settings - Fork 24
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
1e1967a
commit d43abed
Showing
13 changed files
with
435 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0" | ||
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> | ||
<parent> | ||
<groupId>com.admin4j</groupId> | ||
<artifactId>framework</artifactId> | ||
<version>0.8.0</version> | ||
</parent> | ||
|
||
<groupId>com.admin4j.framework</groupId> | ||
<artifactId>enum-spring-boot-starter</artifactId> | ||
<packaging>jar</packaging> | ||
|
||
<name>enum-spring-boot-starter</name> | ||
<description>优雅的使用枚举参数</description> | ||
|
||
|
||
<properties> | ||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> | ||
</properties> | ||
|
||
<dependencies> | ||
<dependency> | ||
<groupId>com.baomidou</groupId> | ||
<artifactId>mybatis-plus-annotation</artifactId> | ||
<version>3.5.3.1</version> | ||
<scope>provided</scope> | ||
</dependency> | ||
<dependency> | ||
<groupId>com.fasterxml.jackson.core</groupId> | ||
<artifactId>jackson-annotations</artifactId> | ||
<version>2.13.5</version> | ||
<scope>provided</scope> | ||
</dependency> | ||
<dependency> | ||
<groupId>org.springframework.boot</groupId> | ||
<artifactId>spring-boot-autoconfigure-processor</artifactId> | ||
<scope>provided</scope> | ||
</dependency> | ||
<dependency> | ||
<groupId>org.springframework.boot</groupId> | ||
<artifactId>spring-boot-starter-web</artifactId> | ||
<scope>test</scope> | ||
</dependency> | ||
<dependency> | ||
<groupId>org.springframework.boot</groupId> | ||
<artifactId>spring-boot-starter-test</artifactId> | ||
<scope>test</scope> | ||
</dependency> | ||
<dependency> | ||
<groupId>org.springframework</groupId> | ||
<artifactId>spring-webmvc</artifactId> | ||
</dependency> | ||
<dependency> | ||
<groupId>org.springframework.boot</groupId> | ||
<artifactId>spring-boot-autoconfigure</artifactId> | ||
</dependency> | ||
</dependencies> | ||
</project> |
49 changes: 49 additions & 0 deletions
49
...starter/src/main/java/com/admin4j/framework/autoconfigure/EnumConverterAutoConfigure.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
package com.admin4j.framework.autoconfigure; | ||
|
||
import com.admin4j.framework.converter.EnumConverter; | ||
import com.admin4j.framework.converter.impl.EnumValueConverter; | ||
import com.admin4j.framework.converter.impl.JackosnEnumConverter; | ||
import com.baomidou.mybatisplus.annotation.EnumValue; | ||
import com.fasterxml.jackson.annotation.JsonValue; | ||
import org.springframework.beans.factory.ObjectProvider; | ||
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; | ||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; | ||
import org.springframework.context.annotation.Bean; | ||
import org.springframework.core.annotation.Order; | ||
import org.springframework.core.convert.ConversionService; | ||
|
||
import java.util.List; | ||
|
||
/** | ||
* @author andanyang | ||
* @since 2023/11/1 11:37 | ||
*/ | ||
public class EnumConverterAutoConfigure { | ||
|
||
@Bean | ||
@Order(1) | ||
@ConditionalOnClass(name = "com.baomidou.mybatisplus.annotation.EnumValue") | ||
public EnumValueConverter enumValueConverter() { | ||
return new EnumValueConverter(EnumValue.class); | ||
} | ||
|
||
@Bean | ||
@Order(2) | ||
@ConditionalOnClass(name = "com.fasterxml.jackson.annotation.JsonValue") | ||
public EnumValueConverter jsonEnumValueConverter() { | ||
return new EnumValueConverter(JsonValue.class); | ||
} | ||
|
||
@Bean | ||
@Order(3) | ||
@ConditionalOnClass(name = "com.fasterxml.jackson.annotation.JsonCreator") | ||
public JackosnEnumConverter jackosnEnumConverter(ObjectProvider<ConversionService> objectProvider) { | ||
return new JackosnEnumConverter(objectProvider); | ||
} | ||
|
||
@Bean | ||
@ConditionalOnBean(EnumConverter.class) | ||
public EnumConverterWebConfigure enumConverterWebConfigure(List<EnumConverter> enumConverters) { | ||
return new EnumConverterWebConfigure(enumConverters); | ||
} | ||
} |
24 changes: 24 additions & 0 deletions
24
...-starter/src/main/java/com/admin4j/framework/autoconfigure/EnumConverterWebConfigure.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
package com.admin4j.framework.autoconfigure; | ||
|
||
import com.admin4j.framework.converter.EnumConverter; | ||
import com.admin4j.framework.converter.factory.EnumConverterFactory; | ||
import lombok.RequiredArgsConstructor; | ||
import org.springframework.format.FormatterRegistry; | ||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; | ||
|
||
import java.util.List; | ||
|
||
/** | ||
* @author andanyang | ||
* @since 2023/11/1 13:26 | ||
*/ | ||
@RequiredArgsConstructor | ||
public class EnumConverterWebConfigure implements WebMvcConfigurer { | ||
|
||
private final List<EnumConverter> enumConverters; | ||
|
||
@Override | ||
public void addFormatters(FormatterRegistry registry) { | ||
registry.addConverterFactory(new EnumConverterFactory(enumConverters)); | ||
} | ||
} |
16 changes: 16 additions & 0 deletions
16
enum-spring-boot-starter/src/main/java/com/admin4j/framework/converter/EnumConverter.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
package com.admin4j.framework.converter; | ||
|
||
import org.springframework.lang.Nullable; | ||
|
||
/** | ||
* 枚举转化器 | ||
* | ||
* @author andanyang | ||
* @since 2023/11/1 9:57 | ||
*/ | ||
public interface EnumConverter { | ||
|
||
|
||
@Nullable | ||
<T extends Enum> T convert(String source, Class<T> enumType); | ||
} |
67 changes: 67 additions & 0 deletions
67
...t-starter/src/main/java/com/admin4j/framework/converter/factory/EnumConverterFactory.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
package com.admin4j.framework.converter.factory; | ||
|
||
|
||
import com.admin4j.framework.converter.EnumConverter; | ||
import lombok.RequiredArgsConstructor; | ||
import org.springframework.core.convert.converter.Converter; | ||
import org.springframework.core.convert.converter.ConverterFactory; | ||
|
||
import java.util.List; | ||
import java.util.Map; | ||
import java.util.concurrent.ConcurrentHashMap; | ||
|
||
/** | ||
* @author andanyang | ||
* @since 2023/11/1 9:22 | ||
*/ | ||
@RequiredArgsConstructor | ||
public class EnumConverterFactory implements ConverterFactory<String, Enum> { | ||
|
||
@SuppressWarnings("rawtypes") | ||
private static final Map<Class, Converter> CONVERTERS = new ConcurrentHashMap<>(64); | ||
private final List<EnumConverter> enumConverters; | ||
|
||
/** | ||
* Get the converter to convert from S to target type T, where T is also an instance of R. | ||
* | ||
* @param targetType the target type to convert to | ||
* @return a converter from S to T | ||
*/ | ||
@Override | ||
public <T extends Enum> Converter<String, T> getConverter(Class<T> targetType) { | ||
return CONVERTERS.computeIfAbsent(targetType, (key) -> new StringToEnum<T>(targetType, enumConverters)); | ||
} | ||
|
||
private static class StringToEnum<T extends Enum> implements Converter<String, T> { | ||
|
||
private final Class<T> enumType; | ||
private final List<EnumConverter> enumConverters; | ||
|
||
StringToEnum(Class<T> enumType, List<EnumConverter> enumConverters) { | ||
this.enumType = enumType; | ||
this.enumConverters = enumConverters; | ||
} | ||
|
||
/** | ||
* Convert the source object of type {@code S} to target type {@code T}. | ||
* | ||
* @param source the source object to convert, which must be an instance of {@code S} (never {@code null}) | ||
* @return the converted object, which must be an instance of {@code T} (potentially {@code null}) | ||
* @throws IllegalArgumentException if the source cannot be converted to the desired target type | ||
*/ | ||
@Override | ||
public T convert(String source) { | ||
if (source.isEmpty()) { | ||
// It's an empty enum identifier: reset the enum value to null. | ||
return null; | ||
} | ||
for (EnumConverter enumConverter : enumConverters) { | ||
T convert = enumConverter.convert(source, enumType); | ||
if (convert != null) { | ||
return convert; | ||
} | ||
} | ||
return null; | ||
} | ||
} | ||
} |
53 changes: 53 additions & 0 deletions
53
...g-boot-starter/src/main/java/com/admin4j/framework/converter/impl/EnumValueConverter.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
package com.admin4j.framework.converter.impl; | ||
|
||
|
||
import com.admin4j.framework.converter.EnumConverter; | ||
|
||
import java.lang.annotation.Annotation; | ||
import java.lang.reflect.Field; | ||
|
||
/** | ||
* 使用 EnumValue注解 字段进行匹配 | ||
* | ||
* @author andanyang | ||
* @since 2023/11/1 10:07 | ||
*/ | ||
// @Service | ||
public class EnumValueConverter<A extends Annotation> implements EnumConverter { | ||
|
||
private final Class<A> targetAnnotation; | ||
|
||
public EnumValueConverter(Class<A> targetAnnotation) { | ||
this.targetAnnotation = targetAnnotation; | ||
} | ||
|
||
@Override | ||
public <T extends Enum> T convert(String source, Class<T> enumType) { | ||
|
||
// 被注解的值字段 | ||
Field valueField = null; | ||
Field[] declaredFields = enumType.getDeclaredFields(); | ||
for (Field field : declaredFields) { | ||
Annotation annotation = field.getAnnotation(targetAnnotation); | ||
if (annotation != null) { | ||
valueField = field; | ||
} | ||
} | ||
|
||
if (valueField != null) { | ||
T[] enumConstants = enumType.getEnumConstants(); | ||
// 查找枚举 | ||
for (T e : enumConstants) { | ||
try { | ||
valueField.setAccessible(true); | ||
if (String.valueOf(valueField.get(e)).equals(source)) { | ||
return e; | ||
} | ||
} catch (IllegalAccessException ex) { | ||
throw new RuntimeException(ex); | ||
} | ||
} | ||
} | ||
return null; | ||
} | ||
} |
55 changes: 55 additions & 0 deletions
55
...boot-starter/src/main/java/com/admin4j/framework/converter/impl/JackosnEnumConverter.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
package com.admin4j.framework.converter.impl; | ||
|
||
|
||
import com.admin4j.framework.converter.EnumConverter; | ||
import com.fasterxml.jackson.annotation.JsonCreator; | ||
import lombok.RequiredArgsConstructor; | ||
import org.springframework.beans.factory.ObjectProvider; | ||
import org.springframework.core.convert.ConversionService; | ||
|
||
import java.lang.reflect.InvocationTargetException; | ||
import java.lang.reflect.Method; | ||
|
||
/** | ||
* 使用 @JsonCreator 方法注解静态字段进行匹配 | ||
* | ||
* @author andanyang | ||
* @since 2023/11/1 10:07 | ||
*/ | ||
|
||
@RequiredArgsConstructor | ||
public class JackosnEnumConverter implements EnumConverter { | ||
|
||
private final ObjectProvider<ConversionService> conversionServiceObjectProvider; | ||
|
||
@Override | ||
public <T extends Enum> T convert(String source, Class<T> enumType) { | ||
|
||
Method[] declaredMethods = enumType.getDeclaredMethods(); | ||
|
||
for (Method method : declaredMethods) { | ||
if (method.isAnnotationPresent(JsonCreator.class)) { | ||
try { | ||
Object invoke; | ||
Class<?> parameterType = method.getParameterTypes()[0]; | ||
Object cast = conversionServiceObjectProvider.getIfAvailable().convert(source, parameterType); | ||
invoke = method.invoke(enumType, cast); | ||
|
||
if (invoke == null) { | ||
return null; | ||
} | ||
if (!enumType.isInstance(invoke)) { | ||
throw new IllegalArgumentException("JsonCreator error: target " + enumType.getCanonicalName() + " but get " + invoke.getClass().getCanonicalName()); | ||
} | ||
|
||
} catch (IllegalAccessException e) { | ||
throw new RuntimeException(e); | ||
} catch (InvocationTargetException e) { | ||
throw new RuntimeException(e); | ||
} | ||
} | ||
} | ||
|
||
return null; | ||
} | ||
} |
2 changes: 2 additions & 0 deletions
2
enum-spring-boot-starter/src/main/resources/META-INF/spring.factories
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ | ||
com.admin4j.framework.autoconfigure.EnumConverterAutoConfigure |
14 changes: 14 additions & 0 deletions
14
enum-spring-boot-starter/src/test/java/com/admin4j/framework/AppTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
package com.admin4j.framework; | ||
|
||
import org.springframework.boot.SpringApplication; | ||
import org.springframework.boot.autoconfigure.SpringBootApplication; | ||
|
||
/** | ||
* Unit test for simple App. | ||
*/ | ||
@SpringBootApplication | ||
public class AppTest { | ||
public static void main(String[] args) { | ||
SpringApplication.run(AppTest.class); | ||
} | ||
} |
40 changes: 40 additions & 0 deletions
40
enum-spring-boot-starter/src/test/java/com/admin4j/framework/EnumConverterTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
package com.admin4j.framework; | ||
|
||
import org.junit.jupiter.api.Assertions; | ||
import org.junit.jupiter.params.ParameterizedTest; | ||
import org.junit.jupiter.params.provider.ValueSource; | ||
import org.springframework.beans.factory.annotation.Autowired; | ||
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; | ||
import org.springframework.boot.test.context.SpringBootTest; | ||
import org.springframework.test.web.servlet.MockMvc; | ||
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; | ||
import org.springframework.test.web.servlet.result.MockMvcResultHandlers; | ||
import org.springframework.test.web.servlet.result.MockMvcResultMatchers; | ||
|
||
/** | ||
* @author andanyang | ||
* @since 2023/11/1 11:58 | ||
*/ | ||
@SpringBootTest(classes = AppTest.class) | ||
@AutoConfigureMockMvc | ||
public class EnumConverterTest { | ||
|
||
@Autowired | ||
private MockMvc mockMvc; | ||
|
||
@ParameterizedTest | ||
@ValueSource(strings = {"3", "2", "1"}) | ||
void genderIdCode(String userStatus) throws Exception { | ||
final String result = mockMvc.perform( | ||
MockMvcRequestBuilders.get("/UserStatus") | ||
.param("userStatus", userStatus) | ||
) | ||
.andExpect(MockMvcResultMatchers.status().isOk()) | ||
.andDo(MockMvcResultHandlers.print()) | ||
.andReturn() | ||
.getResponse() | ||
.getContentAsString(); | ||
|
||
Assertions.assertEquals(result, userStatus); | ||
} | ||
} |
Oops, something went wrong.