In the evolution of single architecture to distributed architecture, cross-process communication becomes a necessity. If Socket is used to communicate directly, it will make programming very complicated.

In 1984, Bruce Jay Nelson proposed a standard for cross-process communication, commonly known as Remote Procedure Call (RPC). All subsequent RPC frameworks are designed using this standard.

The concept of RPC is very simple. When a client wants to make a call, it actually makes a call through the local caller’s Stub, which encodes the methods and parameters that the client needs to execute over the agreed protocol and transmits them to the server over the network. The server receives the information and executes the real method, which then transmits the results to the client over the network.

Web Services description

Web Services are a type of RPC. Web Services use SOAP as a transport protocol, WSDL as a description language for Services, and UDDI as a service registry discovery (though it has not evolved).

Although the protocols for Web Services have not been updated since 2007, they are still heavily used by some financial institutions, such as banks.

There are many frameworks for WebService, such as Axis2, XFire, CXF and so on.

Apache Cxf is one of the best and most dynamic, and the Cxf framework is not only a Web Services framework, but also can be used to implement RESTful Services.

CXF implements a simple Web service

Implementing Web Services using CXF is very simple.

A complete Web Services service is divided into server-side and server-side, first look at the server-side code implementation.

Start by creating a Maven project that introduces the following dependencies in POM.xml:

<dependency> <groupId>org.apache.cxf</groupId> <artifactId>cxf-rt-frontend-jaxws</artifactId> < version > 3.4.0 - the SNAPSHOT < / version > < / dependency > < the dependency > < groupId >. Org. Apache CXF < / groupId > < artifactId > CXF - rt - transports - HTTP < / artifactId > < version > 3.4.0 - the SNAPSHOT < / version > < / dependency > < the dependency > <groupId>org.apache.cxf</groupId> <artifactId>cxf-rt-transports-http-jetty</artifactId> < version > 3.4.0 - the SNAPSHOT < / version > < / dependency >Copy the code

Then you can start writing code. First you need to define an API that can be exposed:

import javax.jws.WebService;

@WebService
public interface CxfDemoService {
    String hello(String name);
}
Copy the code

The @webService annotation indicates that this is an external interface. Then you need to implement the concrete business logic:

public class CxfDemoServiceImpl implements CxfDemoService{
    @Override
    public String hello(String name) {
        return "hello "+ name; }}Copy the code

Just like implementing a normal class, there is nothing special about it. Then create a service:

CxfDemoServiceImpl implementor = new CxfDemoServiceImpl();
JaxWsServerFactoryBean svrFactory = new JaxWsServerFactoryBean();
svrFactory.setServiceClass(CxfDemoService.class);
svrFactory.setAddress("http://localhost:9000/cxfDemoService");
svrFactory.setServiceBean(implementor);
svrFactory.create();
Copy the code

Code is very simple, we address the service is set to http://localhost:9000/cxfDemoService, as long as the port number don’t conflict, this address can be defined according to need. That’s all the code on the server side, just put it in a main method and start it.

We talked about Web Servces using WSDL as the service description language. What do you think about that? Write good service is to provide call for others, then people need to know what can I do for this interface parameters, return what is the result of this time, just visit http://localhost:9000/cxfDemoService? WSDL, after the service address? WSDL will do, and returns the following:

