NutzCN Logo
问答 nutzboot dubbo 注入问题
发布于 1322天前 作者 文涛(wentao) 1574 次浏览 复制 上一个帖子 下一个帖子
标签:

使用nutzboot和dubbo服务的时候,注入对象出错,报错如下:

org.nutz.ioc.IocException: IocBean[dubboManager -> dubboAnnotationBean -> payInterServiceImpl] throw Exception when creating
        at org.nutz.ioc.impl.ObjectMakerImpl.make(ObjectMakerImpl.java:153)
        at org.nutz.ioc.impl.NutIoc.get(NutIoc.java:241)
        at org.nutz.ioc.impl.NutIoc.getByType(NutIoc.java:457)
        at org.nutz.ioc.impl.NutIoc.getByType(NutIoc.java:426)
        at org.nutz.integration.dubbo.AnnotationBean._init(AnnotationBean.java:73)
        at org.nutz.integration.dubbo.AnnotationBean$FM$_init$dac3e00c3bc87ef1b026b7003e9d0058.invoke(AnnotationBean.java)
        at org.nutz.ioc.impl.ObjectMakerImpl$2.trigger(ObjectMakerImpl.java:181)
        at org.nutz.ioc.weaver.DefaultWeaver.onCreate(DefaultWeaver.java:89)
        at org.nutz.ioc.impl.ObjectMakerImpl.make(ObjectMakerImpl.java:141)
        at org.nutz.ioc.impl.NutIoc.get(NutIoc.java:241)
        at org.nutz.ioc.impl.NutIoc.get(NutIoc.java:271)
        at org.nutz.integration.dubbo.DubboManager.init(DubboManager.java:31)
        at org.nutz.integration.dubbo.DubboManager._init(DubboManager.java:24)
        at org.nutz.integration.dubbo.DubboManager$FM$_init$dac3e00c3bc87ef1b026b7003e9d0058.invoke(DubboManager.java)
        at org.nutz.ioc.impl.ObjectMakerImpl$2.trigger(ObjectMakerImpl.java:181)
        at org.nutz.ioc.weaver.DefaultWeaver.onCreate(DefaultWeaver.java:89)
        at org.nutz.ioc.impl.ObjectMakerImpl.make(ObjectMakerImpl.java:141)
        at org.nutz.ioc.impl.NutIoc.get(NutIoc.java:241)
        at org.nutz.ioc.impl.NutIoc.get(NutIoc.java:271)
        at org.nutz.ioc.impl.NutIoc.get(NutIoc.java:161)
        at org.nutz.boot.starter.dubbo.DubboStarter.start(DubboStarter.java:17)
        at org.nutz.boot.AppContext.startServers(AppContext.java:310)
        at org.nutz.boot.NbApp.execute(NbApp.java:210)
        at org.nutz.boot.NbApp.run(NbApp.java:182)
        at com.tv.cps.pay.MainLauncher.main(MainLauncher.java:66)
Caused by: java.lang.RuntimeException: IocBean[payInterServiceImpl] fail at field=[payHttp]
        at org.nutz.ioc.weaver.FieldInjector.inject(FieldInjector.java:40)
        at org.nutz.ioc.weaver.DefaultWeaver.fill(DefaultWeaver.java:67)
        at org.nutz.ioc.impl.ObjectMakerImpl.make(ObjectMakerImpl.java:138)
        ... 24 more
Caused by: org.nutz.ioc.IocException: IocBean[class:com.tv.cps.common.Http] none ioc bean match class=com.tv.cps.common.Http
        at org.nutz.ioc.impl.NutIoc.getByType(NutIoc.java:461)
        at org.nutz.ioc.val.ReferTypeValue.get(ReferTypeValue.java:66)
        at org.nutz.ioc.weaver.FieldInjector.inject(FieldInjector.java:32)
        ... 26 more

注入代码段

@IocBean
@Service(interfaceClass = PayInterService.class)
public class PayInterServiceImpl implements PayInterService {
    @Inject protected Http payHttp;
    @Override
    public NutMap sendPay(...) throws ApiException{
        payHttp.post(...);
    }
}

http类

public class Http {

