日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

将dubbo暴露HTTP服务

發(fā)布時(shí)間:2023/12/20 编程问答 37 豆豆
生活随笔 收集整理的這篇文章主要介紹了 将dubbo暴露HTTP服务 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

通常來說一個(gè)dubbo服務(wù)都是對(duì)內(nèi)的,也就是給內(nèi)部調(diào)用的,但也有可能一個(gè)服務(wù)就是需要提供給外部使用,并且還不能有使用語言的局限性。

比較標(biāo)準(zhǔn)的做法是對(duì)外的服務(wù)我們統(tǒng)一提供一個(gè)openAPI,這樣的調(diào)用方需要按照標(biāo)準(zhǔn)提供相應(yīng)的appID以及密鑰來進(jìn)行驗(yàn)簽才能使用。這樣固然是比較規(guī)范和安全,但復(fù)雜度也不亞于開發(fā)一個(gè)單獨(dú)的系統(tǒng)了。

這里所講到的沒有那么復(fù)雜,就只是把一個(gè)不需要各種權(quán)限檢驗(yàn)的dubbo服務(wù)對(duì)外提供為HTTP服務(wù)。

實(shí)現(xiàn)思路:

1、定義HttpProviderConf配置類

主要用于保存聲明需要對(duì)外提供服務(wù)的包名

package com.bsk.dubbo.http.conf;import java.util.List;public class HttpProviderConf {/*** 提供http訪問的包*/private List<String> usePackage ;public List<String> getUsePackage() {return usePackage;}public void setUsePackage(List<String> usePackage) {this.usePackage = usePackage;} }

2、封裝請(qǐng)求響應(yīng)類

package com.bsk.dubbo.http.req; /*** 請(qǐng)求*/ public class HttpRequest {private String param ;//入?yún)rivate String service ;//請(qǐng)求serviceprivate String method ;//請(qǐng)求方法public String getParam() {return param;}public void setParam(String param) {this.param = param;}public String getService() {return service;}public void setService(String service) {this.service = service;}public String getMethod() {return method;}public void setMethod(String method) {this.method = method;} }

其中param是用于存放真正調(diào)用dubbo服務(wù)時(shí)的入?yún)?#xff0c;傳入json在調(diào)用的時(shí)候解析成具體的參數(shù)對(duì)象。

service存放dubbo服務(wù)聲明的interface API的包名。

method則是真正調(diào)用的方法名稱。

package com.bsk.dubbo.http.rsp;import java.io.Serializable;/*** 響應(yīng)*/ public class HttpResponse implements Serializable{private static final long serialVersionUID = -552828440320737814L;private boolean success;//成功標(biāo)志private String code;//信息碼private String description;//描述public boolean isSuccess() {return success;}public void setSuccess(boolean success) {this.success = success;}public String getCode() {return code;}public void setCode(String code) {this.code = code;}public String getDescription() {return description;}public void setDescription(String description) {this.description = description;} }

?3、編寫暴露服務(wù)Controller接口

利用SpringMVC提供一個(gè)HTTP接口。
在該接口中通過入?yún)⑦M(jìn)行反射找到具體的dubbo服務(wù)實(shí)現(xiàn)進(jìn)行調(diào)用。

