Статьи

Поддержка Spring Remoting с Http Invoker

Spring HTTP Invoker — это важное решение для Java-to-Java Remoting. Эта технология использует стандартный механизм сериализации Java для предоставления сервисов через HTTP и может рассматриваться как альтернативное решение вместо пользовательской сериализации, найденной в Hessian и Burlap. Кроме того, он предоставляется только Spring, поэтому клиентские и серверные приложения должны основываться на Spring.

Spring поддерживает инфраструктуру HTTP invoker через HttpInvokerProxyFactoryBean и HttpInvokerServiceExporter. HttpInvokerServiceExporter, который экспортирует указанный компонент службы в качестве конечной точки службы HTTP invoker, доступный через прокси HTTP invoker. HttpInvokerProxyFactoryBean — это фабричный компонент для прокси-серверов HTTP invoker.

Также предлагается поддержка Spring Remoting и статья RMI для ознакомления с Spring Remoting и примера проекта RMI Service & Client.

Давайте посмотрим на поддержку Spring Remoting для разработки Http Invoker Service & Client.

Используемые технологии:

  • JDK 1.6.0_31
  • Весна 3.1.1
  • Tomcat 7.0
  • Maven 3.0.2

ШАГ 1: СОЗДАТЬ MAVEN ПРОЕКТ

Maven проект создается как показано ниже. (Его можно создать с помощью Maven или IDE Plug-in).

ШАГ 2: БИБЛИОТЕКИ

Spring-зависимости добавляются в pom.xml Maven.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
<!-- Spring 3.1.x dependencies -->
<properties>
    <spring.version>3.1.1.RELEASE</spring.version>
</properties>
  
<dependencies>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-core</artifactId>
        <version>${spring.version}</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>${spring.version}</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-remoting</artifactId>
        <version>2.0.8</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-web</artifactId>
        <version>${spring.version}</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-webmvc</artifactId>
        <version>${spring.version}</version>
    </dependency>
<dependencies>

ШАГ 3: СОЗДАЙТЕ ПОЛЬЗОВАТЕЛЬСКИЙ КЛАСС

Новый класс пользователя создан.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
package com.otv.user;
  
import java.io.Serializable;
  
/**
 * User Bean
 *
 * @author  onlinetechvision.com
 * @since   24 Feb 2012
 * @version 1.0.0
 *
 */
public class User implements Serializable {
  
    private long id;
    private String name;
    private String surname;
  
    /**
     * Get User Id
     *
     * @return long id
     */
    public long getId() {
        return id;
    }
  
    /**
     * Set User Id
     *
     * @param long id
     */
    public void setId(long id) {
        this.id = id;
    }
  
    /**
     * Get User Name
     *
     * @return long id
     */
    public String getName() {
        return name;
    }
  
    /**
     * Set User Name
     *
     * @param String name
     */
    public void setName(String name) {
        this.name = name;
    }
  
    /**
     * Get User Surname
     *
     * @return long id
     */
    public String getSurname() {
        return surname;
    }
  
    /**
     * Set User Surname
     *
     * @param String surname
     */
    public void setSurname(String surname) {
        this.surname = surname;
    }
  
    @Override
    public String toString() {
        StringBuilder strBuilder = new StringBuilder();
        strBuilder.append("Id : ").append(getId());
        strBuilder.append(", Name : ").append(getName());
        strBuilder.append(", Surname : ").append(getSurname());
        return strBuilder.toString();
    }
}

ШАГ 4: СОЗДАЙТЕ ИНТЕРФЕЙС ICacheService

Интерфейс ICacheService, представляющий интерфейс службы удаленного кэша, создан.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
package com.otv.cache.service;
  
import java.util.concurrent.ConcurrentHashMap;
  
import com.otv.user.User;
  
/**
 * Cache Service Interface
 *
 * @author  onlinetechvision.com
 * @since   10 Mar 2012
 * @version 1.0.0
 *
 */
public interface ICacheService {
  
    /**
     * Get User Map
     *
     * @return ConcurrentHashMap User Map
     */
    public ConcurrentHashMap<Long, User> getUserMap();
  
}

ШАГ 5: СОЗДАЙТЕ CacheService CLASS

Класс CacheService создается путем реализации интерфейса ICacheService. Предоставляет доступ к удаленному кешу…

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
package com.otv.cache.service;
  
import java.util.concurrent.ConcurrentHashMap;
  
import com.otv.user.User;
  
