[新增功能](master): 日志和devops环境配置

增加log4j2的相关配置

增加devops基础环境的配置
master
土豆兄弟 3 years ago
parent bb1f6b672a
commit d72f2ce8b4

@ -11,6 +11,10 @@
- 参考: https://mp.weixin.qq.com/s/W5v8zOCHbc2_NvobMGaU8w
dev-protocol-log
- 分布式日志系统的设计及实现,主要涉及kafka Springboot ELK
dev-protocol-gateway
- 智能网关设计
dev-protocol-devops
- DevOps 相关的最佳实现
### 1.1 基本命令(dev-protocol-log)
- Kafka
@ -74,8 +78,27 @@
- 3.
### 3.1 智能网关
#### JWT 在微服务架构下的认证过程
- A> 服务器自主验签方式
![avatar](dev-protocol-gateway/pic/服务器自主验签方式.png)
- 第一步,认证中心微服务负责用户认证任务,在启动时从 Nacos 配置中心抽取 JWT 加密用私钥
- 第二步,用户在登录页输入用户名密码,客户端向认证中心服务发起认证请求
- 第三步认证中心服务根据输入在用户数据库中进行认证校验如果校验成功则返回认证中心将生成用户的JSON数据并创建对应的 JWT 返回给客户端
- 第四步,在收到 JSON 数据后,客户端将其中 token 数据保存在 cookie 或者本地缓存中
- 第五步,随后客户端向具体某个微服务发起新地请求,这个 JWT 都会附加在请求头或者 cookie 中发往 API 网关网关根据路由规则将请求与jwt数据转发至具体的微服务。中间过程网关不对 JWT 做任何处理
- 第六步,微服务接收到请求后,发现请求附带 JWT 数据,于是将 JWT 再次转发给用户认证服务,此时用户认证服务对 JWT 进行验签,验签成功提取其中用户编号,查询用户认证与授权的详细数据
- 第七步,具体的微服务收到上述 JSON 后,对当前执行的操作进行判断,检查是否拥有执行权限,权限检查通过执行业务代码,权限检查失败返回错误响应
- B> API 网关统一验签方案
![avatar](dev-protocol-gateway/pic/API网关统一验签方案.png)
API 网关统一验签与服务端验签最大的区别是在 API 网关层面就发起 JWT 的验签请求,之后路由过程中附加的是从认证中心返回的用户与权限数据,其他的操作步骤与方案一是完全相同的
## TODO-List
1. 使用 切面+注解 的方式对同一类的请求带上相对应的验证信息
2. 注意在调用请求的时候要对内部鉴权方式和外部鉴权方式进行区分,然后知道在使用JWT方案的时候要进行JWT防止伪造鉴定
3. Nginx相关的配置

@ -0,0 +1,93 @@
<?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">
<parent>
<artifactId>dev-protocol</artifactId>
<groupId>org.example</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>dev-protocol-devops</artifactId>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</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-web</artifactId>
</dependency>
<!-- 如果是2.3.1或者以上,需要添加注解依赖的包。-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
<!-- <dependency>-->
<!-- <groupId>org.springframework.cloud</groupId>-->
<!-- <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>-->
<!-- </dependency>-->
<!-- <dependency>-->
<!-- <groupId>org.springframework.cloud</groupId>-->
<!-- <artifactId>spring-cloud-starter-config</artifactId>-->
<!-- </dependency>-->
<!--启用链路追踪服务-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-zipkin</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/org.seleniumhq.selenium/selenium-java -->
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-java</artifactId>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>

@ -0,0 +1,17 @@
package com.baiye;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
/**
*
*
* @author q
* @date 2021/11/26
*/
@SpringBootApplication
public class DevProtocolDevOpsApplication {
public static void main(String[] args) {
SpringApplication.run(DevProtocolDevOpsApplication.class, args);
}
}

