Explorar el Código

Merge branch 'master' into i18n-support

zhou-hao hace 3 años
padre
commit
a59cbdac1c
Se han modificado 18 ficheros con 299 adiciones y 84 borrados
  1. 7 0
      hsweb-commons/hsweb-commons-api/pom.xml
  2. 8 5
      hsweb-commons/hsweb-commons-api/src/main/java/org/hswebframework/web/api/crud/entity/EntityFactory.java
  3. 30 0
      hsweb-commons/hsweb-commons-api/src/main/java/org/hswebframework/web/api/crud/entity/EntityFactoryHolder.java
  4. 16 0
      hsweb-commons/hsweb-commons-api/src/main/java/org/hswebframework/web/api/crud/entity/EntityFactoryHolderConfiguration.java
  5. 10 3
      hsweb-commons/hsweb-commons-api/src/main/java/org/hswebframework/web/api/crud/entity/PagerResult.java
  6. 3 0
      hsweb-commons/hsweb-commons-api/src/main/resources/META-INF/spring.factories
  7. 8 2
      hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/configuration/EasyormConfiguration.java
  8. 7 0
      hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/entity/factory/EntityMappingCustomizer.java
  9. 13 11
      hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/entity/factory/MapperEntityFactory.java
  10. 26 17
      hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/web/ResponseMessage.java
  11. 2 1
      hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/web/ResponseMessageWrapper.java
  12. 14 6
      hsweb-core/src/main/java/org/hswebframework/web/dict/EnumDict.java
  13. 32 4
      hsweb-core/src/test/java/org/hswebframework/web/dict/EnumDictTest.java
  14. 0 1
      hsweb-core/src/test/java/org/hswebframework/web/dict/TestEnum.java
  15. 6 0
      hsweb-starter/pom.xml
  16. 38 24
      hsweb-starter/src/main/java/org/hswebframework/web/starter/jackson/CustomCodecsAutoConfiguration.java
  17. 26 10
      hsweb-starter/src/main/java/org/hswebframework/web/starter/jackson/CustomJackson2JsonDecoder.java
  18. 53 0
      hsweb-starter/src/test/java/org/hswebframework/web/starter/jackson/CustomJackson2JsonDecoderTest.java

+ 7 - 0
hsweb-commons/hsweb-commons-api/pom.xml

@@ -38,6 +38,13 @@
             <artifactId>hibernate-validator</artifactId>
         </dependency>
 
+        <dependency>
+            <groupId>com.google.code.findbugs</groupId>
+            <artifactId>jsr305</artifactId>
+            <version>3.0.2</version>
+            <scope>compile</scope>
+        </dependency>
+
     </dependencies>
 
 </project>

+ 8 - 5
hsweb-commons/hsweb-commons-api/src/main/java/org/hswebframework/web/api/crud/entity/EntityFactory.java

@@ -13,12 +13,14 @@
  *  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  *  * See the License for the specific language governing permissions and
  *  * limitations under the License.
- *  
+ *
  */
 
 package org.hswebframework.web.api.crud.entity;
 
 
+import javax.annotation.Nullable;
+
 /**
  * 实体工厂接口,系统各个地方使用此接口来创建实体,在实际编码中也应该使用此接口来创建实体,而不是使用new方式来创建
  *
@@ -97,11 +99,12 @@ public interface EntityFactory {
      * @param <T>         泛型
      * @return 实体类型
      */
-   default  <T> Class<T> getInstanceType(Class<T> entityClass){
-       return getInstanceType(entityClass,false);
-   }
+    default <T> Class<T> getInstanceType(Class<T> entityClass) {
+        return getInstanceType(entityClass, false);
+    }
 
