Case introduction
This case realizes a simple rpc framework through three chapters. It is used to learn how rpc framework communicates. The current chapter mainly introduces how to customize XML files and parse them. To parse a custom xml, you first define your own xsd file and implement spring's Namespace Handler Support and Bean Definition Parser, which are processed in two ways.
Remote procedure call protocol
RPC (Remote Procedure Call) - Remote Procedure Call (RPC) is a protocol that requests services from remote computer programs over a network without knowing the underlying network technology. RPC protocol assumes the existence of some transport protocols, such as TCP or UDP, to carry information and data between communication programs. In the OSI network communication model, RPC spans the transport layer and application layer. RPC makes it easier to develop applications including network distributed multi-programs.
RPC adopts client/server mode. The requester is a client, and the service provider is a server. First, the client calling process sends a call information with process parameters to the service process, and then waits for the response information. On the server side, the process remains asleep until the call information arrives. When a call information arrives, the server obtains the process parameters, calculates the result, sends the reply information, and then waits for the next call information. Finally, the client calls the process to receive the reply information, obtains the process result, and then the call execution proceeds.
Dubbo is an excellent open source service framework of Alibaba. It enables applications to achieve output and input functions of services through high performance RPC and seamlessly integrate with Spring framework.
Dubbo is a high-performance, lightweight open source Java RPC framework, which provides three core capabilities: Interface-oriented remote method invocation, intelligent fault tolerance and load balancing, and automatic service registration and discovery.
Environmental preparation
1,jdk 1.8.0
2,IntelliJ IDEA Community Edition 2018.3.1 x64
Code examples
itstack-demo-rpc-01 └── src └── main │ ├── java │ │ └── org.itstack.demo.rpc.config │ │ ├── spring │ │ │ ├── bean │ │ │ │ ├── ConsumerBean.java │ │ │ │ ├── ProviderBean.java │ │ │ │ └── ServerBean.java │ │ │ ├── MyBeanDefinitionParser.java │ │ │ └── MyNamespaceHandler.java │ │ ├── ConsumerConfig.java │ │ ├── ProviderConfig.java │ │ └── ProviderConfig.java │ └── resource │ └── META-INF │ ├── rpc.xsd │ ├── spring.handlers │ └── spring.schemas └── test ├── java │ └── org.itstack.demo.test │ ├── service │ │ ├── impl │ │ │ └── HelloServiceImpl.java │ │ └── HelloService.java │ └── ApiTest.java └── resource ├── itstack-rpc-consumer.xml ├── itstack-rpc-provider.xml └── log4j.xml
ProviderConfig.java
public class ProviderConfig { private String nozzle; //Interface private String ref; //mapping private String alias; //alias //Release protected void doExport() { System.out.format("Producer Information=> [Interface:%s] [Mapping:%s] [Alias:%s] \r\n", nozzle, ref, alias); } public String getNozzle() { return nozzle; } public void setNozzle(String nozzle) { this.nozzle = nozzle; } public String getRef() { return ref; } public void setRef(String ref) { this.ref = ref; } public String getAlias() { return alias; } public void setAlias(String alias) { this.alias = alias; } }
ProviderBean.java
public class ProviderBean extends ProviderConfig implements ApplicationContextAware { @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { //Publisher doExport(); } }
MyBeanDefinitionParser.java
public class MyBeanDefinitionParser implements BeanDefinitionParser { private final Class<?> beanClass; MyBeanDefinitionParser(Class<?> beanClass) { this.beanClass = beanClass; } @Override public BeanDefinition parse(Element element, ParserContext parserContext) { RootBeanDefinition beanDefinition = new RootBeanDefinition(); beanDefinition.setBeanClass(beanClass); beanDefinition.setLazyInit(false); String beanName = element.getAttribute("id"); parserContext.getRegistry().registerBeanDefinition(beanName, beanDefinition); for (Method method : beanClass.getMethods()) { if (!isProperty(method, beanClass)) continue; String name = method.getName(); String methodName = name.substring(3, 4).toLowerCase() + name.substring(4); String value = element.getAttribute(methodName); beanDefinition.getPropertyValues().addPropertyValue(methodName, value); } return beanDefinition; } private boolean isProperty(Method method, Class beanClass) { String methodName = method.getName(); boolean flag = methodName.length() > 3 && methodName.startsWith("set") && Modifier.isPublic(method.getModifiers()) && method.getParameterTypes().length == 1; Method getter = null; if (!flag) return false; Class<?> type = method.getParameterTypes()[0]; try { getter = beanClass.getMethod("get" + methodName.substring(3)); } catch (NoSuchMethodException ignore) { } if (null == getter) { try { getter = beanClass.getMethod("is" + methodName.substring(3)); } catch (NoSuchMethodException ignore) { } } flag = getter != null && Modifier.isPublic(getter.getModifiers()) && type.equals(getter.getReturnType()); return flag; } }
MyNamespaceHandler.java
public class MyNamespaceHandler extends NamespaceHandlerSupport { @Override public void init() { registerBeanDefinitionParser("consumer", new MyBeanDefinitionParser(ConsumerBean.class)); registerBeanDefinitionParser("provider", new MyBeanDefinitionParser(ProviderBean.class)); registerBeanDefinitionParser("server", new MyBeanDefinitionParser(ServerBean.class)); } }
rpc.xsd
<?xml version="1.0" encoding="UTF-8"?> <xsd:schema xmlns="http://rpc.itstack.org/schema/rpc" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:beans="http://www.springframework.org/schema/beans" targetNamespace="http://rpc.itstack.org/schema/rpc" elementFormDefault="qualified" attributeFormDefault="unqualified"> <xsd:import namespace="http://www.springframework.org/schema/beans"/> <!-- org.itstack.demo.rpc.config.ServerConfig --> <xsd:element name="server"> <xsd:complexType> <xsd:complexContent> <xsd:extension base="beans:identifiedType"> <xsd:attribute name="host" type="xsd:string"> <xsd:annotation> <xsd:documentation><![CDATA[ Trestle Place ]]></xsd:documentation> </xsd:annotation> </xsd:attribute> <xsd:attribute name="port" type="xsd:string"> <xsd:annotation> <xsd:documentation><![CDATA[ Trestle Port ]]></xsd:documentation> </xsd:annotation> </xsd:attribute> </xsd:extension> </xsd:complexContent> </xsd:complexType> </xsd:element> <!-- org.itstack.demo.rpc.config.ConsumerConfig --> <xsd:element name="consumer"> <xsd:complexType> <xsd:complexContent> <xsd:extension base="beans:identifiedType"> <xsd:attribute name="nozzle" type="xsd:string"> <xsd:annotation> <xsd:documentation><![CDATA[ Interface name ]]></xsd:documentation> </xsd:annotation> </xsd:attribute> <xsd:attribute name="alias" type="xsd:string"> <xsd:annotation> <xsd:documentation><![CDATA[ Service alias grouping information ]]></xsd:documentation> </xsd:annotation> </xsd:attribute> </xsd:extension> </xsd:complexContent> </xsd:complexType> </xsd:element> <!-- org.itstack.demo.rpc.config.ProviderConfig --> <xsd:element name="provider"> <xsd:complexType> <xsd:complexContent> <xsd:extension base="beans:identifiedType"> <xsd:attribute name="nozzle" type="xsd:string"> <xsd:annotation> <xsd:documentation><![CDATA[ Interface name ]]></xsd:documentation> </xsd:annotation> </xsd:attribute> <xsd:attribute name="ref" type="xsd:string"> <xsd:annotation> <xsd:documentation><![CDATA[ Interface Implementation Class ]]></xsd:documentation> </xsd:annotation> </xsd:attribute> <xsd:attribute name="alias" type="xsd:string"> <xsd:annotation> <xsd:documentation><![CDATA[ Service alias grouping information ]]></xsd:documentation> </xsd:annotation> </xsd:attribute> </xsd:extension> </xsd:complexContent> </xsd:complexType> </xsd:element> </xsd:schema>
spring.handlers
http\://rpc.itstack.org/schema/rpc=org.itstack.demo.rpc.config.spring.MyNamespaceHandler
spring.schemas
http\://rpc.itstack.org/schema/rpc/rpc.xsd=META-INF/rpc.xsd
Test section
itstack-rpc-consumer.xml
<?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:rpc="http://rpc.itstack.org/schema/rpc" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://rpc.itstack.org/schema/rpc http://rpc.itstack.org/schema/rpc/rpc.xsd"> <!-- redis Configure and save links --> <rpc:server id="consumer_itstack" host="127.0.0.1" port="6379"/> <rpc:consumer id="consumer_helloService" nozzle="org.itstack.demo.test.service.HelloService" alias="itStackRpc"/> </beans>
itstack-rpc-provider.xml
<?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:rpc="http://rpc.itstack.org/schema/rpc" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://rpc.itstack.org/schema/rpc http://rpc.itstack.org/schema/rpc/rpc.xsd"> <rpc:provider id="provider_helloService" nozzle="org.itstack.demo.test.service.HelloService" ref="helloService" alias="itStackRpc" /> </beans>
ApiTest.java
package org.itstack.demo.test; import org.springframework.context.support.ClassPathXmlApplicationContext; /** * http://www.itstack.org * create by fuzhengwei on 2019/5/4 * This chapter mainly introduces how to read the field information of custom configuration xml file */ public class ApiTest { public static void main(String[] args) { String[] configs = {"itstack-rpc-consumer.xml", "itstack-rpc-provider.xml"}; new ClassPathXmlApplicationContext(configs); } }
test result
2019-05-07 19:44:24,805 main INFO [org.springframework.context.support.ClassPathXmlApplicationContext:prepareRefresh:510] - Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@299a06ac: startup date [Tue May 07 19:44:24 CST 2019]; root of context hierarchy 2019-05-07 19:44:24,872 main INFO [org.springframework.beans.factory.xml.XmlBeanDefinitionReader:loadBeanDefinitions:315] - Loading XML bean definitions from class path resource [itstack-rpc-consumer.xml] 2019-05-07 19:44:24,972 main INFO [org.springframework.beans.factory.xml.XmlBeanDefinitionReader:loadBeanDefinitions:315] - Loading XML bean definitions from class path resource [itstack-rpc-provider.xml] 2019-05-07 19:44:25,008 main INFO [org.springframework.beans.factory.support.DefaultListableBeanFactory:preInstantiateSingletons:577] - Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@192b07fd: defining beans [consumer_itstack,consumer_helloService,provider_helloService]; root of factory hierarchy Server information => [registry address: 127.0.0.1] [registry port: 6379] Producer Information => [Interface: org.itstack.demo.test.service.HelloService] [Mapping: helloService] [Alias: itStackRpc]