解决Hmily与Feign冲突报错 NullPointerException的问题

网友投稿 324 2022-09-14


解决Hmily与Feign冲突报错 NullPointerException的问题

目录Hmily与Feign冲突报错 NullPointerException解决方法java.lang.NullPointerException出现的几种原因及解决出现的原因

Hmily与Feign冲突报错 NullPointerException

在项目中使用了Hmily保证分布式事务的一致性,由于Hmily会注册一个 HmilyFeignInterceptor ,并且feign会将其添加到 SynchronousMethodHandler 中的 requestInterceptors ,当feign客户端执行 HmilyFeignInterceptor 中apply方法

public void apply(final RequestTemplate requestTemplate) {

Transmiter.getInstance().transmit((x$0, xva$1) -> {

requestTemplate.header(x$0, new String[]{xva$1});

}, HmilyTransactionContextLocal.getInstance().get());

}

由于获取到的 HmilyTransactionContext 为 null ,所以抛出 NullPointerException 异常。

解决方法

定义一个后置处理器,将没有被 @Hmily 注解的方法,移除 HmilyFeignInterceptor 。

package com.jz.shop.cart.service;

import com.jz.shop.commons.utils.text.StringUtils;

import feign.InvocationHandlerFactory;

import feign.ReflectiveFeign;

import feign.RequestInterceptor;

import lombok.extern.slf4j.Slf4j;

import org.dromara.hmily.annotation.Hmily;

import org.dromara.hmily.springcloud.feign.HmilyFeignInterceptor;

import org.springframework.beans.BeansException;

import org.springframework.beans.factory.config.BeanPostProcessor;

import org.springframework.cloud.openfeign.FeignClient;

import org.springframework.core.annotation.AnnotationUtils;

import org.springframework.stereotype.Component;

import org.springframework.stereotype.Controller;

import org.springframework.web.bind.annotation.RestController;

import java.lang.reflect.Field;

import java.lang.reflect.Method;

import java.util.List;

import java.util.Map;

/**

* @author:JZ

* @date:2020/6/1

*/

@Slf4j

@Component

public class ShopFeignPostProcessor implements BeanPostProcessor {

public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {

return bean;

}

public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {

// 对所有含有 @FeignClient 的bean进行处理

if (StringUtils.isNotNull(AnnotationUtils.findAnnotation(bean.getClass(), FeignClient.class))) {

// 排除含有 @Controller 和 @RestController 注解的bean

if (StringUtils.isNotNull(AnnotationUtils.findAnnotation(bean.getClass(), Controller.class)) ||

StringUtils.isNotNull(AnnotationUtils.findAnnotation(bean.getClass(), RestController.class))) {

return bean;

}

try {

// 获取代理类中的 FeignInvocationHandler

Field h = bean.getClass().getSuperclass().getDeclaredField("h");

boolean hAccessible = h.isAccessible();

h.setAccessible(true);

Object feignInvocationHandler = h.get(bean);

/**

* 获取 FeignInvocationHandler 中 dispatch 字段的 Map dispatch 属性。

* dispatch中包含feign代理的方法 和 SynchronousMethodHandler

*/

Field dispatchField = feignInvocationHandler.getClass().getDeclaredField("dispatch");

boolean dispatchAccessible = dispatchField.isAccessible();

dispatchField.setAccessible(true);

Map dispatch =

(Map) dispatchField.get(feignInvocationHandler);

/**

* Synchronohttp://usMethodHandler 中的 List requestInterceptors 字段

* 加载了Hmily对feign的拦截器 HmilyFeignInterceptor

*/

for (Map.Entry entry : dispatch.entrySet()) {

/**

* 没有添加 @Hmily 注解的方法不需要被 Hmily 拦截处理,

* 否则会因为加载的 HmilyTransactionContext 为 null 导致 NullPointerException

*/

if (StringUtils.isNull(AnnotationUtils.findAnnotation(entry.getKey(), Hmily.class))) {

Field riField = entry.getValue().getClass().getDeclaredField("requestInterceptors");

boolean riAccessible = riField.isAccessible();

riField.setAccessible(true);

List requestInterceptors = (List) riField.get(entry.getValue());

for (RequestInterceptor interceptor : requestInterceptors) {

if (interceptor instanceof HmilyFeignInterceptor) {

requestInterceptors.remove(interceptor);

break;

}

}

riField.setAccessible(riAccessible);

log.info("{}.{} 方法移除 HmilyFeignInterceptor", beanName, entry.getKey().getName());

}

}

dispatchField.setAccessible(dispatchAccessible);

h.setAccessible(hAccessible);

} catch (Exception e) {

log.warn("{} exception", beanName);

e.printStackTrace();

}

}

return bean;

}

}

java.lang.NullPointerException出现的几种原因及解决

出现的原因

1、字符串变量未初始化

2、接口类型的对象没有用具体的类初始化,比如:

Map map // 会报错

Map map = new Map(); //则不会报错了

3、当一个对象的值为空时,你没有判断为空的情况。

4、字符串与文字的比较,文字可以是一个字符串或Enum的元素,如下会出现异常

String str = null;

if(str.equals(“Test”)){undefined

//这里的代码将不会被触发,因为会抛出java.lang.NullPointerException异常。

}

5、优先使用String.valueOf()方法代替toString()

当程序代码需要对象的字符串表示形式时,请避免使用该对象的toString方法。如果你的对象的引用等于null,NullPointerException则会抛出,使用静态String.valueOf方法,该方法不会抛出任何异常并打印"null"

6、class被声明了类型, 默认 class = null; 这样在调用class中方法的时候系统只能给你个空指针异常, 给其实例化就好了:class = new Class();

7、返回null,方法的返回值不要定义成为一般的类型,而是用数组。这样如果想要返回null的时候就能避免许多不必要的NullPointerException

我加粗的两个是比较常见的,容易忽略的错误,

大部分都是字符串比较的时候由于str=null,那么使用str.equals(“Test”)就会抛出异常

null不能和字符串进行比较

解决的办法有两种:

就是在比较之前判断字符串是否为空

当传入的参数str是空值的时候,程序就会异常,正确的是应该把字符串放在前面

"Test".equals(str)

推荐使用第二种。


版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:SDH概述(什么叫SDH)
下一篇:Gigamon帮助网络管理员解决10G流量监控难题
相关文章

 发表评论

暂时没有评论,来抢沙发吧~