@ -0,0 +1,77 @@
package com.baiye.controller;
import com.baiye.entity.Notebook;
import com.baiye.repository.NotebookRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import javax.validation.Valid;
@Controller
@RequestMapping("/")
public class NotebookController {
private final NotebookRepository notebookRepository;
@Autowired
public NotebookController(NotebookRepository notebookRepository) {
this.notebookRepository = notebookRepository;
}
@GetMapping("signup")
public String showSignUpForm(Notebook notebook) {
return "add-notebook";
}
@GetMapping("list")
public String showUpdateForm(Model model) {
model.addAttribute("notebooks", notebookRepository.findAll());
return "index";
}
@PostMapping("add")
public String addNote(@Valid Notebook notebook, BindingResult result, Model model) {
if (result.hasErrors()) {
return "add-notebook";
}
notebookRepository.save(notebook);
return "redirect:list";
}
@GetMapping("edit/{id}")
public String showUpdateForm(@PathVariable("id") long id, Model model) {
Notebook notebook = notebookRepository.findById(id)
.orElseThrow(() -> new IllegalArgumentException("Invalid notebook Id:" + id));
model.addAttribute("notebook", notebook);
return "update-notebook";
}
@PostMapping("update/{id}")
public String updateNote(@PathVariable("id") long id, @Valid Notebook notebook, BindingResult result,
Model model) {
if (result.hasErrors()) {
notebook.setId(id);
return "update-notebook";
}
notebookRepository.save(notebook);
model.addAttribute("notebooks", notebookRepository.findAll());
return "index";
}
@GetMapping("delete/{id}")
public String deleteNote(@PathVariable("id") long id, Model model) {
Notebook notebook = notebookRepository.findById(id)
.orElseThrow(() -> new IllegalArgumentException("Invalid notebook Id:" + id));
notebookRepository.delete(notebook);
model.addAttribute("notebooks", notebookRepository.findAll());
return "index";
}
}

@ -0,0 +1,67 @@
package com.baiye.entity;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.validation.constraints.NotBlank;
@Entity
public class Notebook {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private long id;
@NotBlank(message = "Name is mandatory")
@Column(name = "name")
private String name;
@NotBlank(message = "Email is mandatory")
@Column(name = "email")
private String email;
@Column(name = "phone_no")
private long phoneNo;
public Notebook() {}
public Notebook(String name, String email) {
this.name = name;
this.email = email;
}
public void setId(long id) {
this.id = id;
}
public long getId() {
return id;
}
public void setName(String name) {
this.name = name;
}
public void setEmail(String email) {
this.email = email;
}
public String getName() {
return name;
}
public String getEmail() {
return email;
}
public long getPhoneNo() {
return phoneNo;
}
public void setPhoneNo(long phoneNo) {
this.phoneNo = phoneNo;
}
}

@ -0,0 +1,16 @@
package com.baiye.repository;
import com.baiye.entity.Notebook;
import org.springframework.data.repository.CrudRepository;
import org.springframework.stereotype.Repository;
import java.util.List;
@Repository
public interface NotebookRepository extends CrudRepository<Notebook, Long> {
List<Notebook> findByName(String name);
}

@ -0,0 +1,8 @@
server:
port: 8081
spring:
application:
name: dev-protocol-devops

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

@ -0,0 +1,63 @@
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="utf-8">
<meta http-equiv="x-ua-compatible" content="ie=edge">
<title>Add User</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet"
href="/css/bootstrap.min.css"
integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO"
crossorigin="anonymous">
<link rel="stylesheet"
href="/css/all.css"
integrity="sha384-5sAR7xN1Nv6T6+dT2mhtzEpVJvfS3NScPQTrOxhwjIuvcA67KV2R5Jz6kr4abQsz"
crossorigin="anonymous">
<!-- <link rel="stylesheet" href="../css/shards.min.css"> -->
</head>
<body>
<div class="container my-5">
<h3> Add notebook</h3>
<div class="card">
<div class="card-body">
<div class="col-md-10">
<form action="#" th:action="@{/add}"
th:object="${notebook}" method="post">
<div class="row">
<div class="form-group col-md-8">
<label for="name" class="col-form-label">Name</label> <input
type="text" th:field="*{name}" class="form-control" id="name"
placeholder="Name"> <span
th:if="${#fields.hasErrors('name')}" th:errors="*{name}"
class="text-danger"></span>
</div>
<div class="form-group col-md-8">
<label for="email" class="col-form-label">Email</label> <input
type="text" th:field="*{email}" class="form-control" id="email"
placeholder="Email"> <span
th:if="${#fields.hasErrors('email')}" th:errors="*{email}"
class="text-danger"></span>
</div>
<div class="form-group col-md-8">
<label for="phoneNo" class="col-form-label">Phone No</label> <input
type="text" th:field="*{phoneNo}" class="form-control"
id="phoneNo" placeholder="PhoneNo"> <span
th:if="${#fields.hasErrors('phoneNo')}" th:errors="*{phoneNo}"
class="text-danger"></span>
</div>
<div class="col-md-6">
<input type="submit" id="addNoteBtn" class="btn btn-primary" value="Add Note">
</div>
<div class="form-group col-md-8"></div>
</div>
</form>
</div>
</div>
</div>
</div>
</body>
</html>