<wsdl:definitions xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:tns="http://cxf.rayjun.cn/" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:ns1="http://schemas.xmlsoap.org/soap/http" name="CxfDemoServiceService" targetNamespace="http://cxf.rayjun.cn/"> <wsdl:types> <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:tns="http://cxf.rayjun.cn/" ElementFormDefault ="unqualified" targetNamespace="http://cxf.rayjun.cn/" version="1.0"> <xs: Element name="hello" type="tns:hello"/> <xs:element name="helloResponse" type="tns:helloResponse"/> <xs:complexType name="hello"> <xs:sequence> <xs:element minOccurs="0" name="arg0" type="xs:string"/> </xs:sequence> </xs:complexType> <xs:complexType name="helloResponse"> <xs:sequence> <xs:element minOccurs="0" name="return" type="xs:string"/> </xs:sequence> </xs:complexType> </xs:schema> </wsdl:types> <wsdl:message name="helloResponse"> <wsdl:part element="tns:helloResponse" name="parameters"> </wsdl:part> </wsdl:message> <wsdl:message name="hello"> <wsdl:part element="tns:hello" name="parameters"> </wsdl:part> </wsdl:message> <wsdl:portType name="CxfDemoService"> <wsdl:operation name="hello"> <wsdl:input message="tns:hello" name="hello"> </wsdl:input> <wsdl:output message="tns:helloResponse" name="helloResponse"> </wsdl:output> </wsdl:operation> </wsdl:portType> <wsdl:binding name="CxfDemoServiceServiceSoapBinding" type="tns:CxfDemoService"> <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/> <wsdl:operation name="hello"> <soap:operation soapAction="" style="document"/> <wsdl:input name="hello"> <soap:body use="literal"/> </wsdl:input> <wsdl:output name="helloResponse">  <soap:body use="literal"/> </wsdl:output> </wsdl:operation> </wsdl:binding> <wsdl:service name="CxfDemoServiceService">  <wsdl:port binding="tns:CxfDemoServiceServiceSoapBinding" name="CxfDemoServicePort"> <soap:address location="http://localhost:9000/cxfDemoService"/> </wsdl:port> </wsdl:service> </wsdl:definitions>Copy the code

The result is an XML document that describes all the information about the service through WSDL, and details about the parameters needed to invoke the service and the returned results can be found in this document.

Now that the server-side code is done, we need to write the client-side code. The client-side code is also very simple:

JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean();
factory.setServiceClass(CxfDemoService.class);
factory.setAddress("http://localhost:8080/CxfDemoService");
CxfDemoService client = (CxfDemoService) factory.create();
String reply = client.hello("Rayjun");
System.out.println("Server : " + reply); // Server: hello rayjun
Copy the code

The above code is crude and can easily become unmaintainable if developed this way, a problem easily solved by organizing the code using Spring.

CXF integrates with Spring

CXF can work seamlessly with Spring by introducing the following Spring dependencies:

< the dependency > < groupId > org. Springframework < / groupId > < artifactId > spring - web < / artifactId > < version > 5.2.5. RELEASE < / version >  </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> < version > 5.2.5. RELEASE < / version > < / dependency >Copy the code

Then create the configuration file for the Spring container:

<? The 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:jaxws="http://cxf.apache.org/jaxws" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd"> <import resource="classpath:META-INF/cxf/cxf.xml"/> <import resource="classpath:META-INF/cxf/cxf-servlet.xml"/> <jaxws:endpoint id="rmsEngineService" implementor="cn.rayjun.cxf.CxfDemoServiceImpl" address="/CxfDemoService"/> </beans>Copy the code

Use the CXF default configuration file directly in the configuration file, and use JAXWS to define the interface to the service. Jax-ws is an implementation of Web Services in J2EE. Jax-rs is also a part of J2EE Web Services and is a RESTful API. We are using JAX-WS here.

Add the configuration file to web.xml:

<! DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc., / / DTD Web Application / 2.3 / EN "" http://java.sun.com/dtd/web-app_2_3.dtd" > < Web - app > < context - param > <param-name>contextConfigLocation</param-name> <param-value>classpath:applicationContext.xml</param-value> </context-param> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <servlet> <servlet-name>CXFServlet</servlet-name> <servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class> <load-on-startup>2</load-on-startup> </servlet> <servlet-mapping> <servlet-name>CXFServlet</servlet-name> <url-pattern>/*</url-pattern> </servlet-mapping> </web-app>Copy the code

You can then package the application into a Web container. For testing purposes, you can also run the project directly using Maven’s Jetty plugin, which is configured as follows:

<plugin> <groupId>org.eclipse.jetty</groupId> <artifactId>jetty-maven-plugin</artifactId> < version > 9.4.29. V20200521 < / version > < configuration > < scanIntervalSeconds > 10 < / scanIntervalSeconds > <war>${project.basedir}/target/cxfdemo.war</war> <webApp> <contextPath>/</contextPath> </webApp> <httpConnector> <port>8080</port> </httpConnector> </configuration> </plugin>Copy the code

Then using MVN Jetty :run-war, the server is up and running, and the client code does not need to change, so it can easily access the service.

At this point, the scaffolding of the service is up with CXF, and you can add additional configurations or start developing business logic as needed.

Follow the wechat official account and chat about other things