package com.bsk.dubbo.http.controller;import com.alibaba.fastjson.JSON; import com.bsk.dubbo.http.conf.HttpProviderConf; import com.bsk.dubbo.http.req.HttpRequest; import com.bsk.dubbo.http.rsp.HttpResponse; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.BeansException; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationContextAware; import org.springframework.context.*; import org.springframework.stereotype.Controller; import org.springframework.util.CollectionUtils; import org.springframework.web.bind.annotation.*;import javax.servlet.http.HttpServletRequest; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.net.InetAddress; import java.net.UnknownHostException; import java.util.HashMap; import java.util.Map;@Controller @RequestMapping("/dubboAPI") public class DubboController implements ApplicationContextAware {private final static Logger logger = LoggerFactory.getLogger(DubboController.class);@Autowiredprivate HttpProviderConf httpProviderConf;/*** 緩存 Map*/private final Map<String, Class<?>> cacheMap = new HashMap<String, Class<?>>();protected ApplicationContext applicationContext;@ResponseBody@RequestMapping(value = "/{service}/{method}", method = RequestMethod.POST)public String api(HttpRequest httpRequest, HttpServletRequest request,@PathVariable String service,@PathVariable String method) {logger.debug("ip:{}-httpRequest:{}", getIP(request), JSON.toJSONString(httpRequest));String invoke = invoke(httpRequest, service, method);logger.debug("callback :" + invoke);return invoke;}private String invoke(HttpRequest httpRequest, String service, String method) {httpRequest.setService(service);httpRequest.setMethod(method);HttpResponse response = new HttpResponse();logger.debug("input param:" + JSON.toJSONString(httpRequest));if (!CollectionUtils.isEmpty(httpProviderConf.getUsePackage())) {boolean isPac = false;for (String pac : httpProviderConf.getUsePackage()) {if (service.startsWith(pac)) {isPac = true;break;}}if (!isPac) {//調(diào)用的是未經(jīng)配置的包logger.error("service is not correct,service=" + service);response.setCode("2");response.setSuccess(false);response.setDescription("service is not correct,service=" + service);}}try {Class<?> serviceCla = cacheMap.get(service);if (serviceCla == null) {serviceCla = Class.forName(service);logger.debug("serviceCla:" + JSON.toJSONString(serviceCla));//設(shè)置緩存cacheMap.put(service, serviceCla);}Method[] methods = serviceCla.getMethods();Method targetMethod = null;for (Method m : methods) {if (m.getName().equals(method)) {targetMethod = m;break;}}if (method == null) {logger.error("method is not correct,method=" + method);response.setCode("2");response.setSuccess(false);response.setDescription("method is not correct,method=" + method);}Object bean = this.applicationContext.getBean(serviceCla);Object result = null;Class<?>[] parameterTypes = targetMethod.getParameterTypes();if (parameterTypes.length == 0) {//沒有參數(shù)result = targetMethod.invoke(bean);} else if (parameterTypes.length == 1) {Object json = JSON.parseObject(httpRequest.getParam(), parameterTypes[0]);result = targetMethod.invoke(bean, json);} else {logger.error("Can only have one parameter");response.setSuccess(false);response.setCode("2");response.setDescription("Can only have one parameter");}return JSON.toJSONString(result);} catch (ClassNotFoundException e) {logger.error("class not found", e);response.setSuccess(false);response.setCode("2");response.setDescription("class not found");} catch (InvocationTargetException e) {logger.error("InvocationTargetException", e);response.setSuccess(false);response.setCode("2");response.setDescription("InvocationTargetException");} catch (IllegalAccessException e) {logger.error("IllegalAccessException", e);response.setSuccess(false);response.setCode("2");response.setDescription("IllegalAccessException");}return JSON.toJSONString(response);}/*** 獲取IP** @param request* @return*/private String getIP(HttpServletRequest request) {if (request == null) {return null;}String s = request.getHeader("X-Forwarded-For");if (s == null || s.length() == 0 || "unknown".equalsIgnoreCase(s)) {s = request.getHeader("Proxy-Client-IP");}if (s == null || s.length() == 0 || "unknown".equalsIgnoreCase(s)) {s = request.getHeader("WL-Proxy-Client-IP");}if (s == null || s.length() == 0 || "unknown".equalsIgnoreCase(s)) {s = request.getHeader("HTTP_CLIENT_IP");}if (s == null || s.length() == 0 || "unknown".equalsIgnoreCase(s)) {s = request.getHeader("HTTP_X_FORWARDED_FOR");}if (s == null || s.length() == 0 || "unknown".equalsIgnoreCase(s)) {s = request.getRemoteAddr();}if ("127.0.0.1".equals(s) || "0:0:0:0:0:0:0:1".equals(s)) {try {s = InetAddress.getLocalHost().getHostAddress();} catch (UnknownHostException unknownhostexception) {return "";}}return s;}@Overridepublic void setApplicationContext(ApplicationContext applicationContext) throws BeansException {this.applicationContext = applicationContext;} }

將這些實(shí)現(xiàn)封裝成一個(gè)功能模塊

具體使用請(qǐng)參考博文:SSM(十三) 將dubbo暴露出HTTP服務(wù) | crossoverJie's Blog

4、測(cè)試示例

使用Jmeter工具進(jìn)行測(cè)試:?

?測(cè)試結(jié)果:

5、總結(jié)

通常來說這樣提供的HTTP接口再實(shí)際中用的不多,但是很方便調(diào)試。

比如寫了一個(gè)dubbo的查詢接口,在測(cè)試環(huán)境或者是預(yù)發(fā)布環(huán)境中就可以直接通過HTTP請(qǐng)求的方式進(jìn)行簡單的測(cè)試,或者就是查詢數(shù)據(jù)。比在Java中寫單測(cè)來測(cè)試或查詢快很多。

總結(jié)

以上是生活随笔為你收集整理的将dubbo暴露HTTP服务的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。