解决Hmily与Feign冲突报错 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<method, methodhandler> dispatch 属性。 * dispatch中包含feign代理的方法 和 synchronousmethodhandler */ field dispatchfield = feigninvocationhandler.getclass().getdeclaredfield("dispatch"); boolean dispatchaccessible = dispatchfield.isaccessible(); dispatchfield.setaccessible(true); map<method, invocationhandlerfactory.methodhandler> dispatch = (map<method, invocationhandlerfactory.methodhandler>) dispatchfield.get(feigninvocationhandler); /** * synchronousmethodhandler 中的 list<requestinterceptor> requestinterceptors 字段 * 加载了hmily对feign的拦截器 hmilyfeigninterceptor */ for (map.entry<method, invocationhandlerfactory.methodhandler> 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<requestinterceptor> requestinterceptors = (list<requestinterceptor>) 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)
推荐使用第二种。
以上为个人经验,希望能给大家一个参考,也希望大家多多支持。
下一篇: JavaScript 正则表达式详解
推荐阅读
-
Android 中ScrollView与ListView冲突问题的解决办法
-
Android 中ScrollView与ListView冲突问题的解决办法
-
win7下docker安装与报错问题的解决方法
-
解决自定义$(id)的方法与jquery选择器$冲突的问题
-
asp.net开发与web标准的冲突问题的一些常见解决方法
-
python3.8与pyinstaller冲突问题的快速解决方法
-
win7下docker安装与报错问题的解决方法
-
Django与Vue语法的冲突问题完美解决方法
-
php5.3中ZendGuardLoader与wincache冲突问题的解决方法
-
记一次Android音频问题的解决--外挂音频codec与内部av音频输出的冲突