Missian指南三:創建一個Missian服務器(使用spring)
在使用Missian時,spring是可選的,但是作者本人強烈推薦和Spring配合使用。Spring是一個偉大的項目,並且它不會對程序在運行時的效率帶來任何損耗。
Missian在服務器端依賴與Mina,Missian只是提供一個Codec(協議編碼解碼,兼容TCP和HTTP)和一個Handler(調用Hessian序列化機制來反序列化數據、使用BeanLocator來定位這次調用的Bean)。熟悉Mina的朋友會很清楚Codec和Handler的概念;不熟悉的朋友也沒關系,按照這個教程一樣可以創建一個高效的服務來。對Mina沒有興趣的朋友可以直接跳到第七步:)
步驟一:創建一個spring配置文件。
- <?xml version="1.0" encoding="UTF-8"?>
- <beans xmlns="http://www.springframework.org/schema/beans"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
- </beans>
步驟二:配置文件中加入:
Xml代碼- <bean class="org.springframework.beans.factory.config.CustomEditorConfigurer">
- <property name="customEditors">
- <map>
- <entry key="java.net.SocketAddress">
- <bean class="org.apache.mina.integration.beans.InetSocketAddressEditor" />
- </entry>
- </map>
- </property>
- </bean>
這個是最後綁定端口時,用來將10.1.23.1:125轉換成SocketAddress的,不用太關註。
步驟三:配置各個Mina的Filter
註意ExecutorFitler是使用的默認構造函數,要指定線程數,或者將已有的線程池傳入,可以使用其它的構造函數;LoggingFilter中除了Exception之外的時間的Log級別已經全部設為DEBUG;CodecFilter是關鍵,這裏引入了Missian的編碼解碼器。
Java代碼- <bean id="executorFilter" class="org.apache.mina.filter.executor.ExecutorFilter" />
- <bean id="codecFilter" class="org.apache.mina.filter.codec.ProtocolCodecFilter">
- <constructor-arg>
- <bean class="com.missian.server.codec.MissianCodecFactory" />
- </constructor-arg>
- </bean>
- <bean id="loggingFilter" class="org.apache.mina.filter.logging.LoggingFilter">
- <property name="messageReceivedLogLevel" value="DEBUG"/>
- <property name="messageSentLogLevel" value="DEBUG"/>
- <property name="sessionCreatedLogLevel" value="DEBUG"/>
- <property name="sessionClosedLogLevel" value="DEBUG"/>
- <property name="sessionIdleLogLevel" value="DEBUG"/>
- <property name="sessionOpenedLogLevel" value="DEBUG"/>
- </bean>
步驟四:構建FilterChian
這裏我把Codec放在線程池之前,因為編碼解碼是CPU密集型的操作,使用線程池並不能提高效率。當然了,有興趣的朋友可以自己調整順序做一下測試。
Java代碼- <bean id="filterChainBuilder"
- class="org.apache.mina.core.filterchain.DefaultIoFilterChainBuilder">
- <property name="filters">
- <map>
- <entry key="codecFilter" value-ref="codecFilter" />
- <entry key="executor" value-ref="executorFilter" />
- <entry key="loggingFilter" value-ref="loggingFilter" />
- </map>
- </property>
- </bean>
步驟五:創建IoHandler。
這一步也很重要,引入了Missian的處理器,就是在這裏調用了Hessian的序列化機制,並完成對相應的Bean的調用。
Xml代碼- <bean id="minaHandler" class="com.missian.server.handler.MissianHandler">
- <constructor-arg>
- <bean class="com.missian.common.beanlocate.SpringLocator" />
- </constructor-arg>
- </bean>
MissianHandler接受一個BeanLocator的構造菜熟,註意這裏直接給MissianHandler註入了一個SpringLocator,使得Missian有能力去Spring去尋找相應的Bean。
這裏是一個很好的擴展點,有需要的話可以在BeanLocator上做做文章。
步驟六:創建一個Acceptor,監聽端口
Java代碼- <bean id="minaAcceptor" class="org.apache.mina.transport.socket.nio.NioSocketAcceptor"
- init-method="bind" destroy-method="unbind">
- <property name="defaultLocalAddress" value=":1235" />
- <property name="handler" ref="minaHandler" />
- <property name="reuseAddress" value="true" />
- <property name="filterChainBuilder" ref="filterChainBuilder" />
- </bean>
到此位置,missian服務配置完畢。接下來配置一下業務邏輯的Bean。
步驟七:配置一個業務邏輯Bean,供Missian客戶端調用
Java代碼- <bean id="hello" class="com.missian.example.bean.HelloImpl"></bean>
上一篇指南裏面創建的這個類第一次出境了,鼓掌……
註意bean的id叫做‘hello’,missian客戶端就是通過‘hello’這個名稱找到這個bean的,例如:http://www.abc.cn/hello。
值得一提的是如果客戶端想通過http://www.abc.cn/p/hello來訪問這個bean,那麽這個bean的配置應該如此:
Java代碼- <bean name="p/hello" class="com.missian.example.bean.HelloImpl"></bean>
ID屬性是不能出現斜杠的,所以通過name來定義這個bean。
步驟八:啟動服務器
Java代碼- public class ServerWithSpring {
- /**
- * @param args
- */
- public static void main(String[] args) {
- new ClassPathXmlApplicationContext("com/missian/example/server/withspring/applicationContext-*.xml");
- }
- }
運行ServerWithSpring即啟動了整個服務了。服務將監聽1235端口,接受HTTP協議和TCP協議格式的請求。
步驟九:用Hessian來調用此服務
由於Missian服務器是兼容Hessian的,所以,在創建Missian客戶端之前,讓我們用Hessian客戶端來測試一下這個服務吧。
Java代碼- HessianProxyFactory factory = new HessianProxyFactory();
- Hello hello = (Hello) factory.create(Hello.class, "http://localhost:1235/hello");
- System.out.println(hello.hello("test", 27));
是的,你會發現調用成功了。
完整的配置文件如下 :
Java代碼- <?xml version="1.0" encoding="UTF-8"?>
- <beans xmlns="http://www.springframework.org/schema/beans"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
- <bean class="org.springframework.beans.factory.config.CustomEditorConfigurer">
- <property name="customEditors">
- <map>
- <entry key="java.net.SocketAddress">
- <bean class="org.apache.mina.integration.beans.InetSocketAddressEditor" />
- </entry>
- </map>
- </property>
- </bean>
- <!-- The IoHandler implementation -->
- <bean id="minaHandler" class="com.missian.server.handler.MissianHandler">
- <constructor-arg>
- <bean class="com.missian.common.beanlocate.SpringLocator" />
- </constructor-arg>
- </bean>
- <!-- the IoFilters -->
- <bean id="executorFilter" class="org.apache.mina.filter.executor.ExecutorFilter" />
- <bean id="codecFilter" class="org.apache.mina.filter.codec.ProtocolCodecFilter">
- <constructor-arg>
- <bean class="com.missian.server.codec.MissianCodecFactory" />
- </constructor-arg>
- </bean>
- <bean id="loggingFilter" class="org.apache.mina.filter.logging.LoggingFilter">
- <property name="messageReceivedLogLevel" value="DEBUG"/>
- <property name="messageSentLogLevel" value="DEBUG"/>
- <property name="sessionCreatedLogLevel" value="DEBUG"/>
- <property name="sessionClosedLogLevel" value="DEBUG"/>
- <property name="sessionIdleLogLevel" value="DEBUG"/>
- <property name="sessionOpenedLogLevel" value="DEBUG"/>
- </bean>
- <!-- The non-SSL filter chain. -->
- <bean id="filterChainBuilder"
- class="org.apache.mina.core.filterchain.DefaultIoFilterChainBuilder">
- <property name="filters">
- <map>
- <entry key="codecFilter" value-ref="codecFilter" />
- <entry key="executor" value-ref="executorFilter" />
- <entry key="loggingFilter" value-ref="loggingFilter" />
- </map>
- </property>
- </bean>
- <!-- The IoAcceptor which binds to port 1235 server side -->
- <bean id="minaAcceptor" class="org.apache.mina.transport.socket.nio.NioSocketAcceptor"
- init-method="bind" destroy-method="unbind">
- <property name="defaultLocalAddress" value=":1235" />
- <property name="handler" ref="minaHandler" />
- <property name="reuseAddress" value="true" />
- <property name="filterChainBuilder" ref="filterChainBuilder" />
- </bean>
- <!-- your business bean, missian client will call this bean by ‘hello‘ -->
- <bean id="hello" class="com.missian.example.bean.HelloImpl"></bean>
- </beans>
Missian指南三:創建一個Missian服務器(使用spring)