    private static final Log log = Logs.get();
    private static final String FORM_CONTENT = "application/x-www-form-urlencoded";
    private static final String JSON_CONTENT = "application/json";
    private static final String XML_CONTENT = "application/xml";

    /**
     * Http名称,用于区分Http的用途
     */
    private String name;
    /**
     * 错误次数,用于管理错误指标及熔断
     */
    private int errNum;
    /**
     * 超时次数,用于管理超时指标及熔断
     */
    private int timeoutNum;
    /**
     * 错误次数熔断指标,0代表不熔断
     */
    private int errDownNum;
    /**
     * 超时次数熔断指标,0代表不熔断
     */
    private int timeoutDownNum;
    /**
     * 熔断后是否自动恢复
     */
    private boolean autoReply;
    /**
     * 熔断自动恢复周期 - 单位:秒
     */
    private int downCycle;

    /**
     * 连接超时时间
     */
    private int connectTimeout;

    /**
     * 等待超时时间
     */
    private int readTimeout;

    /**
     * 处理Http异常
     *
     * @param e
     */
    private void executeException(String url, Throwable e) {
        log.infof(e.getMessage());
        if (e.getMessage().contains("connect timed out")) {
            log.infof("[httpObject:%s] [%s]连接超时...", this.name, url);
            this.timeoutNum++;
        } else if (e.getMessage().contains("Read timed out")) {
            log.infof("[httpObject:%s] [%s] 读取超时...", this.name, url);
            this.timeoutNum++;
        } else {
            System.out.println(e.getMessage());
        }
    }

    /**
     * 设置Http名称
     *
     * @param name
     */
    public void setName(String name) {
        Sender.setup(null);
        this.name = name;
    }

    /**
     * 设置错误次数 - 非200状态的请求返回,Http类会自己管理错误次数
     *
     * @param errNum
     */
    public void setErrNum(int errNum) {
        this.errNum = errNum;
    }

    /**
     * 设置超时次数 - 超时情况下会自己计数,一般情况下不用自己设置
     * 当readTime小于100时,不会计次,用于某些接口不等待返回值的情况
     *
     * @param timeoutNum
     */
    public void setTimeoutNum(int timeoutNum) {
        this.timeoutNum = timeoutNum;
    }

    /**
     * 设置错误熔断次数 - 当错误次数达到上限后,则自动熔断,熔断效果为所有接口返回null
     *
     * @param errDownNum
     */
    public void setErrDownNum(int errDownNum) {
        this.errDownNum = errDownNum;
    }

    /**
     * 设置超时熔断次数 - 当超时次数达到上限后,则自动熔断,熔断效果为所有接口返回null
     *
     * @param timeoutDownNum
     */
    public void setTimeoutDownNum(int timeoutDownNum) {
        this.timeoutDownNum = timeoutDownNum;
    }

    /**
     * 设置熔断后是否自动恢复
     *
     * @param autoReply
     */
    public void setAutoReply(boolean autoReply) {
        this.autoReply = autoReply;
    }

    /**
     * 设置熔断自动恢复周期(秒)
     *
     * @param downCycle
     */
    public void setDownCycle(int downCycle) {
        this.downCycle = downCycle;
        if (downCycle > 0) {
            Tasks.scheduleAtFixedRate(() -> {
                if (autoReply) {
                    clearAllNum();
                }
            }, this.downCycle);
        }
    }

    /**
     * 清空错误和超时计次,用于恢复熔断
     */
    public void clearAllNum() {
        this.errNum = 0;
        this.timeoutNum = 0;
    }

    /**
     * 设置连接超时时间
     *
     * @param connectTimeout
     */
    public void setConnectTimeout(int connectTimeout) {
        this.connectTimeout = connectTimeout;
    }

    /**
     * 设置请求等待超时时间
     *
     * @param readTimeout
     */
    public void setReadTimeout(int readTimeout) {
        this.readTimeout = readTimeout;
    }

    public Http() {
        this.errDownNum = 0;
        this.timeoutDownNum = 0;
        this.autoReply = false;
        this.downCycle = 0;
        this.connectTimeout = 1000;
        this.readTimeout = 5000;
    }

