Http Invoke Spring
42435 ワード
Background
プロジェクトチームから最新のリクエストを受け取り、サーバとサーバの間でサービスを交換するように要求されました.
国内の大手企業SIプロジェクトで行ったことのある人は、開発環境が外部インターネットを許さないことを知っているはずだ.
そのため、Webスクロールは使用できません.これは私たちのシステムの機能です.(通常、Webスクロール機能は個別のサーバとして行われ、外部インターネットが利用可能であるが、今回はAシステム内の特定の業務に関連付けなければならないため、A(システム)−B(Webスクロール+Webサービス)間のサービス要求が可能である.
Requirements
以下に、受け取った要件を示します.
Arrangement
上記の要件をまとめると、次の機能とガイドラインが提供されます.
Task
1.複数のデータソース
MyBasisを使用しています.WebCrawlerとInterface Data Sourceを追加するには、追加のSql Sessionビンを定義します.これで問題がないように見えます.ただし、Webスクロール機能とインタフェース機能はモジュール化されているため、新しい定義のSql Sessionが簡単に追加/変更できるかどうかを確認する必要があります.そうしないと、モジュールの内部を変更して新しいバージョンに渡す必要がある場合があります.
2.サーバサービスへの要求
既存のサーバがサーバにサービスを要求するケースはすでに存在しており、これは他のシステムとの通信であるため、「Spring RestTemplateの使用」のガイドラインのみが提供されています.
なぜRest APIを閉じたのですか?
現在は2つのモジュールのみが対象ですが、ソリューションには数十のモジュールがあり、各モジュールには多くの(複雑な)データ型オブジェクトがあります.
後で他のモジュールに同じ要件がある場合は、追加の変更を必要とせずに、同じガイドを使用して迅速に転送することを考慮する必要があります.
RMI, Http Invoke, Hessian, Burlap
内容から見ると、その中のいくつかの章/欠点が見えます.大体以下に示します.
結論:Http Invokeを用いた.
3.ネットワークの問題による故障処理を保証する
Real Code
Bサーバ(サービスプロバイダ)
[web.xml]
要求テンプレートを次のように分離して使用します.
コンマ(,)をinit-paramパラメータの値として登録することで、1つのテンプレートで複数のインタフェースを定義して使用できます.
次のモードを登録して使用します.
{物理インタフェースプールパッケージ名}:{サービス空ID}
<!-- HTTPInvoker -->
<servlet>
<servlet-name>DefaultInvokeServlet</servlet-name>
<servlet-class>jade.web.DefaultInvokeServlet</servlet-class>
<init-param>
<param-name>parameters</param-name>
<param-value>
jade.web.ExecuteService:executeService,
jade.web.ExecutionService:executionService
</param-value>
</init-param>
<load-on-startup>2</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>DefaultInvokeServlet</servlet-name>
<url-pattern>/http/execute/*</url-pattern>
</servlet-mapping>
[DefaultInvokeServlet.java]HttpRequestHandleServiceletクラスを継承し、1つの既存のサーバで1つのインタフェースのみを使用する複数のメソッドを変更して、1つのサーバで複数のインタフェースを処理します.
package jade.web;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.remoting.httpinvoker.HttpInvokerServiceExporter;
import org.springframework.util.StringUtils;
import org.springframework.web.HttpRequestHandler;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.HttpRequestHandlerServlet;
import org.springframework.web.context.support.WebApplicationContextUtils;
public class DefaultInvokeServlet extends HttpRequestHandlerServlet {
private Map<String, HttpRequestHandler> target = new HashMap();
private final String URL_PREFIX = "/http/execute/";
@Override
public void init() throws ServletException {
this.httpInvokerBinder();
}
@Override
protected void service(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
LocaleContextHolder.setLocale(request.getLocale());
try {
getHttpInvoker(request).handleRequest(request, response);
}
catch (HttpRequestMethodNotSupportedException ex) {
String[] supportedMethods = ex.getSupportedMethods();
if (supportedMethods != null) {
response.setHeader("Allow", StringUtils.arrayToDelimitedString(supportedMethods, ", "));
}
response.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED, ex.getMessage());
}
finally {
LocaleContextHolder.resetLocaleContext();
}
}
private HttpRequestHandler getHttpInvoker(HttpServletRequest request) {
// URL_PREFIX
String requestedUri = request.getRequestURI();
String interfaceName = requestedUri.replace(URL_PREFIX, "");
if(this.target.containsKey(interfaceName)) {
return this.target.get(interfaceName);
}else {
return null;
}
}
private void generateHttpInvoker(String interfaceName, String beanName) {
HttpInvokerServiceExporter httpInvoker = new HttpInvokerServiceExporter();
WebApplicationContext wac = WebApplicationContextUtils.getRequiredWebApplicationContext(getServletContext());
httpInvoker.setService(wac.getBean(beanName));
try {
httpInvoker.setServiceInterface(Class.forName(interfaceName));
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
httpInvoker.afterPropertiesSet();
this.target.put(interfaceName, httpInvoker);
}
private void httpInvokerBinder() {
String candidateChars = this.getInitParameter("parameters");
String[] candidates = candidateChars.split(",");
for(String candidate : candidates) {
candidate = candidate.trim();
generateHttpInvoker(candidate.split(":")[0], candidate.split(":")[1]);
}
}
}
Aサーバ(クライアント)
[application-context.xml]
以下に示すように、既存のSpringコンテキストでは空に登録されています.
<bean id="httpInvokerAdvisor" class="jade.web.HttpInvokerAdvisor">
<property name="serviceUrl" value="http://192.168.4.52:9090/http/execute/"/>
<property name="serviceInterface" value="jade.web.ExecuteService"/>
</bean>
[HttpInvokerAdvisor.java]AOPを利用して、いつでもどこでも気軽に利用できます.
考慮すべきは,後で変更可能な点を分離するだけである.
package jade.web;
import java.util.Arrays;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.remoting.httpinvoker.HttpInvokerProxyFactoryBean;
import lombok.Setter;
import jade.core.entity.ExecutionDetail;
import jade.core.entity.ExecutionLevel;
import smartsuite.ifproxy.core.entity.normalize.NormalizedElement;
@Aspect
public class HttpInvokerAdvisor {
HttpInvokerProxyFactoryBean httpInvokerProxyFactoryBean;
@Setter
private String serviceUrl;
@Setter
private String serviceInterface;
@Around("execution(* jade.web.ExecuteService.executeByNormalizedData(..))")
public Object invoke1(ProceedingJoinPoint joinPoint) {
httpInvokerProxyFactoryBean = new HttpInvokerProxyFactoryBean();
try {
httpInvokerProxyFactoryBean.setServiceUrl(serviceUrl);
httpInvokerProxyFactoryBean.setServiceInterface(Class.forName(serviceInterface));
httpInvokerProxyFactoryBean.afterPropertiesSet();
} catch (Exception e) {
e.printStackTrace();
}
Object[] args = joinPoint.getArgs();
ExecuteService httpClient = (ExecuteService) httpInvokerProxyFactoryBean.getObject();
NormalizedElement el = (NormalizedElement)args[1];
ExecutionDetail detail = httpClient.executeByNormalizedData((String)args[0], el, (ExecutionLevel)args[2]);
return detail;
}
@Around("execution(* jade.spring.service.ExecuteServiceSpring.executeByNormalizedData(..))")
public Object invoke2(ProceedingJoinPoint joinPoint) {
try {
httpInvokerProxyFactoryBean.setServiceUrl(serviceUrl);
httpInvokerProxyFactoryBean.setServiceInterface(Class.forName(serviceInterface));
httpInvokerProxyFactoryBean.afterPropertiesSet();
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("logAround() is running!");
System.out.println("hijacked method : " + joinPoint.getSignature().getName());
System.out.println("hijacked arguments : " + Arrays.toString(joinPoint.getArgs()));
ExecuteService httpClient = (ExecuteService) httpInvokerProxyFactoryBean;
String returnText = httpClient.execute(null, joinPoint.getArgs(), null);
return returnText;
}
}
Reference
この問題について(Http Invoke Spring), 我々は、より多くの情報をここで見つけました https://velog.io/@winn85/Web-Service-Using-Springテキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol