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);
}
}
}
}
网友评论