    private String get(String url, NutMap map, String enc) {
        try {
            Stopwatch sw = Stopwatch.begin();
            Response response = Sender.create(Request.get(url).setParams(map).setEnc(enc)).setConnTimeout(connectTimeout).setTimeout(readTimeout).send();
            response.setEncode(enc);
            String result = response.getContent();
            sw.stop();
            log.infof("[httpObject:%s] method:%s url:%s params:%s result:%s postTimes: %sms", this.name, "getData", url, nutMapToKV_UTF8(map), result, sw.getDuration());
            return response.getContent();
        } catch (Throwable e) {
            executeException(url, e.getCause());
            log.errorf("[httpObject:%s] getData error! message is : %s", this.name, e.getCause().getMessage());
            return "";
        }
    }

    private String post(String url, String data, String contentType) {
        try {
            Stopwatch sw = Stopwatch.begin();
            Request req = Request.create(url, Request.METHOD.POST);
            req.setData(data);
            req.getHeader().set("Content-Type", contentType);
            Response response = Sender.create(req).setConnTimeout(connectTimeout).setTimeout(readTimeout).send();
            String result = response.getContent();
            sw.stop();
            log.infof("[httpObject:%s] method:%s content-type:%s url:%s params:%s result:%s postTimes: %sms", this.name, "postData", contentType, url, data, result, sw.getDuration());
            return result;
        } catch (Throwable e) {
            executeException(url, e.getCause());
            log.errorf("[httpObject:%s] postData error! message is : %s", this.name, Lang.getStackTrace(e));
            return "";
        }
    }

    public Response postGetResponse(String url, String data, String contentType) {
        try {
            Stopwatch sw = Stopwatch.begin();
            Request req = Request.create(url, Request.METHOD.POST);
            req.setData(data);
            req.getHeader().set("Content-Type", contentType);
            Response response = Sender.create(req).setConnTimeout(connectTimeout).setTimeout(readTimeout).send();
            return response;
        } catch (Throwable e) {
            executeException(url, e.getCause());
            log.errorf("[httpObject:%s] postData error! message is : %s", this.name, Lang.getStackTrace(e));
            return null;
        }
    }

    /**
     * NutMap转KV形式
     *
     * @param map      map对象
     * @param encoding 字符集编码
     * @return
     */
    private String nutMapToKV(NutMap map, String encoding) {
        if (map == null) return "";
        List<String> dataList = new ArrayList();
        for (Map.Entry<String, Object> stringObjectEntry : map.entrySet()) {
            try {
                String key = stringObjectEntry.getKey();
                Object valueObj = stringObjectEntry.getValue();
                String value= Lang.isEmpty(valueObj) ? "" : URLEncoder.encode(stringObjectEntry.getValue().toString(), encoding);
                dataList.add(String.format("%s=%s", key, value));
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
        }
        return Strings.join("&", dataList);
    }

    /**
     * http get请求UTF8字符集获取信息
     *
     * @param url url
     * @param map map对象
     * @return
     */
    public String getData_UTF8(String url, NutMap map) {
        return get(url, map, "UTF-8");
    }

    /**
     * http get请求GBK字符集获取信息
     *
     * @param url url
     * @param map map对象
     * @return
     */
    public String getData_GBK(String url, NutMap map) {
        return get(url, map, "GBK");
    }

    /**
     * NutMap转KV形式,使用UTF-8字符集encode
     *
     * @param map map对象
     * @return
     */
    public String nutMapToKV_UTF8(NutMap map) {
        return nutMapToKV(map, "UTF-8");
    }

    /**
     * NutMap转KV形式,使用GBK字符集encode
     *
     * @param map
     * @return
     */
    public String nutMapToKV_GBK(NutMap map) {
        return nutMapToKV(map, "GBK");
    }

    /**
     * 发送Form表单的post请求
     *
     * @param url  url
     * @param data 发送的数据 k=v&k=v形式
     * @return
     */
    public String postFormData(String url, String data) {
        return post(url, data, FORM_CONTENT);
    }

    /**
     * 发送json形式的post请求
     *
     * @param url  url
     * @param data 发送的数据 {"a":1,"b":"c"} json格式数据
     * @return
     */
    public String postJsonData(String url, String data) {
        return post(url, data, JSON_CONTENT);
    }

    /**
     * 发送xml形式的post请求
     *
     * @param url  url
     * @param data 发送的数据 xml 格式
     * @return
     */
    public String postXmlData(String url, String data) {
        return post(url, data, XML_CONTENT);
    }

    /**
     * 发送自定义形式的post请求
     *
     * @param url
     * @param body
     * @param header
     * @return
     */
    public String postData(String url, Object body, Header header) {
        try {
            Stopwatch sw = Stopwatch.begin();
            Response response = org.nutz.http.Http.post3(url, body, header, readTimeout, connectTimeout);
            String result = response.getContent();
            sw.stop();
            log.infof("[httpObject:%s] method:%s url:%s params:%s result:%s postTimes: %sms", this.name, "postCommonData", url, body, result, sw.getDuration());
            return result;
        } catch (Throwable e) {
            executeException(url, e);
            return "";
        }
    }
}
9 回复

这Http类没声明为ioc对象,起码用js或者注解声明才行呀

另外,这事情跟dubbo没什么关联性

额,忘了贴这个代码

/**
 * Http自动注入
 *
 * @author wentao
 */
@IocBean
public class HttpStarter implements ServerFace {