@ -0,0 +1,61 @@
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="utf-8">
<meta http-equiv="x-ua-compatible" content="ie=edge">
<title>Users</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet"
href="/css/bootstrap.min.css"
integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO"
crossorigin="anonymous">
<link rel="stylesheet"
href="/css/all.css"
integrity="sha384-5sAR7xN1Nv6T6+dT2mhtzEpVJvfS3NScPQTrOxhwjIuvcA67KV2R5Jz6kr4abQsz"
crossorigin="anonymous">
<!-- <link rel="stylesheet" href="../css/shards.min.css"> -->
</head>
<body>
<div class="container my-2">
<div class="card">
<div class="card-body">
<div th:switch="${notebooks}" class="container my-5">
<p class="my-5">
<a href="/signup" id="signup" class="btn btn-primary"><i
class="fas fa-user-plus ml-2"> Add notebook</i></a>
</p>
<div class="col-md-10">
<h2 th:case="null">No notebook yet!</h2>
<div th:case="*">
<table class="table table-striped table-responsive-md">
<thead>
<tr>
<th>Name</th>
<th>Email</th>
<th>Phone No</th>
<th>Edit</th>
<th>Delete</th>
</tr>
</thead>
<tbody>
<tr th:each="notebook : ${notebooks}">
<td th:text="${notebook.name}"></td>
<td th:text="${notebook.email}"></td>
<td th:text="${notebook.phoneNo}"></td>
<td><a th:href="@{/edit/{id}(id=${notebook.id})}"
class="btn btn-primary"><i class="fas fa-user-edit ml-2"></i></a></td>
<td><a
th:href="@{/delete/{id}(id=${notebook.id})}"
class="btn btn-primary"><i class="fas fa-user-times ml-2"></i></a></td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
</div>
</body>
</html>

@ -0,0 +1,60 @@
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="utf-8">
<meta http-equiv="x-ua-compatible" content="ie=edge">
<title>Update User</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet"
href="/css/bootstrap.min.css"
integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO"
crossorigin="anonymous">
<link rel="stylesheet"
href="/css/all.css"
integrity="sha384-5sAR7xN1Nv6T6+dT2mhtzEpVJvfS3NScPQTrOxhwjIuvcA67KV2R5Jz6kr4abQsz"
crossorigin="anonymous">
</head>
<body>
<div class="container my-5">
<h3> Update Note</h3>
<div class="card">
<div class="card-body">
<div class="col-md-8">
<form action="#"
th:action="@{/update/{id}(id=${notebook.id})}"
th:object="${notebook}" method="post">
<div class="row">
<div class="form-group col-md-6">
<label for="name" class="col-form-label">Name</label> <input
type="text" th:field="*{name}" class="form-control" id="name"
placeholder="Name"> <span
th:if="${#fields.hasErrors('name')}" th:errors="*{name}"
class="text-danger"></span>
</div>
<div class="form-group col-md-8">
<label for="email" class="col-form-label">Email</label> <input
type="text" th:field="*{email}" class="form-control" id="email"
placeholder="Email"> <span
th:if="${#fields.hasErrors('email')}" th:errors="*{email}"
class="text-danger"></span>
</div>
<div class="form-group col-md-8">
<label for="phoneNo" class="col-form-label">Phone No</label> <input
type="text" th:field="*{phoneNo}" class="form-control"
id="phoneNo" placeholder="phoneNo"> <span
th:if="${#fields.hasErrors('phoneNo')}" th:errors="phoneNo"
class="text-danger"></span>
</div>
<div class="form-group col-md-8">
<input type="submit" class="btn btn-primary"
value="Update Note">
</div>
</div>
</form>
</div>
</div>
</div>
</div>
</body>
</html>