-    <T> Class<T> getInstanceType(Class<T> entityClass,boolean autoRegister);
+    @Nullable
+    <T> Class<T> getInstanceType(Class<T> entityClass, boolean autoRegister);
 
     /**
      * 拷贝对象的属性

+ 30 - 0
hsweb-commons/hsweb-commons-api/src/main/java/org/hswebframework/web/api/crud/entity/EntityFactoryHolder.java

@@ -0,0 +1,30 @@
+package org.hswebframework.web.api.crud.entity;
+
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.ObjectProvider;
+import org.springframework.stereotype.Component;
+
+import java.util.function.Supplier;
+
+@Component
+@Slf4j
+public final class EntityFactoryHolder {
+
+    static EntityFactory FACTORY;
+
+    public static EntityFactory get() {
+        if (FACTORY == null) {
+            throw new IllegalStateException("EntityFactory Not Ready Yet");
+        }
+        return FACTORY;
+    }
+
+    public static <T> T newInstance(Class<T> type,
+                                    Supplier<T> mapper) {
+        if (FACTORY != null) {
+            return FACTORY.newInstance(type);
+        }
+        return mapper.get();
+    }
+
+}

+ 16 - 0
hsweb-commons/hsweb-commons-api/src/main/java/org/hswebframework/web/api/crud/entity/EntityFactoryHolderConfiguration.java

@@ -0,0 +1,16 @@
+package org.hswebframework.web.api.crud.entity;
+
+import org.springframework.context.ApplicationContextAware;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration(proxyBeanMethods = false)
+public class EntityFactoryHolderConfiguration {
+
+
+    @Bean
+    public ApplicationContextAware entityFactoryHolder() {
+        return context -> EntityFactoryHolder.FACTORY = context.getBean(EntityFactory.class);
+    }
+
+}

+ 10 - 3
hsweb-commons/hsweb-commons-api/src/main/java/org/hswebframework/web/api/crud/entity/PagerResult.java

@@ -20,7 +20,9 @@ package org.hswebframework.web.api.crud.entity;
 
 
 import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.AllArgsConstructor;
 import lombok.Getter;
+import lombok.NoArgsConstructor;
 import lombok.Setter;
 import org.hswebframework.ezorm.core.param.QueryParam;
 
@@ -33,15 +35,20 @@ public class PagerResult<E> {
     private static final long serialVersionUID = -6171751136953308027L;
 
     public static <E> PagerResult<E> empty() {
-        return new PagerResult<>(0, new ArrayList<>());
+        return of(0, new ArrayList<>());
     }
 
+    @SuppressWarnings("all")
     public static <E> PagerResult<E> of(int total, List<E> list) {
-        return new PagerResult<>(total, list);
+        PagerResult<E> result;
+        result = EntityFactoryHolder.newInstance(PagerResult.class, PagerResult::new);
+        result.setTotal(total);
+        result.setData(list);
+        return result;
     }
 
     public static <E> PagerResult<E> of(int total, List<E> list, QueryParam entity) {
-        PagerResult<E> pagerResult = new PagerResult<>(total, list);
+        PagerResult<E> pagerResult = of(total, list);
         pagerResult.setPageIndex(entity.getThinkPageIndex());
         pagerResult.setPageSize(entity.getPageSize());
         return pagerResult;

+ 3 - 0
hsweb-commons/hsweb-commons-api/src/main/resources/META-INF/spring.factories

@@ -0,0 +1,3 @@
+# Auto Configure
+org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
+org.hswebframework.web.api.crud.entity.EntityFactoryHolderConfiguration

+ 8 - 2
hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/configuration/EasyormConfiguration.java

@@ -17,6 +17,7 @@ import org.hswebframework.ezorm.rdb.operator.DatabaseOperator;
 import org.hswebframework.ezorm.rdb.operator.DefaultDatabaseOperator;
 import org.hswebframework.web.api.crud.entity.EntityFactory;
 import org.hswebframework.web.crud.annotation.EnableEasyormRepository;
+import org.hswebframework.web.crud.entity.factory.EntityMappingCustomizer;
 import org.hswebframework.web.crud.entity.factory.MapperEntityFactory;
 import org.hswebframework.web.crud.events.CompositeEventListener;
 import org.hswebframework.web.crud.events.EntityEventListener;
@@ -26,6 +27,7 @@ import org.hswebframework.web.crud.generator.DefaultIdGenerator;
 import org.hswebframework.web.crud.generator.MD5Generator;
 import org.hswebframework.web.crud.generator.SnowFlakeStringIdGenerator;
 import org.springframework.beans.BeansException;
+import org.springframework.beans.factory.ObjectProvider;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.config.BeanPostProcessor;
 import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
@@ -52,8 +54,12 @@ public class EasyormConfiguration {
 
     @Bean
     @ConditionalOnMissingBean
-    public EntityFactory entityFactory() {
-        return new MapperEntityFactory();
+    public EntityFactory entityFactory(ObjectProvider<EntityMappingCustomizer> customizers) {
+        MapperEntityFactory factory= new MapperEntityFactory();
+        for (EntityMappingCustomizer customizer : customizers) {
+            customizer.custom(factory);
+        }
+        return factory;
     }
 
     @Bean

+ 7 - 0
hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/entity/factory/EntityMappingCustomizer.java

@@ -0,0 +1,7 @@
+package org.hswebframework.web.crud.entity.factory;
+
+public interface EntityMappingCustomizer {
+
+    void custom(MapperEntityFactory factory);
+
+}

+ 13 - 11
hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/entity/factory/MapperEntityFactory.java

@@ -44,7 +44,7 @@ public class MapperEntityFactory implements EntityFactory, BeanFactory {
     private static final DefaultMapperFactory DEFAULT_MAPPER_FACTORY = clazz -> {
         String simpleClassName = clazz.getPackage().getName().concat(".Simple").concat(clazz.getSimpleName());
         try {
-            return defaultMapper(org.springframework.util.ClassUtils.forName(simpleClassName,null));
+            return defaultMapper(org.springframework.util.ClassUtils.forName(simpleClassName, null));
         } catch (ClassNotFoundException ignore) {
             // throw new NotFoundException(e.getMessage());
         }
@@ -64,7 +64,7 @@ public class MapperEntityFactory implements EntityFactory, BeanFactory {
     public MapperEntityFactory() {
     }
 
-    public MapperEntityFactory(Map<Class<?>, Mapper> realTypeMapper) {
+    public MapperEntityFactory(Map<Class<?>, Mapper<?>> realTypeMapper) {
         this.realTypeMapper.putAll(realTypeMapper);
     }
 
@@ -73,9 +73,9 @@ public class MapperEntityFactory implements EntityFactory, BeanFactory {
         return this;
     }
 
-    public MapperEntityFactory addCopier(PropertyCopier copier) {
-        Class source = ClassUtils.getGenericType(copier.getClass(), 0);
-        Class target = ClassUtils.getGenericType(copier.getClass(), 1);
+    public <S, T> MapperEntityFactory addCopier(PropertyCopier<S, T> copier) {
+        Class<S> source = (Class<S>) ClassUtils.getGenericType(copier.getClass(), 0);
+        Class<T> target = (Class<T>) ClassUtils.getGenericType(copier.getClass(), 1);
         if (source == null || source == Object.class) {
             throw new UnsupportedOperationException("generic type " + source + " not support");
         }
@@ -91,7 +91,7 @@ public class MapperEntityFactory implements EntityFactory, BeanFactory {
         return this;
     }
 
-    private String getCopierCacheKey(Class source, Class target) {
+    private String getCopierCacheKey(Class<?> source, Class<?> target) {
         return source.getName().concat("->").concat(target.getName());
     }
 
@@ -122,11 +122,13 @@ public class MapperEntityFactory implements EntityFactory, BeanFactory {
         }
 
         if (realType == null) {
-            mapper = defaultMapperFactory.apply(beanClass);
-        }
-        if (!Modifier.isInterface(beanClass.getModifiers()) && !Modifier.isAbstract(beanClass.getModifiers())) {
-            realType = beanClass;
+            if (!Modifier.isInterface(beanClass.getModifiers()) && !Modifier.isAbstract(beanClass.getModifiers())) {
+                realType = beanClass;
+            }else {
+                mapper = defaultMapperFactory.apply(beanClass);
+            }
         }
+
         if (mapper == null && realType != null) {
             if (logger.isDebugEnabled() && realType != beanClass) {
                 logger.debug("use instance {} for {}", realType, beanClass);
@@ -170,7 +172,7 @@ public class MapperEntityFactory implements EntityFactory, BeanFactory {
             return (T) new HashSet<>();
         }
 
-        throw new NotFoundException("can't create instance for " + beanClass);
+        throw new NotFoundException("无法初始化实体类:"+beanClass);
     }
 
     @Override

+ 26 - 17
hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/web/ResponseMessage.java

@@ -2,34 +2,36 @@ package org.hswebframework.web.crud.web;
 
 import com.fasterxml.jackson.annotation.JsonInclude;
 import io.swagger.v3.oas.annotations.media.Schema;
-import lombok.*;
+import lombok.Getter;
+import lombok.Setter;
+import org.hswebframework.web.api.crud.entity.EntityFactoryHolder;
 
 import java.io.Serializable;
 
 @Getter
 @Setter
-@Builder
-@AllArgsConstructor
-@NoArgsConstructor
 @JsonInclude(JsonInclude.Include.NON_NULL)
 public class ResponseMessage<T> implements Serializable {
 
     private static final long serialVersionUID = 8992436576262574064L;
 
     @Schema(description = "消息提示")
-    protected String message;
+    private String message;
 
     @Schema(description = "数据内容")
-    protected T result;
+    private T result;
 
     @Schema(description = "状态码")
     private int status;
 
     @Schema(description = "业务码")
-    protected String code;
+    private String code;
 
     @Schema(description = "时间戳(毫秒)")
-    protected Long timestamp = System.currentTimeMillis();
+    private Long timestamp = System.currentTimeMillis();
+
+    public ResponseMessage() {
+    }
 
     public static <T> ResponseMessage<T> ok() {
         return ok(null);
@@ -37,11 +39,7 @@ public class ResponseMessage<T> implements Serializable {
 
     @SuppressWarnings("all")
     public static <T> ResponseMessage<T> ok(T result) {
-        return (ResponseMessage) ResponseMessage.builder()
-                .result(result)
-                .status(200)
-                .code("success")
-                .build();
+        return of("success", result, 200, null, System.currentTimeMillis());
     }
 
     public static <T> ResponseMessage<T> error(String message) {
@@ -53,10 +51,21 @@ public class ResponseMessage<T> implements Serializable {
     }
 
     public static <T> ResponseMessage<T> error(int status, String code, String message) {
-        ResponseMessage<T> msg = new ResponseMessage<>();
-        msg.message = message;
-        msg.code = code;
-        msg.status = status;
+        return of(message, null, status, code, System.currentTimeMillis());
+    }
+
+    public static <T> ResponseMessage<T> of(String message,
+                                            T result,
+                                            int status,
+                                            String code,
+                                            Long timestamp) {
+        @SuppressWarnings("all")
+        ResponseMessage<T> msg = EntityFactoryHolder.newInstance(ResponseMessage.class, ResponseMessage::new);
+        msg.setMessage(message);
+        msg.setResult(result);
+        msg.setStatus(status);
+        msg.setCode(code);
+        msg.setTimestamp(timestamp);
         return msg;
     }
 

+ 2 - 1
hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/web/ResponseMessageWrapper.java

@@ -7,6 +7,7 @@ import org.springframework.core.ReactiveAdapterRegistry;
 import org.springframework.http.MediaType;
 import org.springframework.http.ResponseEntity;
 import org.springframework.http.codec.HttpMessageWriter;
+import org.springframework.lang.NonNull;
 import org.springframework.util.CollectionUtils;
 import org.springframework.util.MimeType;
 import org.springframework.web.bind.annotation.RequestMapping;
@@ -51,7 +52,7 @@ public class ResponseMessageWrapper extends ResponseBodyResultHandler {
     private Set<String> excludes = new HashSet<>();
 
     @Override
-    public boolean supports(HandlerResult result) {
+    public boolean supports(@NonNull HandlerResult result) {
 
         if (!CollectionUtils.isEmpty(excludes) && result.getHandler() instanceof HandlerMethod) {
             HandlerMethod method = (HandlerMethod) result.getHandler();

+ 14 - 6
hsweb-core/src/main/java/org/hswebframework/web/dict/EnumDict.java

@@ -16,6 +16,8 @@ import com.fasterxml.jackson.databind.DeserializationContext;
 import com.fasterxml.jackson.databind.JsonDeserializer;
 import com.fasterxml.jackson.databind.JsonNode;
 import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
+import lombok.AllArgsConstructor;
+import lombok.NoArgsConstructor;
 import lombok.SneakyThrows;
 import lombok.extern.slf4j.Slf4j;
 import org.hswebframework.web.exception.ValidationException;
@@ -25,6 +27,7 @@ import org.springframework.util.StringUtils;
 import java.io.IOException;
 import java.lang.reflect.Type;
 import java.util.*;
+import java.util.function.Function;
 import java.util.function.Predicate;
 import java.util.function.Supplier;
 import java.util.stream.Collectors;
@@ -123,11 +126,6 @@ public interface EnumDict<V> extends JSONSerializable {
         return getText();
     }
 
-    @JsonCreator
-    default EnumDict<V> fromJsonNode(Object val) {
-
-        return null;
-    }
 
 
     /**
@@ -294,7 +292,10 @@ public interface EnumDict<V> extends JSONSerializable {
      * 自定义fastJson枚举序列化
      */
     @Slf4j
