美文网首页
尝鲜Spring Cloud 2020.0.0

尝鲜Spring Cloud 2020.0.0

作者: EasyNetCN | 来源:发表于2020-12-23 15:04 被阅读0次

    基于Spring Boot 2.4.1的Spring Cloud 2020.0.0(https://spring.io/blog/2020/12/22/spring-cloud-2020-0-0-aka-ilford-is-available)发布了,今天差不多花了6个多小时找了一个项目进行升级改造,终于跑了起来,进行了以下修改(仅供参考)

    pom.xml

    <?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></groupId>
        <artifactId></artifactId>
        <version></version>
    
        <name>operation platform</name>
    
        <properties>
            <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
            <java.version>15</java.version>
            <hikaricp.version>3.4.5</hikaricp.version>
            <mysql.version>8.0.21</mysql.version>
            <guava.version>30.1-jre</guava.version>
            <poi.version>4.1.2</poi.version>
            <logstash-logback-encoder.version>6.5</logstash-logback-encoder.version>
            <jib-maven-plugin.version>2.7.0</jib-maven-plugin.version>
        </properties>
    
        <parent>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-parent</artifactId>
            <version>2.4.1</version>
        </parent>
    
        <repositories>
            <repository>
                <id>aliyun</id>
                <url>http://maven.aliyun.com/nexus/content/groups/public/</url>
            </repository>
        </repositories>
        <pluginRepositories>
            <pluginRepository>
                <id>aliyun</id>
                <url>http://maven.aliyun.com/nexus/content/groups/public</url>
            </pluginRepository>
        </pluginRepositories>
    
        <dependencyManagement>
            <dependencies>
                <dependency>
                    <groupId>org.springframework.cloud</groupId>
                    <artifactId>spring-cloud-dependencies</artifactId>
                    <version>2020.0.0</version>
                    <type>pom</type>
                    <scope>import</scope>
                </dependency>
            </dependencies>
        </dependencyManagement>
    
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-consul-all</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-openfeign</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-stream-kafka</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-webflux</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-thymeleaf</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-cache</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-data-redis</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-jdbc</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-security</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-actuator</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.session</groupId>
                <artifactId>spring-session-data-redis</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-devtools</artifactId>
                <optional>true</optional>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-test</artifactId>
                <scope>test</scope>
            </dependency>
            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
            </dependency>
            <dependency>
                <groupId>org.apache.commons</groupId>
                <artifactId>commons-lang3</artifactId>
            </dependency>
            <dependency>
                <groupId>com.google.guava</groupId>
                <artifactId>guava</artifactId>
                <version>${guava.version}</version>
            </dependency>
            <dependency>
                <groupId>io.github.openfeign</groupId>
                <artifactId>feign-okhttp</artifactId>
            </dependency>
            <dependency>
                <groupId>net.logstash.logback</groupId>
                <artifactId>logstash-logback-encoder</artifactId>
                <version>${logstash-logback-encoder.version}</version>
            </dependency>
            <dependency>
                <groupId>com.belerweb</groupId>
                <artifactId>pinyin4j</artifactId>
                <version>2.5.1</version>
            </dependency>
            <dependency>
                <groupId>org.apache.poi</groupId>
                <artifactId>poi-ooxml-schemas</artifactId>
                <version>${poi.version}</version>
            </dependency>
            <dependency>
                <groupId>org.apache.poi</groupId>
                <artifactId>poi-ooxml</artifactId>
                <version>${poi.version}</version>
            </dependency>
            <dependency>
                <groupId>org.apache.poi</groupId>
                <artifactId>poi</artifactId>
                <version>${poi.version}</version>
            </dependency>
        </dependencies>
        <build>
            <plugins>
                <plugin>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-maven-plugin</artifactId>
                    <configuration>
                        <executable>true</executable>
                    </configuration>
                </plugin>
                <plugin>
                    <groupId>com.google.cloud.tools</groupId>
                    <artifactId>jib-maven-plugin</artifactId>
                    <version>${jib-maven-plugin.version}</version>
                    <configuration>
                        <from>
                            <image>adoptopenjdk:15.0.1_9-jre-hotspot</image>
                        </from>
                        <to>
                            <image>${project.artifactId}:${project.version}</image>
                        </to>
                        <container>
                            <creationTime>USE_CURRENT_TIMESTAMP</creationTime>
                            <environment>
                                <TZ>Asia/Shanghai</TZ>
                            </environment>
                        </container>
                    </configuration>
                </plugin>
            </plugins>
        </build>
    </project>
    
    

    bootstrap.yml修改为application.yml,其中配置结构有了较大的变化

    spring:
      application:
        name: operation-platform
      config:
        import:
        - consul:${consul.host}:${consul.port:8500}
      profiles:
        include:
        - common
    ---
    spring: 
      config:
        activate:
          on-profile:
          - common
      codec:
        max-in-memory-size:
          -1
      cloud:
        consul:
          discovery:
            prefer-ip-address: true
            health-check-critical-timeout: 30s
          config:
            enabled: true
            prefix: ydyun360-config
            format: yaml
            default-context: ${spring.application.name}
        loadbalancer:
          ribbon:
            enabled: true
        stream:
          kafka:
            binder:
              brokers: ${kafka.brokers:localhost:9092}
              auto-add-partitions: false
              auto-create-topics: false
          bindings:
            log-service-topic-output: # 消息订阅通道
              destination: log-service-topic  # topic
              contentType: application/json
              producer:
                partition-key-expression:  headers['partitionKey']
                partition-count: 2
          default-binder: kafka
      cache:
        redis:
          key-prefix: ${spring.application.name}
          time-to-live: 0
      jackson:
        date-format: yyyy-MM-dd HH:mm:ss
        time-zone:
          Asia/Shanghai
      kafka:
        bootstrap-servers: ${spring.cloud.stream.kafka.binder.brokers}
      session:
        timeout: 30d
        redis:
          namespace: ${spring.application.name}
      jpa:
        show-sql: false
      datasource:
        type: com.zaxxer.hikari.HikariDataSource
        hikari:
          data-source-properties:
            cachePrepStmts: true
            prepStmtCacheSize: 500
            prepStmtCacheSqlLimit: 2048
            useServerPrepStmts: true
            rewriteBatchedStatements: true
            cacheResultSetMetadata: true
            cacheServerConfiguration: true
            elideSetAutoCommits: true
            maintainTimeStats: false
    feign:
      httpclient:
        enabled: false
      okhttp:
        enabled: true
      client:
        config:
          default:
            read-timeout: 3600000
    ribbon:
      eager-load:
        enabled: true
        clients: file-service,goods-service,user-service
      ConnectTimeout: 10000
      ReadTimeout: 3600000
    
    logging:
      level:
        root: INFO
      file: 
        name: logs/${spring.application.name}.log
    
    server:
      http2:
        enabled: true
      compression:
        enabled: true
        mime-types: application/json,application/xml,text/html,text/javascript,text/css,text/xml,text/plain
        min-response-size: 2048
      port: 9003
    
    ---
    spring: 
      config:
        activate:
          on-profile:
          - development-local
    
    ---
    spring:
      config:
        activate:
          on-profile:
          - development-test
      cloud:
        consul:
          host: ${consul.host:}
          port: ${consul.port:}
      
    ---
    spring:
      config:
        activate:
          on-profile:
          - development-rc
      cloud:
        consul:
          host: ${consul.host:}
          port: ${consul.port:}
    
    ---
    spring:
      config:
        activate:
          on-profile:
          -  testing
    
    ---
    spring:
      config:
        activate:
          on-profile:
          - release
    
    ---
    spring:
      config:
        activate:
          on-profile:
          - production
    

    启动时候可以设置当前激活的profile

    --spring.profiles.active=development-test --consul.host= --consul.port=
    

    全局异常处理修改

    import java.io.IOException;
    import java.io.PrintWriter;
    import java.io.StringWriter;
    import java.time.LocalDateTime;
    import java.util.HashMap;
    
    import org.apache.commons.lang3.StringUtils;
    import org.apache.commons.logging.Log;
    import org.apache.commons.logging.LogFactory;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.boot.autoconfigure.web.ErrorProperties;
    import org.springframework.boot.autoconfigure.web.WebProperties.Resources;
    import org.springframework.boot.autoconfigure.web.reactive.error.DefaultErrorWebExceptionHandler;
    import org.springframework.boot.web.error.ErrorAttributeOptions;
    import org.springframework.boot.web.error.ErrorAttributeOptions.Include;
    import org.springframework.boot.web.reactive.error.ErrorAttributes;
    import org.springframework.cloud.consul.serviceregistry.ConsulRegistration;
    import org.springframework.context.ApplicationContext;
    import org.springframework.core.annotation.Order;
    import org.springframework.http.HttpStatus;
    import org.springframework.http.MediaType;
    import org.springframework.http.codec.ServerCodecConfigurer;
    import org.springframework.messaging.MessageHeaders;
    import org.springframework.messaging.support.MessageBuilder;
    import org.springframework.stereotype.Component;
    import org.springframework.util.MimeTypeUtils;
    import org.springframework.web.reactive.function.BodyInserters;
    import org.springframework.web.reactive.function.server.RequestPredicates;
    import org.springframework.web.reactive.function.server.RouterFunction;
    import org.springframework.web.reactive.function.server.RouterFunctions;
    import org.springframework.web.reactive.function.server.ServerRequest;
    import org.springframework.web.reactive.function.server.ServerResponse;
    
    import com.fasterxml.jackson.databind.ObjectMapper;
    
    import reactor.core.publisher.Mono;
    
    @Component
    @Order(-2)
    public class GlobalDefaultExceptionHandler extends DefaultErrorWebExceptionHandler {
        private static final Log logger = LogFactory.getLog(GlobalDefaultExceptionHandler.class);
    
        @Value("${spring.application.name}")
        private String applicationName;
    
        @Value("${spring.profiles.active}")
        private String profile;
    
        @Autowired
        private ConsulRegistration consulRegistration;
    
        @Autowired
        private ObjectMapper objectMapper;
    
        @Autowired
        private LogStreams logStreams;
    
        public GlobalDefaultExceptionHandler(ErrorAttributes errorAttributes, ApplicationContext applicationContext,
                ServerCodecConfigurer serverCodecConfigurer) {
            super(errorAttributes, new Resources(), new ErrorProperties(), applicationContext);
            super.setMessageWriters(serverCodecConfigurer.getWriters());
            super.setMessageReaders(serverCodecConfigurer.getReaders());
        }
    
        @Override
        protected RouterFunction<ServerResponse> getRoutingFunction(ErrorAttributes errorAttributes) {
            return RouterFunctions.route(RequestPredicates.all(), this::renderErrorResponse);
        }
    
        @Override
        protected Mono<ServerResponse> renderErrorResponse(ServerRequest request) {
            var errorPropertiesMap = getErrorAttributes(request, ErrorAttributeOptions.of(Include.EXCEPTION,
                    Include.STACK_TRACE, Include.MESSAGE, Include.BINDING_ERRORS));
            var status = (int) errorPropertiesMap.get("status");
            var exception = this.getError(request);
            var code = "";
            var message = "";
            var trace = "";
    
            if (exception instanceof BusinessException) {
                var businessException = (BusinessException) exception;
    
                status = businessException.getStatus();
                code = businessException.getCode();
                message = exception.getMessage();
            } else {
                code = String.valueOf(status);
                try (var stringWriter = new StringWriter(); var printWriter = new PrintWriter(stringWriter)) {
                    exception.printStackTrace(printWriter);
                    trace = stringWriter.getBuffer().toString();
                } catch (IOException ex) {
                    logger.error(ex);
                }
    
                if (status == 400) {
                    message = "参数错误";
                } else if (status == 401) {
                    message = "无权访问";
                } else if (status == 404) {
                    message = "未找到";
                } else if (status == 500) {
                    message = "服务内部错误";
                }
            }
    
            var serviceErrorLog = new ServiceErrorLog();
    
            serviceErrorLog.setApplicationName(applicationName);
            serviceErrorLog.setServerIp(consulRegistration.getHost());
            serviceErrorLog.setPath(StringUtils.isNotBlank(request.path()) ? request.path() : "");
    
            if (!request.queryParams().isEmpty()) {
                try {
                    serviceErrorLog.setQueryParams(objectMapper.writeValueAsString(request.queryParams()));
                } catch (IOException ex) {
                    logger.error(ex);
                }
            }
    
            if (StringUtils.isBlank(serviceErrorLog.getQueryParams())) {
                serviceErrorLog.setQueryParams("");
            }
    
            serviceErrorLog.setMessage(message);
            serviceErrorLog.setTrace(trace);
            serviceErrorLog.setLogTime(LocalDateTime.now());
    
            if (status != 404) {
                sendError(serviceErrorLog);
            }
    
            var errorMap = new HashMap<String, Object>();
    
            errorMap.put("code", code);
            errorMap.put("message", message);
            errorMap.put("trace", trace);
    
            return ServerResponse.status(HttpStatus.valueOf(status)).contentType(MediaType.APPLICATION_JSON)
                    .body(BodyInserters.fromValue(errorMap));
        }
    
        private void sendError(ServiceErrorLog serviceErrorLog) {
            if (!profile.endsWith("-local")) {
                try {
                    var messageChannel = logStreams.outboundLogStreams();
    
                    messageChannel.send(MessageBuilder.withPayload(serviceErrorLog)
                            .setHeader(MessageHeaders.CONTENT_TYPE, MimeTypeUtils.APPLICATION_JSON)
                            .setHeader("partitionKey", "service-error-logs").build());
                } catch (Exception ex) {
                    logger.error(ex);
                }
            }
        }
    }
    

    相关文章

      网友评论

          本文标题:尝鲜Spring Cloud 2020.0.0

          本文链接:https://www.haomeiwen.com/subject/kxaynktx.html