@ -0,0 +1,46 @@
### Example user template template
### Example user template
# IntelliJ project files
.idea
*.iml
out
gen
### Maven template
target/
pom.xml.tag
pom.xml.releaseBackup
pom.xml.versionsBackup
pom.xml.next
release.properties
dependency-reduced-pom.xml
buildNumber.properties
.mvn/timing.properties
# https://github.com/takari/maven-wrapper#usage-without-binary-jar
.mvn/wrapper/maven-wrapper.jar
### Java template
# Compiled class file
*.class
# Log file
*.log
# BlueJ files
*.ctxt
# Mobile Tools for Java (J2ME)
.mtj.tmp/
# Package Files #
*.jar
*.war
*.nar
*.ear
*.zip
*.tar.gz
*.rar
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
hs_err_pid*

Binary file not shown.

After

Width:  |  Height:  |  Size: 60 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 65 KiB

@ -0,0 +1,31 @@
<?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">
<parent>
<artifactId>dev-protocol</artifactId>
<groupId>org.example</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>dev-protocol-gateway</artifactId>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
</dependencies>
</project>

@ -0,0 +1,17 @@
package com.baiye;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
/**
*
*
* @author q
* @date 2021/11/24
*/
@SpringBootApplication
public class DevProtocolGatewayApplication {
public static void main(String[] args) {
SpringApplication.run(DevProtocolGatewayApplication.class, args);
}
}

@ -0,0 +1,24 @@
package com.baiye.notify;
/**
* inotify
* <p>
*
* <p>
*
*
*
* @author q
* @date 2021/11/24
*/
public interface INotifyService {
/**
*
*/
String handleType();
/**
*
*/
Integer handle(String notifyBody);
}

@ -0,0 +1,12 @@
package com.baiye.notify;
import java.util.Map;
import java.util.Objects;
public interface IService {
Map<String, INotifyService> getNotifyServiceMap();
Integer handle(String body);
}

@ -0,0 +1,60 @@
package com.baiye.notify;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import javax.annotation.PostConstruct;
import java.util.Collection;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;
@Service
public class IServiceImpl implements IService {
private ApplicationContext applicationContext;
private Map<String, INotifyService> notifyServiceMap;
/**
* spring INotifyServicemap;
* <p>
*
*/
@PostConstruct
public void init() {
Map<String, INotifyService> map = applicationContext.getBeansOfType(INotifyService.class);
Collection<INotifyService> services = map.values();
if (CollectionUtils.isEmpty(services)) {
return;
}
notifyServiceMap = services.stream().collect(Collectors.toMap(INotifyService::handleType, x -> x));
}
@Override
public Map<String, INotifyService> getNotifyServiceMap() {
return notifyServiceMap;
}
@Override
public Integer handle(String body) {
//参数处理+验签逻辑
// todo 获取具体的业务实现类
INotifyService notifyService = notifyServiceMap.get(Object.class.toString());
Integer status = null;
if (Objects.nonNull(notifyService)) {
//执行具体业务
try {
status = notifyService.handle("这里是传入的参数内容");
} catch (Exception e) {
e.printStackTrace();
}
}
//后续逻辑处理
return status;
}
}

@ -0,0 +1,30 @@
package com.baiye.notify;
import lombok.AllArgsConstructor;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
*
*
*
*
* @author q
* @date 2021/11/24
*/
@AllArgsConstructor
@RestController
@RequestMapping(value = "/notify")
public class NotifyController {
private IService service;
@PostMapping(value = "/receive")
public String receive(@RequestBody String body) {
//处理通知
Integer status = service.handle(body);
return "success";
}
}

@ -1,7 +1,10 @@
package com.baiye;
import org.springframework.boot.SpringApplication;
import cn.hutool.core.util.ArrayUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.context.ConfigurableApplicationContext;
/**
*
@ -10,8 +13,38 @@ import org.springframework.boot.autoconfigure.SpringBootApplication;
* @date 2021/11/16
*/
@SpringBootApplication
@Slf4j
public class DevProtocolLogApplication {
public static void main(String[] args) {
SpringApplication.run(DevProtocolLogApplication.class, args);
// String[] argsNew = addDefaultArgsFromApplication(args);
ConfigurableApplicationContext context = new SpringApplicationBuilder(DevProtocolLogApplication.class)
// 加入一些系统配置
// .properties("Dlog4j.skipJansi=false")
// 读取命令行参数
.run(args);
// SpringApplication.run(DevProtocolLogApplication.class, args);
// todo 也可以同时启动多个容器进行
// ConfigurableApplicationContext context2 = new SpringApplicationBuilder(TestProfiles.class)
// .properties("spring.config.location=classpath:/test-profiles.yml")
// .properties("spring.profiles.active=mysql")
// .properties("server.port=8848")
// .run(args);
}
/**
*
*
* @param args arg
* @return {@link String[]}
*/
private static String[] addDefaultArgsFromApplication(String[] args){
return ArrayUtil.append(args, "Dlog4j.skipJansi=false");
}
}