+    @AllArgsConstructor
+    @NoArgsConstructor
     class EnumDictJSONDeserializer extends JsonDeserializer implements ObjectDeserializer {
+        private Function<Object,Object> mapper;
 
         @Override
         @SuppressWarnings("all")
@@ -346,7 +347,14 @@ public interface EnumDict<V> extends JSONSerializable {
         @SneakyThrows
         public Object deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException {
             JsonNode node = jp.getCodec().readTree(jp);
-
+            if(mapper!=null){
+                if(node.isTextual()){
+                    return mapper.apply(node.asText());
+                }
+                if(node.isNumber()){
+                    return mapper.apply(node.asLong());
+                }
+            }
             String currentName = jp.currentName();
             Object currentValue = jp.getCurrentValue();
             Class findPropertyType;

+ 32 - 4
hsweb-core/src/test/java/org/hswebframework/web/dict/EnumDictTest.java

@@ -1,14 +1,19 @@
 package org.hswebframework.web.dict;
 
-import com.fasterxml.jackson.databind.JsonDeserializer;
-import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.*;
+import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
+import com.fasterxml.jackson.databind.deser.std.EnumDeserializer;
+import com.fasterxml.jackson.databind.module.SimpleDeserializers;
 import com.fasterxml.jackson.databind.module.SimpleModule;
+import com.fasterxml.jackson.databind.type.ClassKey;
 import lombok.Getter;
 import lombok.Setter;
 import lombok.SneakyThrows;
 import org.junit.Assert;
 import org.junit.Test;
 
+import java.util.List;
+
 import static org.junit.Assert.*;
 
 public class EnumDictTest {
@@ -18,8 +23,22 @@ public class EnumDictTest {
     public void testJackson() {
         ObjectMapper mapper = new ObjectMapper();
         SimpleModule module = new SimpleModule();
-        JsonDeserializer<EnumDict> deserialize = new EnumDict.EnumDictJSONDeserializer();
-        module.addDeserializer(Enum.class, (JsonDeserializer) deserialize);
+        module.setDeserializers(new SimpleDeserializers() {
+            @Override
+            public JsonDeserializer<?> findEnumDeserializer(Class<?> type,
+                                                            DeserializationConfig config,
+                                                            BeanDescription beanDesc) throws JsonMappingException {
+                JsonDeserializer<?> deser = null;
+                if (type.isEnum()) {
+                    if (EnumDict.class.isAssignableFrom(type)) {
+                        deser = new EnumDict.EnumDictJSONDeserializer(val -> EnumDict
+                                .find((Class) type, val)
+                                .orElse(null));
+                    }
+                }
+                return deser;
+            }
+        });
         mapper.registerModule(module);
 
 
@@ -40,6 +59,11 @@ public class EnumDictTest {
 
         System.out.println((Object) mapper.readerFor(TestEnum.class).readValue("\"E1\""));
 
+        testEntity = mapper.readerFor(TestEntity.class)
+                           .readValue("{\"testEnums\":[\"E1\"]}");
+//        System.out.println(testEntity.getTestEnums());
+        Assert.assertArrayEquals(testEntity.getTestEnums(), new TestEnum[]{TestEnum.E1});
+
     }
 
     @Test
@@ -49,9 +73,11 @@ public class EnumDictTest {
 
         assertTrue(EnumDict.find(TestEnum.class, "e1")
                            .isPresent());
+
         assertTrue(EnumDict.find(TestEnum.class, "E1")
                            .isPresent());
 
+
     }
 
     @Getter
@@ -60,6 +86,8 @@ public class EnumDictTest {
         private TestEnum testEnum = TestEnum.E1;
 
         private SimpleEnum simpleEnum = SimpleEnum.A;
+
+        private TestEnum[] testEnums;
     }
 
     public enum SimpleEnum {

+ 0 - 1
hsweb-core/src/test/java/org/hswebframework/web/dict/TestEnum.java

@@ -1,7 +1,6 @@
 package org.hswebframework.web.dict;
 
 import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
-import com.fasterxml.jackson.databind.annotation.JsonSerialize;
 import lombok.AllArgsConstructor;
 import lombok.Getter;
 

+ 6 - 0
hsweb-starter/pom.xml

@@ -68,5 +68,11 @@
             <artifactId>r2dbc-h2</artifactId>
             <scope>test</scope>
         </dependency>
+        <dependency>
+            <groupId>com.google.code.findbugs</groupId>
+            <artifactId>jsr305</artifactId>
+            <version>3.0.2</version>
+            <scope>compile</scope>
+        </dependency>
     </dependencies>
 </project>

+ 38 - 24
hsweb-starter/src/main/java/org/hswebframework/web/starter/jackson/CustomCodecsAutoConfiguration.java

@@ -1,8 +1,10 @@
 package org.hswebframework.web.starter.jackson;
 
-import com.fasterxml.jackson.databind.JsonDeserializer;
-import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.*;
+import com.fasterxml.jackson.databind.deser.std.EnumDeserializer;
+import com.fasterxml.jackson.databind.module.SimpleDeserializers;
 import com.fasterxml.jackson.databind.module.SimpleModule;
+import com.fasterxml.jackson.databind.type.ClassKey;
 import org.hswebframework.web.api.crud.entity.EntityFactory;
 import org.hswebframework.web.dict.EnumDict;
 import org.springframework.boot.autoconfigure.AutoConfigureAfter;
@@ -19,28 +21,40 @@ import org.springframework.http.codec.CodecConfigurer;
 @AutoConfigureAfter(JacksonAutoConfiguration.class)
 public class CustomCodecsAutoConfiguration {
 
-	@Configuration(proxyBeanMethods = false)
-	@ConditionalOnClass(ObjectMapper.class)
-	static class JacksonDecoderConfiguration {
-
-		@Bean
-		@Order(1)
-		@ConditionalOnBean(ObjectMapper.class)
-		CodecCustomizer jacksonDecoderCustomizer(EntityFactory entityFactory, ObjectMapper objectMapper) {
-		//	objectMapper.setTypeFactory(new CustomTypeFactory(entityFactory));
-			SimpleModule module = new SimpleModule();
-			JsonDeserializer deserializer = new EnumDict.EnumDictJSONDeserializer();
-			module.addDeserializer(Enum.class,  deserializer);
-			objectMapper.registerModule(module);
-
-
-			return (configurer) -> {
-				CodecConfigurer.DefaultCodecs defaults = configurer.defaultCodecs();
-				defaults.jackson2JsonDecoder(new CustomJackson2JsonDecoder(objectMapper));
-			};
-		}
-
-	}
+    @Configuration(proxyBeanMethods = false)
+    @ConditionalOnClass(ObjectMapper.class)
+    static class JacksonDecoderConfiguration {
+
+        @Bean
+        @Order(1)
+        @ConditionalOnBean(ObjectMapper.class)
+        @SuppressWarnings("all")
+        CodecCustomizer jacksonDecoderCustomizer(EntityFactory entityFactory, ObjectMapper objectMapper) {
+            //	objectMapper.setTypeFactory(new CustomTypeFactory(entityFactory));
+            SimpleModule module = new SimpleModule();
+            module.setDeserializers(new SimpleDeserializers() {
+                @Override
+                public JsonDeserializer<?> findEnumDeserializer(Class<?> type,
+                                                                DeserializationConfig config,
+                                                                BeanDescription beanDesc) {
+                    JsonDeserializer<?> deser = null;
+                    if (type.isEnum() && EnumDict.class.isAssignableFrom(type)) {
+                        deser = new EnumDict.EnumDictJSONDeserializer(val -> EnumDict
+                                .find((Class) type, val)
+                                .orElse(null));
+                    }
+                    return deser;
+                }
+            });
+            objectMapper.registerModule(module);
+
+            return (configurer) -> {
+                CodecConfigurer.DefaultCodecs defaults = configurer.defaultCodecs();
+                defaults.jackson2JsonDecoder(new CustomJackson2JsonDecoder(entityFactory, objectMapper));
+            };
+        }
+
+    }
 
 
 }

+ 26 - 10
hsweb-starter/src/main/java/org/hswebframework/web/starter/jackson/CustomJackson2JsonDecoder.java

@@ -6,6 +6,7 @@ import com.fasterxml.jackson.databind.ObjectMapper;
 import com.fasterxml.jackson.databind.ObjectReader;
 import com.fasterxml.jackson.databind.exc.InvalidDefinitionException;
 import com.fasterxml.jackson.databind.util.TokenBuffer;
+import org.hswebframework.web.api.crud.entity.EntityFactory;
 import org.reactivestreams.Publisher;
 import org.springframework.core.MethodParameter;
 import org.springframework.core.ResolvableType;
@@ -19,12 +20,14 @@ import org.springframework.http.codec.HttpMessageDecoder;
 import org.springframework.http.codec.json.Jackson2CodecSupport;
 import org.springframework.http.server.reactive.ServerHttpRequest;
 import org.springframework.http.server.reactive.ServerHttpResponse;
+import org.springframework.lang.NonNull;
 import org.springframework.lang.Nullable;
 import org.springframework.util.Assert;
 import org.springframework.util.MimeType;
 import reactor.core.publisher.Flux;
 import reactor.core.publisher.Mono;
 
+import javax.annotation.Nonnull;
 import java.io.IOException;
 import java.lang.annotation.Annotation;
 import java.lang.reflect.Type;
@@ -33,11 +36,14 @@ import java.util.Map;
 
 public class CustomJackson2JsonDecoder extends Jackson2CodecSupport implements HttpMessageDecoder<Object> {
 
+    private final EntityFactory entityFactory;
+
     /**
      * Constructor with a Jackson {@link ObjectMapper} to use.
      */
-    public CustomJackson2JsonDecoder(ObjectMapper mapper, MimeType... mimeTypes) {
+    public CustomJackson2JsonDecoder(EntityFactory entityFactory, ObjectMapper mapper, MimeType... mimeTypes) {
         super(mapper, mimeTypes);
+        this.entityFactory = entityFactory;
     }
 
 
@@ -51,7 +57,8 @@ public class CustomJackson2JsonDecoder extends Jackson2CodecSupport implements H
     }
 
     @Override
-    public Flux<Object> decode(Publisher<DataBuffer> input, ResolvableType elementType,
+    @NonNull
+    public Flux<Object> decode(@NonNull Publisher<DataBuffer> input, @NonNull ResolvableType elementType,
                                @Nullable MimeType mimeType, @Nullable Map<String, Object> hints) {
 
         ObjectMapper mapper = getObjectMapper();
@@ -74,15 +81,17 @@ public class CustomJackson2JsonDecoder extends Jackson2CodecSupport implements H
     }
 
     @Override
-    public Mono<Object> decodeToMono(Publisher<DataBuffer> input, ResolvableType elementType,
+    @NonNull
+    public Mono<Object> decodeToMono(@NonNull Publisher<DataBuffer> input, @NonNull ResolvableType elementType,
                                      @Nullable MimeType mimeType, @Nullable Map<String, Object> hints) {
 
         return DataBufferUtils.join(input)
-                .map(dataBuffer -> decode(dataBuffer, elementType, mimeType, hints));
+                              .map(dataBuffer -> decode(dataBuffer, elementType, mimeType, hints));
     }
 
     @Override
-    public Object decode(DataBuffer dataBuffer, ResolvableType targetType,
+    @NonNull
+    public Object decode(@NonNull DataBuffer dataBuffer, @NonNull ResolvableType targetType,
                          @Nullable MimeType mimeType, @Nullable Map<String, Object> hints) throws DecodingException {
 
         try {
@@ -101,8 +110,13 @@ public class CustomJackson2JsonDecoder extends Jackson2CodecSupport implements H
         Assert.notNull(elementType, "'elementType' must not be null");
         MethodParameter param = getParameter(elementType);
         Class<?> contextClass = (param != null ? param.getContainingClass() : null);
-        Type type = elementType.resolve() == null ? elementType.getType() : elementType.resolve();
-
+        Type type = elementType.resolve() == null ? elementType.getType() : elementType.toClass();
+        if (type instanceof Class) {
+            Class<?> realType = entityFactory.getInstanceType(((Class<?>) type), false);
+            if (realType != null) {
+                type = realType;
+            }
+        }
         JavaType javaType = getJavaType(type, contextClass);
         Class<?> jsonView = (hints != null ? (Class<?>) hints.get(Jackson2CodecSupport.JSON_VIEW_HINT) : null);
         return jsonView != null ?
@@ -135,13 +149,15 @@ public class CustomJackson2JsonDecoder extends Jackson2CodecSupport implements H
     // HttpMessageDecoder...
 
     @Override
-    public Map<String, Object> getDecodeHints(ResolvableType actualType, ResolvableType elementType,
-                                              ServerHttpRequest request, ServerHttpResponse response) {
+    @NonNull
+    public Map<String, Object> getDecodeHints(@NonNull ResolvableType actualType, @NonNull ResolvableType elementType,
+                                              @NonNull ServerHttpRequest request, @NonNull ServerHttpResponse response) {
 
         return getHints(actualType);
     }
 
     @Override
+    @NonNull
     public List<MimeType> getDecodableMimeTypes() {
         return getMimeTypes();
     }
@@ -149,7 +165,7 @@ public class CustomJackson2JsonDecoder extends Jackson2CodecSupport implements H
     // Jackson2CodecSupport ...
 
     @Override
-    protected <A extends Annotation> A getAnnotation(MethodParameter parameter, Class<A> annotType) {
+    protected <A extends Annotation> A getAnnotation(MethodParameter parameter, @NonNull Class<A> annotType) {
         return parameter.getParameterAnnotation(annotType);
     }
 

+ 53 - 0
hsweb-starter/src/test/java/org/hswebframework/web/starter/jackson/CustomJackson2JsonDecoderTest.java

@@ -0,0 +1,53 @@
+package org.hswebframework.web.starter.jackson;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import lombok.SneakyThrows;
+import org.hswebframework.web.api.crud.entity.EntityFactory;
+import org.hswebframework.web.api.crud.entity.QueryParamEntity;
+import org.hswebframework.web.crud.entity.factory.MapperEntityFactory;
+import org.hswebframework.web.crud.web.reactive.ReactiveQueryController;
+import org.junit.Test;
+import org.springframework.core.MethodParameter;
+import org.springframework.core.ResolvableType;
+import org.springframework.core.io.buffer.DataBuffer;
+import org.springframework.core.io.buffer.DefaultDataBuffer;
+import org.springframework.core.io.buffer.DefaultDataBufferFactory;
+import org.springframework.http.MediaType;
+import org.springframework.util.MimeType;
+import reactor.core.publisher.Mono;
+
+import java.util.Collections;
+
+import static org.junit.Assert.*;
+
+public class CustomJackson2JsonDecoderTest {
+
+    @Test
+    @SneakyThrows
+    public void testDecodeCustomType() {
+
+        MapperEntityFactory entityFactory = new MapperEntityFactory();
+
+        entityFactory.addMapping(QueryParamEntity.class,MapperEntityFactory.defaultMapper(CustomQueryParamEntity.class));
+
+
+        ObjectMapper mapper = new ObjectMapper();
+        CustomJackson2JsonDecoder decoder = new CustomJackson2JsonDecoder(entityFactory, mapper);
+
+        ResolvableType type = ResolvableType.forMethodParameter(
+                ReactiveQueryController.class.getMethod("query", QueryParamEntity.class), 0
+        );
+
+        DataBuffer buffer = new DefaultDataBufferFactory().wrap("{}".getBytes());
+
+        Object object = decoder.decode(buffer, type, MediaType.APPLICATION_JSON, Collections.emptyMap());
+
+        assertTrue(object instanceof CustomQueryParamEntity);
+
+    }
+
+    public static class CustomQueryParamEntity extends QueryParamEntity {
+
+    }
+
+}