ダボHTTPサービスを公開
点关注不迷路,欢迎再访!
ディレクトリ
序文
通常、ダボサービスは、内部コールの内部にあるが、そこにサービスを提供する必要が外用であってもよく、また、言語の使用の制限を持つことができません。この章では、そんなにそれだけでHTTPサービスの外部サービスを提供ダボの多様性をテストするための許可を必要としない、複雑ではありません話しました。
準備
以下は、この記事で取り上げた知識の一部を以下に示します。
春の知識
Javaリフレクション知識
SpringMVC知識
其实思路很简单,利用SpringMVC提供一个HTTP接口。在该接口中通过入参进行反射找到具体的dubbo服务实现进行调用。
HttpProviderConf設定クラス
私たちは、クラスの完全修飾名を使用する必要性を反映するときに声明を保存するためにHttpProviderConfパッケージ名のクラスを定義する必要があります。まず、すべての後に、サービスを提供するために必要な:
public class HttpProviderConf {
/**
* 提供http访问的包
*/
private List<String> usePackage ;
public List<String> getUsePackage() {
return usePackage;
}
public void setUsePackage(List<String> usePackage) {
this.usePackage = usePackage;
}
}
参照要求に応答して、参照
HttpRequestの入参
public class HttpRequest {
private String param ;//入参
private String service ;//请求service
private String method ;//请求方法
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をリアルタイムコールダボサービスに格納するパラメータに使用される場合には、具体的なパラメータオブジェクトに解析する際に、着信コールは、JSON。
店舗へのダボのサービスパッケージ名サービスは、インタフェースAPIの宣言しました。
この方法は、メソッド呼び出しの本当の名前です。
HttpResponseに応答
public class HttpResponse implements Serializable{
private static final long serialVersionUID = -6296842759601736401L;
private boolean success;// 成功标志
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;
}
}
ここでは唯一の共通HTTP応答データとサービスをカプセル化します。
公開するサービスコントローラ
@Controller
@RequestMapping("/dubboAPI")
public class DubboController implements ApplicationContextAware {
private final static Logger logger = LoggerFactory.getLogger(DubboController.class);
@Autowired
private HttpProviderConf httpProviderConf;
// 缓存作用的map
private final Map<String, Class<?>> cacheMap = new HashMap<String, Class<?>>();
protected ApplicationContext applicationContext;
@ResponseBody
@RequestMapping(value = "/{service}/{method}", method = RequestMethod.GET)
public String api(HttpRequest httpRequest, HttpServletRequest request, @PathVariable String service,
@PathVariable String method) {
logger.info("ip:{}-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) {
// 调用的是未经配置的包
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));
// 设置缓存
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) {
// 没有参数
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;
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
}
-
最初はDubboControllerの定義、および外部被ばくSpringMVCノートHTTPサービスを使用することです。
-
setApplicationContext()メソッドは、スプリング・コンテキスト・オブジェクトを初期化するために使用される器具Org.springframework.context.ApplicationContextAware実装クラスは、対応するコンテナオブジェクトの後に得ることができます。
-
呼び出し()メソッドのコア。
-
ます。http://127.0.0.1:8080 /ダボ-プロバイダ/ dubboAPI / com.dubbo.service.IDubboService / getUserメソッド、あなたが呼び出すと。
-
上記の呼び出しの具体例。まずcom.dubbo.service.IDubboService、getUserメソッドは人参ににHttpRequestに割り当てられています。
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://code.alibabatech.com/schema/dubbo
http://code.alibabatech.com/schema/dubbo/dubbo.xsd">
<!-- 定义了提供方应用信息,用于计算依赖关系。在dubbo-admin 或 dubbo-monitor 会显示这个名字,方便识别 -->
<dubbo:application name="admin-provider" owner="admin" organization="dubbox"/>
<!-- 使用zookeeper 注册中心暴露服务,注意要先开启 zookeeper -->
<dubbo:registry address="zookeeper://127.0.0.1:2181"/>
<!-- 用dubbo协议在20880端口暴露服务 -->
<dubbo:protocol name="dubbo" port="20880"/>
<!-- 用dubbo 协议实现定义好的 api 接口 -->
<dubbo:service interface="com.dubbo.service.IDubboService" ref="dubboService" protocol="dubbo"/>
<dubbo:service interface="com.dubbo.service.IUserService" ref="userService" protocol="dubbo"/>
<!--dubbo服务暴露为http服务-->
<bean class="com.crossoverJie.dubbo.http.conf.HttpProviderConf">
<property name="usePackage">
<list>
<!--需要暴露服务的接口包名,可多个-->
<value>com.dubbo.service</value>
</list>
</property>
</bean>
</beans>
それらが暴露、缶複数を必要とするパッケージ名com.dubbo.serviceです。
- すべての反射の取得は、システムのオーバーヘッドを保存することができないこと、それが反射を取得することによって取得されていない場合、マップキャッシュに取得された除去インタフェースクラス反射型、及びキャッシュへマップの設定値、(リソースの浪費を反映)。
- 次いで、着信インターフェイスgetUserメソッドか否かが判断されます。
- 引数が直接呼び出されていない場合、メソッドのパラメータリストを削除します。
- パラメータがある場合は、数を決定します。パラメータを1つだけ実行するためにここまで。それだけで、具体的なパラメータのリストがBOに書き込むことができ、通話ダボリアルタイムでのBO型を渡すことができます。解決するために多くの時間がJSONの間に存在する場合に2つのパラメータオブジェクトに割り当てることができないので行きます。
- 呼び出しの後、呼び出しが返されるデータを返します。