/**
 * Cache Service Implementation
 *
 * @author  onlinetechvision.com
 * @since   10 Mar 2012
 * @version 1.0.0
 *
 */
public class CacheService implements ICacheService {
  
    //User Map is injected...
    ConcurrentHashMap<Long, User> userMap;
  
    /**
     * Get User Map
     *
     * @return ConcurrentHashMap User Map
     */
    public ConcurrentHashMap<Long, User> getUserMap() {
        return userMap;
    }
  
    /**
     * Set User Map
     *
     * @param ConcurrentHashMap User Map
     */
    public void setUserMap(ConcurrentHashMap<Long, User> userMap) {
        this.userMap = userMap;
    }
  
}

ШАГ 6: СОЗДАЙТЕ ИНТЕРФЕЙС IHttpUserService

IHttpUserService, представляющий интерфейс службы пользователя Http, создан. Кроме того, он предоставляет удаленные методы для клиентов Http…

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
package com.otv.http.server;
  
import java.util.List;
  
import com.otv.user.User;
  
/**
 * Http User Service Interface
 *
 * @author  onlinetechvision.com
 * @since   10 Mar 2012
 * @version 1.0.0
 *
 */
public interface IHttpUserService {
  
    /**
     * Add User
     *
     * @param  User user
     * @return boolean response of the method
     */
    public boolean addUser(User user);
  
    /**
     * Delete User
     *
     * @param  User user
     * @return boolean response of the method
     */
    public boolean deleteUser(User user);
  
    /**
     * Get User List
     *
     * @return List user list
     */
    public List<User> getUserList();
  
}

ШАГ 7: СОЗДАЙТЕ HttpUserService CLASS

Класс HttpUserService создается путем реализации интерфейса IHttpUserService.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
package com.otv.http.server;
  
import java.util.ArrayList;
import java.util.List;
import org.apache.log4j.Logger;
  
import com.otv.cache.service.ICacheService;
import com.otv.user.User;
  
/**
 * Http User Service Implementation
 *
 * @author  onlinetechvision.com
 * @since   10 Mar 2012
 * @version 1.0.0
 *
 */
public class HttpUserService implements IHttpUserService {
  
    private static Logger logger = Logger.getLogger(HttpUserService.class);
  
    //Remote Cache Service is injected...
    ICacheService cacheService;
  
    /**
     * Add User
     *
     * @param  User user
     * @return boolean response of the method
     */
    public boolean addUser(User user) {
        getCacheService().getUserMap().put(user.getId(), user);
        logger.debug("User has been added to cache. User : "+getCacheService().getUserMap().get(user.getId()));
        return true;
    }
  
    /**
     * Delete User
     *
     * @param  User user
     * @return boolean response of the method
     */
    public boolean deleteUser(User user) {
        getCacheService().getUserMap().remove(user.getId());
        logger.debug("User has been deleted from cache. User : "+user);
        return true;
    }
  
    /**
     * Get User List
     *
     * @return List user list
     */
    public List<User> getUserList() {
        List<User> list = new ArrayList<User>();
        list.addAll(getCacheService().getUserMap().values());
        logger.debug("User List : "+list);
        return list;
    }
  
    /**
     * Get Remote Cache Service
     *
     * @return ICacheService Remote Cache Service
     */
    public ICacheService getCacheService() {
        return cacheService;
    }
  
    /**
     * Set Remote Cache Service
     *
     * @param ICacheService Remote Cache Service
     */
    public void setCacheService(ICacheService cacheService) {
        this.cacheService = cacheService;
    }
  
}

ШАГ 8: СОЗДАЙТЕ HttpUserService-servlet.xml

Контекст приложения HttpUserService отображается следующим образом. Этот xml должен называться your_servlet_name-servlet.xml

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:util="http://www.springframework.org/schema/util"
        xsi:schemaLocation="http://www.springframework.org/schema/beans
  
  
  
  
    <!-- User Map Declaration -->
    <bean id="UserMap" class="java.util.concurrent.ConcurrentHashMap" />
  
    <!-- Cache Service Declaration -->
    <bean id="CacheService" class="com.otv.cache.service.CacheService">
        <property name="userMap" ref="UserMap"/>
    </bean>  
  
    <!-- Http User Service Bean Declaration -->
    <bean id="HttpUserService" class="com.otv.http.server.HttpUserService" >
        <property name="cacheService" ref="CacheService"/>
    </bean>
  
    <!-- Http Invoker Service Declaration -->
    <bean id="HttpUserServiceExporter" class="org.springframework.remoting.httpinvoker.HttpInvokerServiceExporter">
  
        <!-- service represents Service Impl -->
        <property name="service" ref="HttpUserService"/>
  
        <!-- serviceInterface represents Http Service Interface which is exposed -->
        <property name="serviceInterface" value="com.otv.http.server.IHttpUserService"/>
  
    </bean>
  
    <!-- Mapping configurations from URLs to request handler beans -->
    <bean id="urlMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
        <property name="mappings">
            <props>
                <prop key="/HttpUserService">HttpUserServiceExporter</prop>
            </props>
        </property>
    </bean>
  
