Handwritten RPC Framework Chapter 1 Custom Configuration xml

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] 

Pay attention to bugstack wormhole stack public number to get source code and reply < RPC source code >

Keywords: Java xml Attribute Spring

Added by crishna369 on Thu, 22 Aug 2019 11:20:56 +0300