大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。
Jetbrains全家桶1年46,售后保障稳定
说明:使用bytebuddy框架来实现 RestTemplate链路追踪,并且将日志id追加到头部,借鉴 skywalking 中增强技术;直接上代码。
maven依赖
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<byte.buddy.version>1.9.6</byte.buddy.version>
<lombok.version>1.18.22</lombok.version>
<log4.version>1.2.17</log4.version>
<log4.api.version>1.7.21</log4.api.version>
<spring.web.version>5.2.8.RELEASE</spring.web.version>
<dubbo.version>2.7.0</dubbo.version>
<javax.version>4.0.1</javax.version>
</properties>
<dependency>
<groupId>net.bytebuddy</groupId>
<artifactId>byte-buddy</artifactId>
<version>${byte.buddy.version}</version>
</dependency>
<dependency>
<groupId>net.bytebuddy</groupId>
<artifactId>byte-buddy-agent</artifactId>
<version>${byte.buddy.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>${spring.web.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>${spring.web.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo</artifactId>
<version>${dubbo.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>${javax.version}</version>
<scope>provided</scope>
</dependency>
1. 入口类
public class TraceAgent
{
public static void premain(String args, Instrumentation instrumentation) {
//将插件从文件中读取出来
PluginFinder pluginFinder = new PluginFinder(new PluginBootstrap().loadPlugins());
//创建一个代理增强对象
new AgentBuilder.Default()
//通过自定义实现的类去拦截指定的对象
.type(pluginFinder.buildMatch()) //拦截指定的类
.transform(new Transformer(pluginFinder))
.installOn(instrumentation);
}
public static class Transformer implements AgentBuilder.Transformer {
//插件持有器
private final PluginFinder pluginFinder;
public Transformer(PluginFinder pluginFinder) {
this.pluginFinder = pluginFinder;
}
@Override
public DynamicType.Builder<?> transform(DynamicType.Builder<?> builder, TypeDescription typeDescription, ClassLoader classLoader,
JavaModule javaModule) {
//获取到插件,构建一个动态插件器
List<ClassEnhancePluginDefine> classEnhancePluginDefines = pluginFinder.find(typeDescription);
if (classEnhancePluginDefines.size() > 0) {
//判断当前插件是否符合当前的拦截对象
DynamicType.Builder<?> newBuilder = builder;
//调用插件的define方法去获取到动态类型构造器,就是去返回需要匹配方法的增强方法
for (ClassEnhancePluginDefine define : classEnhancePluginDefines) {
DynamicType.Builder<?> possibleNewBuilder = define.define(builder, classLoader);
if (possibleNewBuilder != null) {
newBuilder = possibleNewBuilder;
}
}
return newBuilder;
}
return builder;
}
}
}
2. 插件读取器
public class PluginBootstrap {
/** PLUGINS */
private static final String PLUGINS = "agent-plugin.def";
//主要是将文件中的插件读取出来,然后通过名称构造出来
public List<ClassEnhancePluginDefine> loadPlugins() {
ClassPathResource classPathResource = new ClassPathResource(PLUGINS);
List<ClassEnhancePluginDefine> enhancePluginDefines = new ArrayList<>();
try {
if (!classPathResource.exists()) {
return enhancePluginDefines;
}
InputStreamReader streamReader = new InputStreamReader(classPathResource.getInputStream());
BufferedReader reader = new BufferedReader(streamReader);
String tempString;
while ((tempString = reader.readLine()) != null) {
if (tempString.trim().length() == 0 || tempString.startsWith("#")) {
continue;
}
if (StringUtils.isEmpty(tempString)) {
continue;
}
String[] pluginDefine = tempString.split("=");
if (pluginDefine.length != 2) {
continue;
}
log.debug("读取到插件类:{}", pluginDefine[1]);
ClassEnhancePluginDefine classEnhancePluginDefine = (ClassEnhancePluginDefine) Class.forName(pluginDefine[1],
true,
this.getClass().getClassLoader())
.newInstance();
enhancePluginDefines.add(classEnhancePluginDefine);
}
} catch (Exception e) {
log.error("读取插件配置异常:", e);
}
return enhancePluginDefines;
}
}
3. agent-plugin.def文件定义
spring-resttemplate=com.xxx.agent.interceptor.resttemplate.sync.RestTemplateInstrumentation
dubbo=com.xxx.agent.interceptor.doubbo.DubboInstrumentation
httpServlet=com.xxx.agent.interceptor.httpservlet.HttpServletInstrumentation
4. 插件持有器
public class PluginFinder {
private final Map<String, LinkedList<ClassEnhancePluginDefine>> nameMatchDefine = new HashMap<>();
//将读取出来的插件传入到 PluginFinder 持有器中
public PluginFinder(List<ClassEnhancePluginDefine> classEnhancePluginDefines) {
//遍历插件的名称,并且添加到名字匹配器当中
classEnhancePluginDefines.forEach(classEnhancePluginDefine -> {
//调用插件的实现方法,将需要增强的对象设置到map当中,value就是多个插件List
String enhanceClass = classEnhancePluginDefine.enhanceClass();
LinkedList<ClassEnhancePluginDefine> enhancePluginDefines = nameMatchDefine.computeIfAbsent(enhanceClass,
k -> new LinkedList<>());
enhancePluginDefines.add(classEnhancePluginDefine);
});
}
//通过传入的 typeDescription 对象来判断是否是指定要增强的类,并且返回插件
public List<ClassEnhancePluginDefine> find(TypeDescription typeDescription) {
List<ClassEnhancePluginDefine> matchedPlugins = new LinkedList<ClassEnhancePluginDefine>();
String typeName = typeDescription.getTypeName();
if (nameMatchDefine.containsKey(typeName)) {
matchedPlugins.addAll(nameMatchDefine.get(typeName));
}
return matchedPlugins;
}
//构建一个匹配器
public ElementMatcher<? super TypeDescription> buildMatch() {
ElementMatcher.Junction elementMatcher = new AbstractJunction<NamedElement>() {
@Override
//判断class名称是否是自己需要增强,在初始化的时候就把插件需要增强的类设置进去了
public boolean matches(NamedElement namedElement) {
return nameMatchDefine.containsKey(namedElement.getActualName());
}
};
//判断需要创建的对象是不是一个接口
elementMatcher = elementMatcher.and(not(isInterface()));
for (String matchClass : nameMatchDefine.keySet()) {
elementMatcher = elementMatcher.or(nameStartsWithIgnoreCase(matchClass));
}
//然后返回属性匹配器
return new ProtectiveShieldMatcher<>(elementMatcher);
}
}
public class ProtectiveShieldMatcher<T> extends ElementMatcher.Junction.AbstractBase<T> {
/** Element matcher */
private final ElementMatcher<? super T> elementMatcher;
/** * Protective shield matcher * * @param elementMatcher element matcher * @since 1.0.0 */
public ProtectiveShieldMatcher(ElementMatcher<? super T> elementMatcher) {
this.elementMatcher = elementMatcher;
}
/** * Matches * * @param target target * @return the boolean * @since 1.0.0 */
@Override
public boolean matches(T target) {
try {
return this.elementMatcher.matches(target);
} catch (Throwable t) {
log.warn("匹配增强类失败:{}", t.getMessage());
return false;
}
}
}
public abstract class AbstractJunction<S> implements ElementMatcher.Junction<S> {
/** * And * * @param <U> parameter * @param elementMatcher element matcher * @return the junction * @since 1.0.0 */
@Override
public <U extends S> Junction<U> and(ElementMatcher<? super U> elementMatcher) {
return new Conjunction<>(this, elementMatcher);
}
/** * Or * * @param <U> parameter * @param elementMatcher element matcher * @return the junction * @since 1.0.0 */
@Override
public <U extends S> Junction<U> or(ElementMatcher<? super U> elementMatcher) {
return new Disjunction<>(this, elementMatcher);
}
}
5. 插件定义的顶级接口类
public interface ClassEnhancePluginDefine {
/** * 需要增强的类 * * @return the string * @since 1.0.0 */
String enhanceClass();
/** * 获取到定义方法 * * @return the dynamic type . builder * @since 1.0.0 */
DynamicType.Builder<?> define(DynamicType.Builder<?> newBuilder,
ClassLoader classLoader);
/** * 获取到需要增强的具体方法 * * @return the list * @since 1.0.0 */
InstanceMethodsInterceptPoint[] enhanceInstance();
}
6. 抽象插件类
public abstract class AbstractClassEnhancePluginDefine implements ClassEnhancePluginDefine {
@Override
public DynamicType.Builder<?> define(DynamicType.Builder<?> newBuilder, ClassLoader classLoader) {
//获取到需要拦截的方法
InstanceMethodsInterceptPoint[] instanceMethodsInterceptPoints = this.enhanceInstance();
if (instanceMethodsInterceptPoints.length <= 0) {
return newBuilder;
}
//遍历需要拦截点位
for (InstanceMethodsInterceptPoint instanceMethodsInterceptPoint : instanceMethodsInterceptPoints) {
//需要使用的拦截器
Class<?> interceptor = instanceMethodsInterceptPoint.getMethodsInterceptor();
//获取到需要拦截的方法匹配器
ElementMatcher.Junction<MethodDescription> junction
= not(isStatic()).and(instanceMethodsInterceptPoint.getMethodsMatcher());
//将需要拦截的方法以及执行的拦截器挂载到builder上
newBuilder = newBuilder
.method(junction)
.intercept(MethodDelegation
.withDefaultConfiguration()
.to(new InstMethodsInter(interceptor)));
}
return newBuilder;
}
}
7. 增强方法的顶级接口
public interface InstanceMethodsInterceptPoint {
/** * 方法匹配器 * * @return the methods matcher * @since 1.0.0 */
ElementMatcher<MethodDescription> getMethodsMatcher();
/** * 方法拦截器 * * @return the methods interceptor * @since 1.0.0 */
Class<?> getMethodsInterceptor();
/** * 是否覆盖参数,暂未实现 * * @return the boolean * @since 1.0.0 */
boolean isOverrideArgs();
}
8. 环绕方法的拦截器
public interface InstanceMethodsAroundInterceptor {
/** * Before method * * @param objInst obj inst * @param method method * @param allArguments all arguments * @param argumentsTypes arguments types * @throws Throwable throwable * @since 1.0.0 */
void beforeMethod(Object objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes) throws Throwable;
/** * After method * * @param objInst obj inst * @param method method * @param allArguments all arguments * @param argumentsTypes arguments types * @param result result * @return the object * @throws Throwable throwable * @since 1.0.0 */
Object afterMethod(Object objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes, Object result) throws Throwable;
/** * Handle method exception * * @param objInst obj inst * @param method method * @param allArguments all arguments * @param argumentsTypes arguments types * @param t t * @since 1.0.0 */
void handleMethodException(Object objInst, Method method, Object[] allArguments,
Class<?>[] argumentsTypes, Throwable t);
}
9. 方法执行的包装方法
public class InstMethodsInter {
/** Interceptor */
private InstanceMethodsAroundInterceptor interceptor;
/** * Inst methods inter * * @param interceptorName interceptor name * @since 1.0.0 */
public InstMethodsInter(@NonNull Class<?> interceptorName) {
try {
this.interceptor = (InstanceMethodsAroundInterceptor) interceptorName.newInstance();
} catch (Exception e) {
e.printStackTrace();
}
}
/** * Intercept * * @param obj obj * @param allArguments all arguments * @param method method * @param callable callable * @return the object * @since 1.0.0 */
@RuntimeType
public Object intercept(@This Object obj,
@AllArguments Object[] allArguments,
@Origin Method method,
@SuperCall Callable<?> callable) {
Object result = null;
try {
interceptor.beforeMethod(obj, method, allArguments, method.getParameterTypes());
} catch (Throwable throwable) {
log.error("前置增强方法执行异常:", throwable);
}
try {
//真正方法的执行
result = callable.call();
} catch (Throwable t) {
interceptor.handleMethodException(obj, method, allArguments, method.getParameterTypes(), t);
} finally {
try {
result = interceptor.afterMethod(obj, method, allArguments, method.getParameterTypes(), result);
} catch (Throwable t) {
log.error("后置增强方法执行异常:", t);
}
}
return result;
}
}
10. 实现的插件类
RestTemplate 增强类
public class RestTemplateInstrumentation extends AbstractClassEnhancePluginDefine {
/** 需要增强的类*/
private static final String ENHANCE_CLASS = "org.springframework.web.client.RestTemplate";
/** 需要增强的方法*/
private static final String DO_EXECUTE_METHOD_NAME = "doExecute";
/** 对应增强方法执行的类*/
private static final Class<?> DO_EXECUTE_INTERCEPTOR = RestExecuteInterceptor.class;
/** 需要增强的方法*/
private static final String HANDLE_REQUEST_METHOD_NAME = "handleResponse";
/** 对应增强方法执行的类*/
private static final Class<?> HAND_REQUEST_INTERCEPTOR = RestResponseInterceptor.class;
/** 需要增强的方法 */
private static final String CREATE_REQUEST_METHOD_NAME = "createRequest";
/** 对应增强方法执行的类*/
private static final Class<?> CREATE_REQUEST_INTERCEPTOR = RestRequestInterceptor.class;
/** * Enhance class * * @return the string * @since 1.0.0 */
@Override
public String enhanceClass() {
return ENHANCE_CLASS;
}
/** * Enhance instance * * @return the instance methods intercept point [ ] * @since 1.0.0 */
@Override
public InstanceMethodsInterceptPoint[] enhanceInstance() {
return new InstanceMethodsInterceptPoint[] {
new InstanceMethodsInterceptPoint() {
@Override
public ElementMatcher<MethodDescription> getMethodsMatcher() {
return named(CREATE_REQUEST_METHOD_NAME);
}
@Override
public Class<?> getMethodsInterceptor() {
return CREATE_REQUEST_INTERCEPTOR;
}
@Override
public boolean isOverrideArgs() {
return false;
}
},
new InstanceMethodsInterceptPoint() {
@Override
public ElementMatcher<MethodDescription> getMethodsMatcher() {
return named(DO_EXECUTE_METHOD_NAME);
}
@Override
public Class<?> getMethodsInterceptor() {
return DO_EXECUTE_INTERCEPTOR;
}
@Override
public boolean isOverrideArgs() {
return false;
}
},
new InstanceMethodsInterceptPoint() {
@Override
public ElementMatcher<MethodDescription> getMethodsMatcher() {
return named(HANDLE_REQUEST_METHOD_NAME);
}
@Override
public Class<?> getMethodsInterceptor() {
return HAND_REQUEST_INTERCEPTOR;
}
@Override
public boolean isOverrideArgs() {
return false;
}
}
};
}
}
1. excute() 方法
public class RestExecuteInterceptor implements InstanceMethodsAroundInterceptor {
@Override
public void beforeMethod(Object objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes) throws Throwable {
}
@Override
public Object afterMethod(Object objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes, Object result) throws Throwable {
return result;
}
@Override
public void handleMethodException(Object objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes, Throwable t) {
//调用异常之后打印调用链路
RuntimeContextManager.printTraceLog();
}
}
2. createRequest() 方法
public class RestRequestInterceptor implements InstanceMethodsAroundInterceptor {
@Override
public void beforeMethod(Object objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes) throws Throwable {
}
@Override
public Object afterMethod(Object objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes, Object result) throws Throwable {
ClientHttpRequest clientHttpRequest = (ClientHttpRequest) result;
if (clientHttpRequest instanceof AbstractClientHttpRequest) {
AbstractClientHttpRequest httpRequest = (AbstractClientHttpRequest) clientHttpRequest;
//将traceId追加到header头当中
RuntimeContextManager.CarrierItem item = RuntimeContextManager.get();
while (item.hasNext()) {
item = item.next();
httpRequest.getHeaders().add(ConstName.HEAD_KEY, item.getHeadValue());
}
}
return result;
}
@Override
public void handleMethodException(Object objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes, Throwable t) {
RuntimeContextManager.printTraceLog();
}
}
3. handleResponse() 方法
public class RestResponseInterceptor implements InstanceMethodsAroundInterceptor {
/** * Before method * * @param objInst obj inst * @param method method * @param allArguments all arguments * @param argumentsTypes arguments types * @throws Throwable throwable * @since 1.0.0 */
@Override
public void beforeMethod(Object objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes) throws Throwable {
}
/** * After method * * @param objInst obj inst * @param method method * @param allArguments all arguments * @param argumentsTypes arguments types * @param result result * @return the object * @throws Throwable throwable * @since 1.0.0 */
@Override
public Object afterMethod(Object objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes, Object result) throws Throwable {
ClientHttpResponse clientHttpResponse = (ClientHttpResponse) allArguments[1];
List<String> traceList = clientHttpResponse.getHeaders().get(ConstName.HEAD_KEY);
if (!CollectionUtils.isEmpty(traceList)) {
RuntimeContextManager.remove();
//将trace放到 manager当中存储
traceList.forEach(trace -> {
RuntimeContextManager.add(RuntimeContextManager.CarrierItem.item(trace, trace));
});
}
return result;
}
/** * Handle method exception * * @param objInst obj inst * @param method method * @param allArguments all arguments * @param argumentsTypes arguments types * @param t t * @since 1.0.0 */
@Override
public void handleMethodException(Object objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes, Throwable t) {
RuntimeContextManager.printTraceLog();
}
}
servlet 增强类
public class HttpServletInstrumentation extends AbstractClassEnhancePluginDefine {
private static final String ENHANCE_CLASS = "org.springframework.web.servlet.DispatcherServlet";
private static final String DO_FILTER_METHOD = "service";
private static final Class<HttpServletInterceptor> DO_FILTER_INTERCEPTOR = HttpServletInterceptor.class;
/** * Enhance class * * @return the string * @since 1.0.0 */
@Override
public String enhanceClass() {
return ENHANCE_CLASS;
}
/** * Enhance instance * * @return the instance methods intercept point [ ] * @since 1.0.0 */
@Override
public InstanceMethodsInterceptPoint[] enhanceInstance() {
return new InstanceMethodsInterceptPoint[] {
new InstanceMethodsInterceptPoint() {
@Override
public ElementMatcher<MethodDescription> getMethodsMatcher() {
//拦截对应的方法,并且是public方法
return named(DO_FILTER_METHOD).and(isPublic());
}
@Override
public Class<?> getMethodsInterceptor() {
return DO_FILTER_INTERCEPTOR;
}
@Override
public boolean isOverrideArgs() {
return false;
}
}
};
}
}
1. service() 方法
public class HttpServletInterceptor implements InstanceMethodsAroundInterceptor {
/** * Before method * * @param objInst obj inst * @param method method * @param allArguments all arguments * @param argumentsTypes arguments types * @throws Throwable throwable * @since 1.0.0 */
@Override
public void beforeMethod(Object objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes) throws Throwable {
HttpServletRequest httpRequest = (HttpServletRequest) allArguments[0];
Enumeration<String> headers = httpRequest.getHeaders(ConstName.HEAD_KEY);
//将请求头的数据读取出来后清除掉头部数据
if (headers.hasMoreElements()) {
String nextElement = headers.nextElement();
RuntimeContextManager.CarrierItem carrierItem
= RuntimeContextManager.CarrierItem.item(nextElement, nextElement);
RuntimeContextManager.add(carrierItem);
}
RuntimeContextManager.CarrierItem next = RuntimeContextManager.CarrierItem.item(System.getProperty(ConstName.CONFIG_APP_NAME),
System.getProperty(ConstName.CONFIG_APP_NAME));
RuntimeContextManager.add(next);
httpRequest.removeAttribute(ConstName.HEAD_KEY);
}
/** * After method * * @param objInst obj inst * @param method method * @param allArguments all arguments * @param argumentsTypes arguments types * @param result result * @return the object * @throws Throwable throwable * @since 1.0.0 */
@Override
public Object afterMethod(Object objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes, Object result) throws Throwable {
HttpServletResponse httpServletResponse = (HttpServletResponse) allArguments[1];
RuntimeContextManager.addResponseHeaders(httpServletResponse);
RuntimeContextManager.printTraceLog();
RuntimeContextManager.remove();
return result;
}
/** * Handle method exception * * @param objInst obj inst * @param method method * @param allArguments all arguments * @param argumentsTypes arguments types * @param t t * @since 1.0.0 */
@Override
public void handleMethodException(Object objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes, Throwable t) {
RuntimeContextManager.printTraceLog();
RuntimeContextManager.remove();
}
}
dubbo 增强类
public class DubboInstrumentation extends AbstractClassEnhancePluginDefine {
private static final String ENHANCE_CLASS = "org.apache.dubbo.monitor.support.MonitorFilter";
private static final Class<DubboInterceptor> INTERCEPT_CLASS = DubboInterceptor.class;
/** DO_EXECUTE_METHOD_NAME */
private static final String INVOKE_METHOD_NAME = "invoke";
@Override
public String enhanceClass() {
return ENHANCE_CLASS;
}
@Override
public InstanceMethodsInterceptPoint[] enhanceInstance() {
return new InstanceMethodsInterceptPoint[] {
new InstanceMethodsInterceptPoint() {
@Override
public ElementMatcher<MethodDescription> getMethodsMatcher() {
return named(INVOKE_METHOD_NAME);
}
@Override
public Class<DubboInterceptor> getMethodsInterceptor() {
return INTERCEPT_CLASS;
}
@Override
public boolean isOverrideArgs() {
return false;
}
}
};
}
}
1. invoke() 方法
public class DubboInterceptor implements InstanceMethodsAroundInterceptor {
/** * Before method * * @param objInst obj inst * @param method method * @param allArguments all arguments * @param argumentsTypes arguments types * @throws Throwable throwable * @since y.y.y */
@Override
public void beforeMethod(Object objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes) throws Throwable {
Invoker invoker = (Invoker) allArguments[0];
Invocation invocation = (Invocation) allArguments[1];
RpcContext rpcContext = RpcContext.getContext();
boolean isConsumer = rpcContext.isConsumerSide();
URL requestURL = invoker.getUrl();
if (isConsumer) {
//添加一次当前服务的名称
RuntimeContextManager.add(RuntimeContextManager.CarrierItem.item(System.getProperty(ConstName.CONFIG_APP_NAME),
System.getProperty(ConstName.CONFIG_APP_NAME)));
//判断如果是消费者,将数据写入请求头
String traceStr = RuntimeContextManager.getTraceStr();
rpcContext.getAttachments().put(ConstName.HEAD_KEY, traceStr);
} else {
//如果是提供者
String traceStr = rpcContext.getAttachments().get(ConstName.HEAD_KEY);
RuntimeContextManager.addTraceForStr(traceStr);
}
}
/** * After method * * @param objInst obj inst * @param method method * @param allArguments all arguments * @param argumentsTypes arguments types * @param result result * @return the object * @throws Throwable throwable * @since y.y.y */
@Override
public Object afterMethod(Object objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes, Object result) throws Throwable {
return null;
}
/** * Handle method exception * * @param objInst obj inst * @param method method * @param allArguments all arguments * @param argumentsTypes arguments types * @param t t * @since y.y.y */
@Override
public void handleMethodException(Object objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes, Throwable t) {
}
/** * Generate operation name * * @param requestURL request url * @param invocation invocation * @return the string * @since y.y.y */
private String generateOperationName(URL requestURL, Invocation invocation) {
StringBuilder operationName = new StringBuilder();
String groupStr = requestURL.getParameter(Constants.GROUP_KEY);
groupStr = StringUtils.isEmpty(groupStr) ? "" : groupStr + "/";
operationName.append(groupStr);
operationName.append(requestURL.getPath());
operationName.append("." + invocation.getMethodName() + "(");
for (Class<?> classes : invocation.getParameterTypes()) {
operationName.append(classes.getSimpleName() + ",");
}
if (invocation.getParameterTypes().length > 0) {
operationName.delete(operationName.length() - 1, operationName.length());
}
operationName.append(")");
return operationName.toString();
}
/** * Generate request url * * @param url url * @param invocation invocation * @return the string * @since y.y.y */
private String generateRequestURL(URL url, Invocation invocation) {
StringBuilder requestURL = new StringBuilder();
requestURL.append(url.getProtocol() + "://");
requestURL.append(url.getHost());
requestURL.append(":" + url.getPort() + "/");
requestURL.append(generateOperationName(url, invocation));
return requestURL.toString();
}
}
11. 上下文持有器
public class RuntimeContextManager {
private final static ThreadLocal<CarrierItem> RUNTIME_CARRIER = new ThreadLocal<>();
public static CarrierItem get() {
CarrierItem carrierItem = RUNTIME_CARRIER.get();
if (carrierItem == null) {
carrierItem = new CarrierItem(Thread.currentThread().getName(), System.currentTimeMillis()+"", null);
RUNTIME_CARRIER.set(carrierItem);
}
return carrierItem;
}
public static void remove() {
RUNTIME_CARRIER.remove();
}
public static void add(CarrierItem next) {
CarrierItem item = get();
while (item.hasNext()) {
item = item.next();
}
//如果尾部的服务名跟添加时的一样,就不需要再添加
String headValue = item.getHeadValue();
if (headValue.equalsIgnoreCase(next.headValue)) {
return;
}
item.setNext(next);
}
public static void addRequestHeaders(ClientHttpRequest clientHttpRequest) {
CarrierItem carrierItem = get();
clientHttpRequest.getHeaders().remove(ConstName.HEAD_KEY);
while (carrierItem.hasNext()) {
carrierItem = carrierItem.next;
clientHttpRequest.getHeaders().add(ConstName.HEAD_KEY, carrierItem.headValue);
}
}
public static void addResponseHeaders(ServletResponse servletResponse) {
CarrierItem carrierItem = get();
if (servletResponse instanceof HttpServletResponse) {
while (carrierItem.hasNext()) {
carrierItem = carrierItem.next;
((HttpServletResponse) servletResponse).addHeader(ConstName.HEAD_KEY, carrierItem.headValue);
}
}
}
public static void printTraceLog() {
String s = getTraceStr();
if (s == null) {
return;
}
log.info("服务调用路径:{}", s);
}
public static String getTraceStr() {
CarrierItem carrierItem = get();
List<String> items = new ArrayList<>();
while (carrierItem.hasNext()) {
carrierItem = carrierItem.next;
items.add(carrierItem.headValue);
}
if (CollectionUtils.isEmpty(items)) {
return null;
}
return items.stream().map(String::valueOf).collect(Collectors.joining(ConstName.DELIMITER));
}
public static void addTraceForStr(String traceStr) {
if (StringUtils.isEmpty(traceStr)) {
return;
}
String[] trace = StringUtils.split(traceStr, ConstName.DELIMITER);
Arrays.stream(trace).forEach(str -> {
add(CarrierItem.item(str, str));
});
}
public static class CarrierItem implements Iterator<CarrierItem> {
private String headKey;
private String headValue;
private CarrierItem next;
public CarrierItem() {
}
public CarrierItem(String headKey, String headValue) {
this(headKey, headValue, null);
}
public CarrierItem(String headKey, String headValue, CarrierItem next) {
this.headKey = headKey;
this.headValue = headValue;
this.next = next;
}
public static CarrierItem item(String headKey, String headValue) {
return new CarrierItem(headKey, headValue);
}
@Override
public boolean hasNext() {
return next != null;
}
@Override
public CarrierItem next() {
return next;
}
@Override
public void remove() {
}
public String getHeadKey() {
return headKey;
}
public void setHeadKey(String headKey) {
this.headKey = headKey;
}
public String getHeadValue() {
return headValue;
}
public void setHeadValue(String headValue) {
this.headValue = headValue;
}
public CarrierItem getNext() {
return next;
}
public void setNext(CarrierItem next) {
this.next = next;
}
}
}
public class ConstName {
/** CONFIG_APP_NAME */
public static final String CONFIG_APP_NAME = "APP_NAME";
/** HEAD_KEY */
public static final String HEAD_KEY = "Trace";
/** 分隔符 */
public static final String DELIMITER = "--->";
}
由于公司封装的框架原因,导致restTemplate增强会有问题,所以一在拦截handResponse()会导致提前返回对象;但是大体框架没有问题,都是根据skywalking的源码进行修改,各位看官根据具体的业务可以进行实现;如果有什么错误的地方,还请各位大佬指教
发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/213943.html原文链接:https://javaforall.cn
【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛
【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...