    @Inject
    protected PropertiesProxy conf;

    @Inject("refer:$ioc")
    protected Ioc ioc;

    @Override
    public void start() throws Exception {
        Logs.get().debugf("准备注入http对象..");
        // 扫描所有redisName
        String regex = "(\\w*Http)\\.name";
        for (String key : conf.getKeys()) {
            Pattern pattern = Regex.getPattern(regex);
            Matcher match = pattern.matcher(key);
            if (match.find()) {
                String name = match.group(1);
                ioc.addBean(name, conf.make(Http.class, name + "."));
            }
        }
    }
}

我的http注入一直都能正常使用,只有在这个dubbo实现类里注入报错

今天发现还有一条关键日志,最后一条

[DEBUG] 01:36:36.090 org.nutz.ioc.loader.combo.ComboIocLoader.printFoundIocBean(ComboIocLoader.java:226) - Found IocObject(payInterServiceImpl) in AnnotationIocLoader(packages=[com.tv.cps])
[DEBUG] 01:36:36.090 org.nutz.ioc.impl.NutIoc.get(NutIoc.java:166) - Get 'payInterServiceImpl'<class com.tv.cps.pay.service.impl.PayInterServiceImpl>
[DEBUG] 01:36:36.090 org.nutz.ioc.impl.NutIoc.get(NutIoc.java:192) -     >> Load definition name=payInterServiceImpl
[DEBUG] 01:36:36.090 org.nutz.ioc.loader.combo.ComboIocLoader.printFoundIocBean(ComboIocLoader.java:226) - Found IocObject(payInterServiceImpl) in AnnotationIocLoader(packages=[com.tv.cps])
[DEBUG] 01:36:36.090 org.nutz.ioc.impl.NutIoc.get(NutIoc.java:223) -     >> Make...'payInterServiceImpl'<class com.tv.cps.pay.service.impl.PayInterServiceImpl>
[DEBUG] 01:36:36.091 org.nutz.ioc.impl.ScopeContext.save(ScopeContext.java:65) - Save object 'payInterServiceImpl' to [app] 
[DEBUG] 01:36:36.091 org.nutz.ioc.aop.impl.DefaultMirrorFactory.getMirror(DefaultMirrorFactory.java:76) - Load class com.tv.cps.pay.service.impl.PayInterServiceImpl without AOP
[DEBUG] 01:36:36.092 org.nutz.ioc.val.ReferTypeValue.get(ReferTypeValue.java:64) - name=payHttp not found, search for type=com.tv.cps.common.Http

这个http所在的package,与XxxLauncher所在的package不是上下级关系? 为NbApp设置一下mainPackage,默认配置下,只扫描Launcher所在package及子package里的IocBean注解

new NbApp().setMainPackage("xxx.yyy.zzz").run();

MainLauncher里是这样启动的

new NbApp().setArgs(args).setPrintProcDoc(true).setMainPackage("com.tv.cps").run();

当前项目是com.tv.cps.pay 注入类在 com.tv.cps.common

当前项目其他普通http接口注入的http对象是OK的,只有这个dubbo实现类不行

添加回复
请先登陆
回到顶部