@ -35,8 +35,8 @@ spring:
# earliest 在偏移量无效的情况下, 消费者从起始位置读取分区的记录
auto-offset-reset: earliest
# 序列化配置
key-deserializer: org.apache.kafka.common.serialization.StringSerializer
value-deserializer: org.apache.kafka.common.serialization.StringSerializer
key-deserializer: org.apache.kafka.common.serialization.StringDeserializer
value-deserializer: org.apache.kafka.common.serialization.StringDeserializer
listener:
# 手动ack方式进行确认
ack-mode: manual

@ -1,6 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- 通用的 log4j2 依赖配置 -->
<!-- 详情见 https://www.jianshu.com/p/bfc182ee33db -->
<!-- log4j2 配置查看 https://logging.apache.org/log4j/2.x/manual/configuration.html#XML -->
<!-- Configuration-->
<!-- status这个用于设置log4j2自身内部的信息输出可以不设置当设置成trace时你会看到log4j2内部各种详细输出&ndash;&gt; OFF为关闭-->
<!-- monitorInterval为一个非零值来让 Log4j 每隔指定的秒数来重新读取配置文件,可以用来动态应用 Log4j 配置 -->
@ -27,8 +28,14 @@
hostAddress : 本地ip地址
-->
<!-- 颜色配置参考 https://logging.apache.org/log4j/2.x/manual/layouts.html -->
<!-- 日志的输出格式 -->
<property name="LOG_PATTERN" value="[%d{yyyy-MM-dd HH:mm:ss, SSS}] [%-5level] [%thread-%tid] [%logger{36}] [%X{hostName}] [%X{ip}] [%X{applicationName}] [%F,%L,%C,%M]- [%m] ## '%ex'%n" />
<!-- fixme 不推荐 2.10版本以后Log4j2默认关闭了Jansi一个支持输出ANSI颜色的类库 要看彩色日志就要加启动参数 -Dlog4j.skipJansi=false -->
<!-- fixme 推荐 把 官网中的 %highlight %style 标签都改成 %clr -->
<!-- 配置举例: 根据级别颜色进行输出的 -->
<!-- <property name="LOG_PATTERN" value=" %clr{[%d{yyyy-MM-dd HH:mm:ss, SSS}][%-5level] [%thread-%tid] [%logger{36}] [%X{applicationName}] [%F,%L,%C,%M]- [%m] ## '%ex'%n}{FATAL=white, ERROR=red, WARN=blue, INFO=black, DEBUG=green, TRACE=blue}" />-->
<!-- 配置举例: 彩色日志 -->
<property name="LOG_PATTERN" value="%style{[%d{yyyy-MM-dd HH:mm:ss, SSS}]}{Yellow} %highlight{[%-5level]}{ERROR=Bright RED, WARN=Bright Yellow, INFO=Bright Green, DEBUG=Bright Cyan, TRACE=Bright White} %style{[%thread-%tid] [%logger{36}]}{Cyan} %style{[%X{hostName}] [%X{ip}] [%X{applicationName}]}{Magenta} %style{[%F,%L,%C,%M]}{Green} - %style{[%m] ## }{{Normal}} %style{'%ex'}{red}%n"/>
<!-- 定义日志存储的路径 -->
<property name="FILE_PATH" value="./log/"/>
<!-- 定义日志输出的文件名 -->

@ -12,6 +12,8 @@
<module>dev-protocol-test</module>
<module>dev-protocol-log</module>
<module>dev-protocol-common</module>
<module>dev-protocol-gateway</module>
<module>dev-protocol-devops</module>
</modules>
<properties>
@ -19,6 +21,7 @@
<maven.compiler.target>8</maven.compiler.target>
<spring.boot.version>2.3.2.RELEASE</spring.boot.version>
<spring.cloud.version>Hoxton.SR10</spring.cloud.version>
</properties>
@ -32,6 +35,13 @@
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring.cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>

Loading…
Cancel
Save