</beans>

ШАГ 9: СОЗДАТЬ web.xml

web.xml настроен следующим образом:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
<?xml version="1.0" encoding="UTF-8"?>
  
    <display-name>OTV_SpringHttpInvoker</display-name>
  
    <!-- Spring Context Configuration' s Path definition -->
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>
            /WEB-INF/HttpUserService-servlet.xml
        </param-value>
    </context-param>
  
    <!-- The Bootstrap listener to start up and shut down Spring's root WebApplicationContext. It is registered to Servlet Container -->
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
  
    <!-- Central dispatcher for HTTP-based remote service exporters. Dispatches to registered handlers for processing web requests.-->
    <servlet>
        <servlet-name>HttpUserService</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <load-on-startup>2</load-on-startup>
    </servlet>
  
    <!-- Servlets should be registered with servlet container and mapped with url for the http requests. -->
    <servlet-mapping>
        <servlet-name>HttpUserService</servlet-name>
        <url-pattern>/HttpUserService</url-pattern>
    </servlet-mapping>
  
    <welcome-file-list>
      <welcome-file>/pages/index.xhtml</welcome-file>
    </welcome-file-list>
  
</web-app>

ШАГ 10: СОЗДАЙТЕ КЛАСС HttpUserServiceClient

Класс HttpUserServiceClient создан. Вызывает Remote Http User Service и выполняет пользовательские операции.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
package com.otv.http.client;
  
import org.apache.log4j.Logger;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
  
import com.otv.http.server.IHttpUserService;
import com.otv.user.User;
  
/**
 * Http User Service Client
 *
 * @author  onlinetechvision.com
 * @since   24 Feb 2012
 * @version 1.0.0
 *
 */
public class HttpUserServiceClient {
  
    private static Logger logger = Logger.getLogger(HttpUserServiceClient.class);
  
    /**
     * Main method of the Http User Service Client
     *
     */
    public static void main(String[] args) {
  
        logger.debug("Http User Service Client is starting...");
  
        //Http Client Application Context is started...
        ApplicationContext context = new ClassPathXmlApplicationContext("httpClientAppContext.xml");
  
        //Remote User Service is called via Http Client Application Context...
        IHttpUserService httpClient = (IHttpUserService) context.getBean("HttpUserService");
  
        //New User is created...
        User user = new User();
        user.setId(1);
        user.setName("Bruce");
        user.setSurname("Willis");
  
        //The user is added to the remote cache...
        httpClient.addUser(user);
  
        //The users are gotten via remote cache...
        httpClient.getUserList();
  
        //The user is deleted from remote cache...
        httpClient.deleteUser(user);
  
        logger.debug("Http User Service Client is stopped...");
    }
}

ШАГ 11: СОЗДАЙТЕ httpClientAppContext.xml

Контекст приложения клиента Http выглядит следующим образом:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
  
  
    <!-- Http Invoker Client Declaration -->
    <bean id="HttpUserService" class="org.springframework.remoting.httpinvoker.HttpInvokerProxyFactoryBean">
  
        <!-- serviceUrl demonstrates Http Service Url which is called-->
        <property name="serviceUrl" value="http://remotehost:port/OTV_SpringHttpInvoker-0.0.1-SNAPSHOT/HttpUserService"/>
  
        <!-- serviceInterface demonstrates Http Service Interface which is called -->
        <property name="serviceInterface" value="com.otv.http.server.IHttpUserService"/>
  
    </bean>
  
</beans>

ШАГ 12: ДЕПЛОЙНЫЙ ПРОЕКТ

