Skip to content

Commit bc209a0

Browse files
committed
全链路上下文demo
1 parent a3f900b commit bc209a0

20 files changed

+595
-0
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -623,3 +623,5 @@
623623
/springboot-code-authorization/springboot-code-authorization.iml
624624
/springboot-mybatis-autoId/target/
625625
/springboot-mybatis-autoId/springboot-mybatis-autoId.iml
626+
/springboot-chaincontext/target/classes/com/github/lybgeek/chaincontext/
627+
/springboot-chaincontext/springboot-chaincontext.iml

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,3 +106,5 @@ springboot实战系列暂时先更新到这边,下边是对之前springboot实
106106

107107
[springboot之优雅处理返回值](https://mp.weixin.qq.com/s?__biz=MzI1MTY1Njk4NQ==&mid=2247492409&idx=1&sn=e18d0511d71cec0a122d8ea950a81243&chksm=e9ed0d4fde9a8459183519ce711c71dce719d2382b8b9e33bd8adeadc0d6c1bee067b692a02a&token=2137971283&lang=zh_CN#rd)
108108

109+
[如何使用自定义类加载器防止代码被反编译破解](https://mp.weixin.qq.com/s?__biz=MzI1MTY1Njk4NQ==&mid=2247493416&idx=1&sn=2c4cc888793e88df15396ff6fb3dbda0&chksm=e9ed095ede9a8048522c77d9a01d0675ccfd134d2db2f4adccc2eb9c5e85d998edc3c9da2097&token=1482534083&lang=zh_CN#rd)
110+

pom.xml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
<module>springboot-unit-resp</module>
3434
<module>springboot-mybatis-autoId</module>
3535
<module>springboot-code-authorization</module>
36+
<module>springboot-chaincontext</module>
3637
</modules>
3738
<parent>
3839
<groupId>org.springframework.boot</groupId>
@@ -95,10 +96,18 @@
9596
<hytrix.version>1.5.18</hytrix.version>
9697
<spring-kafka.version>2.2.6.RELEASE</spring-kafka.version>
9798
<hutool.version>5.4.1</hutool.version>
99+
<spring-cloud.version>Greenwich.RC2</spring-cloud.version>
98100
</properties>
99101

100102
<dependencyManagement>
101103
<dependencies>
104+
<dependency>
105+
<groupId>org.springframework.cloud</groupId>
106+
<artifactId>spring-cloud-dependencies</artifactId>
107+
<version>${spring-cloud.version}</version>
108+
<type>pom</type>
109+
<scope>import</scope>
110+
</dependency>
102111
<dependency>
103112
<groupId>org.yaml</groupId>
104113
<artifactId>snakeyaml</artifactId>

springboot-chaincontext/ReadME.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
该demo主要演示全链路上下文,其功能包括如下
2+
3+
- RestTemplate在调用下游服务时如何将链路上下文数据携带?
4+
- Feign在调用下游服务时如何将链路上下文数据携带?
5+
- 服务接收方如何将header或者参数中携带的相关数据设置到链路上下文中?
6+
- 如何保证hystrix线程池的情况下链路上下文依然有效?

springboot-chaincontext/pom.xml

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<project xmlns="http://maven.apache.org/POM/4.0.0"
3+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
5+
<parent>
6+
<artifactId>springboot-learning</artifactId>
7+
<groupId>com.github.lybgeek</groupId>
8+
<version>0.0.1-SNAPSHOT</version>
9+
</parent>
10+
<modelVersion>4.0.0</modelVersion>
11+
12+
<artifactId>springboot-chaincontext</artifactId>
13+
14+
<dependencies>
15+
<dependency>
16+
<groupId>org.springframework.boot</groupId>
17+
<artifactId>spring-boot-starter-web</artifactId>
18+
</dependency>
19+
<dependency>
20+
<groupId>org.springframework.cloud</groupId>
21+
<artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
22+
</dependency>
23+
<dependency>
24+
<groupId>org.springframework.cloud</groupId>
25+
<artifactId>spring-cloud-starter-openfeign</artifactId>
26+
</dependency>
27+
</dependencies>
28+
29+
30+
</project>
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
package com.github.lybgeek.chaincontext;
2+
3+
import java.util.Optional;
4+
import java.util.concurrent.ConcurrentHashMap;
5+
6+
/**
7+
* The ChainRequestContext holds all key-value config while key is in {@link ChainContextProperties#getKeys()}
8+
* <p>
9+
* the ChainRequestContext is an extension of a ConcurrentHashMap
10+
*
11+
* @author linyb
12+
*
13+
*/
14+
public class ChainContextHolder extends ConcurrentHashMap<String, Object> {
15+
16+
private static final long serialVersionUID = -5792996927212791314L;
17+
18+
protected static Class<? extends ChainContextHolder> contextClass = ChainContextHolder.class;
19+
20+
protected static final ThreadLocal<? extends ChainContextHolder> THREAD_LOCAL = new InheritableThreadLocal<ChainContextHolder>() {
21+
@Override
22+
protected ChainContextHolder initialValue() {
23+
try {
24+
return contextClass.newInstance();
25+
} catch (Throwable e) {
26+
throw new RuntimeException(e);
27+
}
28+
}
29+
};
30+
31+
/**
32+
* Override the default ChainRequestContext
33+
*
34+
* @param clazz
35+
*/
36+
public static void setContextClass(Class<? extends ChainContextHolder> clazz) {
37+
contextClass = clazz;
38+
}
39+
40+
/**
41+
* Get the current ChainRequestContext
42+
*
43+
* @return the current ChainRequestContext
44+
*/
45+
public static final ChainContextHolder getCurrentContext() {
46+
return THREAD_LOCAL.get();
47+
}
48+
49+
/**
50+
* Unsets the threadLocal context. Done at the end of the request.
51+
*
52+
* @return
53+
*/
54+
public void unset() {
55+
this.clear();
56+
THREAD_LOCAL.remove();
57+
}
58+
59+
/**
60+
* Returns either passed value of the key, or if the value is {@code null}, the value of {@code defaultValue}.
61+
*
62+
* @param key
63+
* @param defaultValue
64+
* @return
65+
*/
66+
public Object getDefault(String key, Object defaultValue) {
67+
return Optional.ofNullable(get(key)).orElse(defaultValue);
68+
}
69+
70+
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
package com.github.lybgeek.chaincontext;
2+
3+
import org.springframework.boot.context.properties.ConfigurationProperties;
4+
5+
import java.util.List;
6+
7+
/**
8+
*
9+
*
10+
* @author linyb
11+
*
12+
*/
13+
@ConfigurationProperties(prefix = "spring.chaincontext")
14+
public class ChainContextProperties {
15+
16+
/**
17+
* Keys to set in chaincontext, all keys with keyPrefix will add to chaincontext while keys is empty
18+
*/
19+
private List<String> keys;
20+
21+
/**
22+
* The prefix of all keys
23+
*/
24+
private String keyPrefix = "X-CHAIN-";
25+
26+
public List<String> getKeys() {
27+
return keys;
28+
}
29+
30+
public void setKeys(List<String> keys) {
31+
this.keys = keys;
32+
}
33+
34+
public String getKeyPrefix() {
35+
return keyPrefix;
36+
}
37+
38+
public void setKeyPrefix(String keyPrefix) {
39+
this.keyPrefix = keyPrefix;
40+
}
41+
42+
}
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
package com.github.lybgeek.chaincontext.autoconfig;
2+
3+
import com.github.lybgeek.chaincontext.ChainContextProperties;
4+
import com.github.lybgeek.chaincontext.feign.FeignConfiguration;
5+
import com.github.lybgeek.chaincontext.hystrix.HystrixChainContextConfiguration;
6+
import com.github.lybgeek.chaincontext.mvc.ChainContextWebMvcConfigure;
7+
import com.github.lybgeek.chaincontext.mvc.ChainContexthandlerInterceptor;
8+
import com.github.lybgeek.chaincontext.parser.DefaultRequestKeyParser;
9+
import com.github.lybgeek.chaincontext.parser.IRequestKeyParser;
10+
import com.github.lybgeek.chaincontext.rest.ChainContextBeanPostProcessor;
11+
import org.springframework.beans.factory.annotation.Autowired;
12+
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
13+
import org.springframework.boot.context.properties.EnableConfigurationProperties;
14+
import org.springframework.context.annotation.Bean;
15+
import org.springframework.context.annotation.Configuration;
16+
import org.springframework.context.annotation.Import;
17+
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
18+
19+
20+
21+
/**
22+
*
23+
* @author linyb
24+
*
25+
*/
26+
@Configuration
27+
@Import({FeignConfiguration.class, HystrixChainContextConfiguration.class})
28+
@EnableConfigurationProperties(ChainContextProperties.class)
29+
public class ChainContextAutoConfiguration implements WebMvcConfigurer {
30+
31+
@Autowired
32+
private ChainContextProperties chainContextProperties;
33+
34+
@ConditionalOnMissingBean
35+
@Bean
36+
public IRequestKeyParser requestKeyParser() {
37+
return new DefaultRequestKeyParser();
38+
}
39+
40+
@Bean
41+
public WebMvcConfigurer webMvcConfigurer(IRequestKeyParser requestKeyParser) {
42+
ChainContexthandlerInterceptor interceptor = new ChainContexthandlerInterceptor(chainContextProperties, requestKeyParser);
43+
return new ChainContextWebMvcConfigure(interceptor);
44+
}
45+
46+
@Bean
47+
public ChainContextBeanPostProcessor chainContextBeanPostProcessor() {
48+
return new ChainContextBeanPostProcessor();
49+
}
50+
51+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
package com.github.lybgeek.chaincontext.feign;
2+
3+
4+
import com.github.lybgeek.chaincontext.ChainContextHolder;
5+
import feign.RequestInterceptor;
6+
import feign.RequestTemplate;
7+
8+
/**
9+
* RequestInterceptor to add chain context to feign request
10+
*
11+
* @author linyb
12+
*
13+
*/
14+
public class ChainContextRequestInterceptor implements RequestInterceptor {
15+
16+
@Override
17+
public void apply(RequestTemplate template) {
18+
if (ChainContextHolder.getCurrentContext() != null) {
19+
ChainContextHolder.getCurrentContext().forEach((key, value) -> {
20+
template.header(key, value.toString());
21+
});
22+
}
23+
}
24+
25+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package com.github.lybgeek.chaincontext.feign;
2+
3+
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
4+
import org.springframework.context.annotation.Bean;
5+
import org.springframework.context.annotation.Configuration;
6+
7+
import com.netflix.loadbalancer.ILoadBalancer;
8+
9+
import feign.Feign;
10+
import feign.RequestInterceptor;
11+
12+
@ConditionalOnClass(value = { ILoadBalancer.class, Feign.class })
13+
@Configuration
14+
public class FeignConfiguration {
15+
16+
@Bean
17+
public RequestInterceptor requestInterceptor() {
18+
return new ChainContextRequestInterceptor();
19+
}
20+
21+
}

0 commit comments

Comments
 (0)