diff --git a/hsweb-authorization/hsweb-authorization-basic/src/main/java/org/hswebframework/web/authorization/basic/configuration/AopAuthorizeAutoConfiguration.java b/hsweb-authorization/hsweb-authorization-basic/src/main/java/org/hswebframework/web/authorization/basic/configuration/AopAuthorizeAutoConfiguration.java index b68f6fd29..a2b1d2902 100644 --- a/hsweb-authorization/hsweb-authorization-basic/src/main/java/org/hswebframework/web/authorization/basic/configuration/AopAuthorizeAutoConfiguration.java +++ b/hsweb-authorization/hsweb-authorization-basic/src/main/java/org/hswebframework/web/authorization/basic/configuration/AopAuthorizeAutoConfiguration.java @@ -4,21 +4,25 @@ import org.hswebframework.web.authorization.basic.aop.AopAuthorizingController; import org.hswebframework.web.authorization.basic.aop.AopMethodAuthorizeDefinitionParser; import org.hswebframework.web.authorization.basic.aop.DefaultAopMethodAuthorizeDefinitionParser; import org.hswebframework.web.authorization.basic.handler.AuthorizingHandler; +import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.boot.autoconfigure.AutoConfigureAfter; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Role; /** * @author zhouhao */ @Configuration(proxyBeanMethods = false) @AutoConfigureAfter(AuthorizingHandlerAutoConfiguration.class) +@Role(BeanDefinition.ROLE_INFRASTRUCTURE) public class AopAuthorizeAutoConfiguration { @Bean @ConditionalOnMissingBean(AopMethodAuthorizeDefinitionParser.class) + @Role(BeanDefinition.ROLE_INFRASTRUCTURE) public DefaultAopMethodAuthorizeDefinitionParser defaultAopMethodAuthorizeDefinitionParser() { return new DefaultAopMethodAuthorizeDefinitionParser(); } @@ -26,6 +30,7 @@ public class AopAuthorizeAutoConfiguration { @Bean @ConfigurationProperties(prefix = "hsweb.authorize") + @Role(BeanDefinition.ROLE_INFRASTRUCTURE) public AopAuthorizingController aopAuthorizingController(AuthorizingHandler authorizingHandler, AopMethodAuthorizeDefinitionParser aopMethodAuthorizeDefinitionParser) { diff --git a/hsweb-authorization/hsweb-authorization-basic/src/main/java/org/hswebframework/web/authorization/basic/configuration/AuthorizingHandlerAutoConfiguration.java b/hsweb-authorization/hsweb-authorization-basic/src/main/java/org/hswebframework/web/authorization/basic/configuration/AuthorizingHandlerAutoConfiguration.java index 1edd1f1fb..51f41ac46 100644 --- a/hsweb-authorization/hsweb-authorization-basic/src/main/java/org/hswebframework/web/authorization/basic/configuration/AuthorizingHandlerAutoConfiguration.java +++ b/hsweb-authorization/hsweb-authorization-basic/src/main/java/org/hswebframework/web/authorization/basic/configuration/AuthorizingHandlerAutoConfiguration.java @@ -11,6 +11,7 @@ import org.hswebframework.web.authorization.basic.handler.UserAllowPermissionHan import org.hswebframework.web.authorization.basic.web.*; import org.hswebframework.web.authorization.token.UserTokenManager; import org.springframework.beans.factory.ObjectProvider; +import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.boot.autoconfigure.AutoConfiguration; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; @@ -19,6 +20,7 @@ import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Role; /** * 权限控制自动配置类 @@ -28,10 +30,12 @@ import org.springframework.context.annotation.Configuration; */ @AutoConfiguration @EnableConfigurationProperties(EmbedAuthenticationProperties.class) +@Role(BeanDefinition.ROLE_INFRASTRUCTURE) public class AuthorizingHandlerAutoConfiguration { @Bean + @Role(BeanDefinition.ROLE_INFRASTRUCTURE) public DefaultAuthorizingHandler authorizingHandler() { return new DefaultAuthorizingHandler(null); } diff --git a/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/web/ResponseMessageWrapper.java b/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/web/ResponseMessageWrapper.java index 37e058d48..9610bc1a5 100644 --- a/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/web/ResponseMessageWrapper.java +++ b/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/web/ResponseMessageWrapper.java @@ -37,7 +37,7 @@ public class ResponseMessageWrapper extends ResponseBodyResultHandler { static { try { param = new MethodParameter(ResponseMessageWrapper.class - .getDeclaredMethod("methodForParams"), -1); + .getDeclaredMethod("methodForParams"), -1); } catch (NoSuchMethodException e) { e.printStackTrace(); } @@ -69,24 +69,24 @@ public class ResponseMessageWrapper extends ResponseBodyResultHandler { boolean isAlreadyResponse = gen == ResponseMessage.class || gen == ResponseEntity.class; boolean isStream = result.getReturnType().resolve() == Mono.class - || result.getReturnType().resolve() == Flux.class; + || result.getReturnType().resolve() == Flux.class; RequestMapping mapping = result.getReturnTypeSource() - .getMethodAnnotation(RequestMapping.class); + .getMethodAnnotation(RequestMapping.class); if (mapping == null) { return false; } for (String produce : mapping.produces()) { MimeType mimeType = MimeType.valueOf(produce); if (MediaType.TEXT_EVENT_STREAM.includes(mimeType) || - MediaType.APPLICATION_STREAM_JSON.includes(mimeType)) { + MediaType.APPLICATION_NDJSON.includes(mimeType)) { return false; } } return isStream - && super.supports(result) - && !isAlreadyResponse; + && super.supports(result) + && !isAlreadyResponse; } @Override @@ -94,24 +94,31 @@ public class ResponseMessageWrapper extends ResponseBodyResultHandler { public Mono handleResult(ServerWebExchange exchange, HandlerResult result) { Object body = result.getReturnValue(); - if (exchange - .getRequest() - .getHeaders() - .getAccept() - .contains(MediaType.TEXT_EVENT_STREAM)) { - return writeBody(body, param, exchange); + List accept = exchange.getRequest().getHeaders().getAccept(); + + if (accept.contains(MediaType.TEXT_EVENT_STREAM)|| + accept.contains(MediaType.APPLICATION_NDJSON)) { + return writeBody(body, result.getReturnTypeSource(), exchange); + } + + String ignoreWrapper = exchange + .getRequest() + .getHeaders() + .getFirst("X-Response-Wrapper"); + if ("Ignore".equals(ignoreWrapper)) { + return writeBody(body, result.getReturnTypeSource(), exchange); } if (body instanceof Mono) { body = ((Mono) body) - .map(ResponseMessage::ok) - .switchIfEmpty(Mono.just(ResponseMessage.ok())); + .map(ResponseMessage::ok) + .switchIfEmpty(Mono.just(ResponseMessage.ok())); } if (body instanceof Flux) { body = ((Flux) body) - .collectList() - .map(ResponseMessage::ok) - .switchIfEmpty(Mono.just(ResponseMessage.ok())); + .collectList() + .map(ResponseMessage::ok) + .switchIfEmpty(Mono.just(ResponseMessage.ok())); } if (body == null) { diff --git a/hsweb-datasource/hsweb-datasource-api/src/main/java/org/hswebframework/web/datasource/AopDataSourceSwitcherAutoConfiguration.java b/hsweb-datasource/hsweb-datasource-api/src/main/java/org/hswebframework/web/datasource/AopDataSourceSwitcherAutoConfiguration.java index 9e79de1b2..ad665fc91 100644 --- a/hsweb-datasource/hsweb-datasource-api/src/main/java/org/hswebframework/web/datasource/AopDataSourceSwitcherAutoConfiguration.java +++ b/hsweb-datasource/hsweb-datasource-api/src/main/java/org/hswebframework/web/datasource/AopDataSourceSwitcherAutoConfiguration.java @@ -9,9 +9,11 @@ import org.hswebframework.web.utils.ExpressionUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.aop.support.StaticMethodMatcherPointcutAdvisor; +import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Role; import org.springframework.util.ClassUtils; import org.springframework.util.StringUtils; import reactor.core.publisher.Flux; @@ -32,20 +34,24 @@ import static org.hswebframework.web.datasource.strategy.AnnotationDataSourceSwi * @since 3.0 */ @Configuration(proxyBeanMethods = false) +@Role(BeanDefinition.ROLE_INFRASTRUCTURE) public class AopDataSourceSwitcherAutoConfiguration { @Bean + @Role(BeanDefinition.ROLE_INFRASTRUCTURE) @ConfigurationProperties(prefix = "hsweb.datasource") public ExpressionDataSourceSwitchStrategyMatcher expressionDataSourceSwitchStrategyMatcher() { return new ExpressionDataSourceSwitchStrategyMatcher(); } @Bean + @Role(BeanDefinition.ROLE_INFRASTRUCTURE) public AnnotationDataSourceSwitchStrategyMatcher annotationDataSourceSwitchStrategyMatcher() { return new AnnotationDataSourceSwitchStrategyMatcher(); } @Bean + @Role(BeanDefinition.ROLE_INFRASTRUCTURE) public TableSwitchStrategyMatcher alwaysNoMatchStrategyMatcher() { return new TableSwitchStrategyMatcher() { @Override @@ -61,6 +67,7 @@ public class AopDataSourceSwitcherAutoConfiguration { } @Bean + @Role(BeanDefinition.ROLE_INFRASTRUCTURE) public SwitcherMethodMatcherPointcutAdvisor switcherMethodMatcherPointcutAdvisor( List matchers, List tableSwitcher) { diff --git a/hsweb-logging/hsweb-access-logging-aop/src/main/java/org/hswebframework/web/logging/aop/AopAccessLoggerSupportAutoConfiguration.java b/hsweb-logging/hsweb-access-logging-aop/src/main/java/org/hswebframework/web/logging/aop/AopAccessLoggerSupportAutoConfiguration.java index 4ab23eff2..ef9b5ac58 100644 --- a/hsweb-logging/hsweb-access-logging-aop/src/main/java/org/hswebframework/web/logging/aop/AopAccessLoggerSupportAutoConfiguration.java +++ b/hsweb-logging/hsweb-access-logging-aop/src/main/java/org/hswebframework/web/logging/aop/AopAccessLoggerSupportAutoConfiguration.java @@ -2,10 +2,12 @@ package org.hswebframework.web.logging.aop; import org.hswebframework.web.logging.AccessLoggerListener; +import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Role; import org.springframework.core.annotation.Order; /** @@ -17,21 +19,25 @@ import org.springframework.core.annotation.Order; */ @ConditionalOnClass(AccessLoggerListener.class) @Configuration(proxyBeanMethods = false) +@Role(BeanDefinition.ROLE_INFRASTRUCTURE) public class AopAccessLoggerSupportAutoConfiguration { @Bean @ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET) + @Role(BeanDefinition.ROLE_INFRASTRUCTURE) public AopAccessLoggerSupport aopAccessLoggerSupport() { return new AopAccessLoggerSupport(); } @Bean @ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.REACTIVE) + @Role(BeanDefinition.ROLE_INFRASTRUCTURE) public ReactiveAopAccessLoggerSupport reactiveAopAccessLoggerSupport() { return new ReactiveAopAccessLoggerSupport(); } @Bean + @Role(BeanDefinition.ROLE_INFRASTRUCTURE) public DefaultAccessLoggerParser defaultAccessLoggerParser() { return new DefaultAccessLoggerParser(); } @@ -39,6 +45,7 @@ public class AopAccessLoggerSupportAutoConfiguration { @Bean @ConditionalOnClass(name = "io.swagger.annotations.Api") @Order(10) + @Role(BeanDefinition.ROLE_INFRASTRUCTURE) public SwaggerAccessLoggerParser swaggerAccessLoggerParser() { return new SwaggerAccessLoggerParser(); } @@ -46,6 +53,7 @@ public class AopAccessLoggerSupportAutoConfiguration { @Bean @ConditionalOnClass(name = "io.swagger.v3.oas.annotations.tags.Tag") @Order(1) + @Role(BeanDefinition.ROLE_INFRASTRUCTURE) public Swagger3AccessLoggerParser swagger3AccessLoggerParser() { return new Swagger3AccessLoggerParser(); } @@ -53,6 +61,7 @@ public class AopAccessLoggerSupportAutoConfiguration { @Bean @ConditionalOnClass(name = "org.hswebframework.web.authorization.annotation.Resource") @Order(999) + @Role(BeanDefinition.ROLE_INFRASTRUCTURE) public ResourceAccessLoggerParser resourceAccessLoggerParser() { return new ResourceAccessLoggerParser(); } diff --git a/hsweb-starter/pom.xml b/hsweb-starter/pom.xml index 9b18b8952..291db9f79 100644 --- a/hsweb-starter/pom.xml +++ b/hsweb-starter/pom.xml @@ -76,8 +76,12 @@ 5.0.0 test + + org.springframework + spring-web + - + diff --git a/hsweb-starter/src/main/java/org/hswebframework/web/starter/jackson/CustomCodecsAutoConfiguration.java b/hsweb-starter/src/main/java/org/hswebframework/web/starter/jackson/CustomCodecsAutoConfiguration.java index 137c9de76..27b314f44 100644 --- a/hsweb-starter/src/main/java/org/hswebframework/web/starter/jackson/CustomCodecsAutoConfiguration.java +++ b/hsweb-starter/src/main/java/org/hswebframework/web/starter/jackson/CustomCodecsAutoConfiguration.java @@ -1,6 +1,8 @@ package org.hswebframework.web.starter.jackson; -import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.module.SimpleModule; import org.hswebframework.web.api.crud.entity.EntityFactory; import org.springframework.boot.autoconfigure.AutoConfiguration; @@ -10,8 +12,12 @@ import org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration; import org.springframework.boot.web.codec.CodecCustomizer; import org.springframework.context.annotation.Bean; import org.springframework.core.annotation.Order; +import org.springframework.http.HttpMethod; +import org.springframework.http.HttpStatus; import org.springframework.http.codec.CodecConfigurer; +import java.io.IOException; + @AutoConfiguration(after = JacksonAutoConfiguration.class) public class CustomCodecsAutoConfiguration { @@ -19,6 +25,36 @@ public class CustomCodecsAutoConfiguration { @ConditionalOnClass(ObjectMapper.class) static class JacksonDecoderConfiguration { + @Bean + SimpleModule springWebModule() { + //兼容spring web相关序列化 + SimpleModule module = new SimpleModule(); + module.addSerializer(HttpMethod.class, new JsonSerializer<>() { + @Override + public void serialize(HttpMethod httpMethod, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException { + jsonGenerator.writeString(httpMethod.name()); + } + }); + module.addDeserializer(HttpMethod.class, new JsonDeserializer<>() { + @Override + public HttpMethod deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException { + return HttpMethod.valueOf(jsonParser.getValueAsString()); + } + }); + module.addSerializer(HttpStatus.class, new JsonSerializer<>() { + @Override + public void serialize(HttpStatus httpStatus, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException { + jsonGenerator.writeNumber(httpStatus.value()); + } + }); + module.addDeserializer(HttpStatus.class, new JsonDeserializer<>() { + @Override + public HttpStatus deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException { + return HttpStatus.valueOf(jsonParser.getValueAsInt()); + } + }); + return module; + } @Bean SimpleModule entityAndEnumDictModule(EntityFactory entityFactory) { diff --git a/hsweb-starter/src/main/java/org/hswebframework/web/starter/jackson/CustomJackson2jsonEncoder.java b/hsweb-starter/src/main/java/org/hswebframework/web/starter/jackson/CustomJackson2jsonEncoder.java index 27c42a42d..ccb021275 100644 --- a/hsweb-starter/src/main/java/org/hswebframework/web/starter/jackson/CustomJackson2jsonEncoder.java +++ b/hsweb-starter/src/main/java/org/hswebframework/web/starter/jackson/CustomJackson2jsonEncoder.java @@ -56,7 +56,7 @@ public class CustomJackson2jsonEncoder extends Jackson2CodecSupport implements H static { STREAM_SEPARATORS = new HashMap<>(4); - STREAM_SEPARATORS.put(MediaType.APPLICATION_STREAM_JSON, NEWLINE_SEPARATOR); + STREAM_SEPARATORS.put(MediaType.APPLICATION_NDJSON, NEWLINE_SEPARATOR); STREAM_SEPARATORS.put(MediaType.parseMediaType("application/stream+x-jackson-smile"), new byte[0]); ENCODINGS = new HashMap<>(JsonEncoding.values().length + 1); @@ -75,6 +75,7 @@ public class CustomJackson2jsonEncoder extends Jackson2CodecSupport implements H */ protected CustomJackson2jsonEncoder(ObjectMapper mapper, MimeType... mimeTypes) { super(mapper, mimeTypes); + setStreamingMediaTypes(Collections.singletonList(MediaType.APPLICATION_NDJSON)); }