После развертывания проекта OTV_SpringHttpInvoker на Tomcat запускается клиент службы поддержки пользователей Http, и выходные журналы отображаются следующим образом:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
....
15.03.2012 21:26:41 DEBUG (DispatcherServlet.java:819) - DispatcherServlet with name 'HttpUserService' processing POST request for [/OTV_SpringHttpInvoker-0.0.1-SNAPSHOT/HttpUserService]
15.03.2012 21:26:41 DEBUG (AbstractUrlHandlerMapping.java:124) - Mapping [/HttpUserService] to HandlerExecutionChain with handler [org.springframework.remoting.httpinvoker.HttpInvokerServiceExporter@f9104a] and 1 interceptor
15.03.2012 21:26:41 DEBUG (RemoteInvocationTraceInterceptor.java:73) - Incoming HttpInvokerServiceExporter remote call: com.otv.http.server.IHttpUserService.addUser
15.03.2012 21:26:41 DEBUG (HttpUserService.java:33) - User has been added to cache. User : Id : 1, Name : Bruce, Surname : Willis
15.03.2012 21:26:41 DEBUG (RemoteInvocationTraceInterceptor.java:79) - Finished processing of HttpInvokerServiceExporter remote call: com.otv.http.server.IHttpUserService.addUser
15.03.2012 21:26:41 DEBUG (DispatcherServlet.java:957) - Null ModelAndView returned to DispatcherServlet with name 'HttpUserService': assuming HandlerAdapter completed request handling
15.03.2012 21:26:41 DEBUG (FrameworkServlet.java:913) - Successfully completed request
15.03.2012 21:26:41 DEBUG (DispatcherServlet.java:819) - DispatcherServlet with name 'HttpUserService' processing POST request for [/OTV_SpringHttpInvoker-0.0.1-SNAPSHOT/HttpUserService]
15.03.2012 21:26:41 DEBUG (AbstractUrlHandlerMapping.java:124) - Mapping [/HttpUserService] to HandlerExecutionChain with handler [org.springframework.remoting.httpinvoker.HttpInvokerServiceExporter@f9104a] and 1 interceptor
15.03.2012 21:26:41 DEBUG (RemoteInvocationTraceInterceptor.java:73) - Incoming HttpInvokerServiceExporter remote call: com.otv.http.server.IHttpUserService.getUserList
15.03.2012 21:26:41 DEBUG (HttpUserService.java:57) - User List : [Id : 1, Name : Bruce, Surname : Willis]
15.03.2012 21:26:41 DEBUG (RemoteInvocationTraceInterceptor.java:79) - Finished processing of HttpInvokerServiceExporter remote call: com.otv.http.server.IHttpUserService.getUserList
15.03.2012 21:26:41 DEBUG (DispatcherServlet.java:957) - Null ModelAndView returned to DispatcherServlet with name 'HttpUserService': assuming HandlerAdapter completed request handling
15.03.2012 21:26:41 DEBUG (FrameworkServlet.java:913) - Successfully completed request
15.03.2012 21:26:41 DEBUG (DispatcherServlet.java:819) - DispatcherServlet with name 'HttpUserService' processing POST request for [/OTV_SpringHttpInvoker-0.0.1-SNAPSHOT/HttpUserService]
15.03.2012 21:26:41 DEBUG (AbstractUrlHandlerMapping.java:124) - Mapping [/HttpUserService] to HandlerExecutionChain with handler [org.springframework.remoting.httpinvoker.HttpInvokerServiceExporter@f9104a] and 1 interceptor
15.03.2012 21:26:41 DEBUG (RemoteInvocationTraceInterceptor.java:73) - Incoming HttpInvokerServiceExporter remote call: com.otv.http.server.IHttpUserService.deleteUser
15.03.2012 21:26:41 DEBUG (HttpUserService.java:45) - User has been deleted from cache. User : Id : 1, Name : Bruce, Surname : Willis
15.03.2012 21:26:41 DEBUG (RemoteInvocationTraceInterceptor.java:79) - Finished processing of HttpInvokerServiceExporter remote call: com.otv.http.server.IHttpUserService.deleteUser
15.03.2012 21:26:41 DEBUG (DispatcherServlet.java:957) - Null ModelAndView returned to DispatcherServlet with name 'HttpUserService': assuming HandlerAdapter completed request handling
15.03.2012 21:26:41 DEBUG (FrameworkServlet.java:913) - Successfully completed request
...

ШАГ 13: СКАЧАТЬ

OTV_SpringHttpInvoker

Справка: поддержка Spring Remoting с Http Invoker от нашего партнера по JCG Эрен Авсарогуллари в блоге Online Technology Vision .