This article will demonstrate four RPC remote invocation methods through specific remote service publishing and consumption cases.

I. Remote service production and consumption through RMI

  • Java itself providesjava.rmiPackage, convenient for developers to deploy and consume remote services, the following will be explained through specific cases.

Remote service provider implementation.

Creating an RMI-Provider Project (Maven)

  1. createUserServiceInterface.
// The interface of the service to be published
public interface UserService extends Remote {
    public String helloRmi(String name) throws RemoteException;
}
Copy the code
  1. createUserServiceImplThe implementation class
  • Pay attention to,UserServiceImplIn addition to the implementationUserServiceInterfaces, but also inheritanceUnicastRemoteObjectClass, you can think of it as a class that is published for others to call whenUserServiceImplAfter implementing this class,UserServiceImplIt can be published for others to call.
// The implementation class of the service to be published
public class UserServiceImpl extends UnicastRemoteObject implements UserService {
    public UserServiceImpl(a) throws RemoteException {
        super(a); }public String helloRmi(String name) throws RemoteException {
        return "hello "+ name; }}Copy the code
  1. Publishing remote Services
public static void main(String[] args) {
    try {
        // The remote service is published
        LocateRegistry.createRegistry(8888);// Publish the remote service locally on port 8888
        String name = "rmi://localhost:8888/rmi";// The url to which the published remote service is accessed
        UserService userService = new UserServiceImpl();// Create a remote object that provides a specific service
        Naming.bind(name, userService);// Bind a URL to the remote service
        System.out.println("-- PUBLISHED RMI remote service --");
    } catch(Exception e) { e.printStackTrace(); }}Copy the code

Remote service consumer implementation

Create the RMI-Consumer project

  1. thermi-providerThe project ofUserServiceInterface withUserServiceImplImplementation classes are copied to thisrmi-consumerThis step can be optimized for decoupling, we can create one morermi-resourceThe project,rmi-providerandrmi-consumerRely on togetherrmi-resourceProject and then put the resource files such as those used by the remote serviceUserServiceSuch as in thermi-resourceIn the project)
  2. A remote service consumer invokes a remote service.
public static void main(String[] args) {
    try {
        Publish the access URL for the remote service
        String name = "rmi://localhost:8888/rmi";
        // Obtain the proxy object of the remote service by publishing the URL of the remote service
        UserService userService = (UserService) Naming.lookup(name);
        System.out.println("Proxy object for the obtained remote service :" + userService.getClass().getName());
        String result = userService.helloRmi("rmi");// Get the result of the remote method call
        System.out.println("result: " + result);

    }catch(Exception e) { e.printStackTrace(); }}// Finally output$Proxy0 result: hello rmiCopy the code
  • From the final output we see that the obtained remote service object is dynamically generated by the proxy.

 

2. Realize the production and consumption of remote service through WebService

  • WebService protocol is a concrete implementation of RPC, which is passed by service providers and consumershttp + xmlTo communicate.

Remote service provider implementation.

  1. Start by creating the remote service interfaceUserServiceAnd its implementation classesUserServiceImpl.
  • Note, useWebServiceThe remote service needs to be annotated@WebService
@WebService
public interface UserService {
    public String sayHello(String name);
}

@WebService
public class UserServiceImpl implements UserService {
    @Override
    public String sayHello(String name) {
        return "hello " + name + "~"; }}Copy the code
  1. Publish remote services, procedures andrmiSimilarly, you need to provide the remote service access address and the specific remote service implementation class, usedEndpointOf the classpublish()Method to publish, which is packaged in the JDK.
public class WsProviderApp {
    public static void main(String[] args) {
        // Access address of the published WebService
        String address = "http://localhost:9999/ws";
        // Create a remote service object
        UserService userService = new UserServiceImpl();
        // Publish the service
        Endpoint.publish(address, userService);
        System.out.println("Remote services have been released..."); }}Copy the code

View the remote service document WDSL

  • andrmiThe difference is that after a WebService is published, the caller can initiate a call to the remote service by looking at its documentation.
  • You can view this by entering the remote service’s access address in your browser plus? wdslIn this case, for examplehttp://localhost:9999/ws?wsdl
  • Note that the WDSL document needs to be parsed with a tool when the client invokes the remote method and the tool class for invoking the remote method is obtained. See the next paragraph for details.

Remote service consumer implementation.

  1. First, we get the utility class to call the remote service from the documentation. The JDK has wrapped the obtained utility for us, which is inbinDirectory, the name iswsimport
  2. On the cli, enter the parse command
wsimport -keep -d C:\githubRepositories\shopping\ws-consumer\src\main\java -p com.shenghao.client http://localhost:9999/ws? wsdlExplanation:1. Wsimport is the name of the command2-keep is used to keep the generated class, otherwise it would only be generatedclassThe file 3....dFollow this with the absolute path 4. - to the package where the utility classes are stored in the projectpwdslAddress of documentCopy the code


5. You can see that after the command is executed, a bunch of related classes appear in the specified package. The most directly called class is UserServiceImplService. The following demonstrates the call to the remote method.

public static void main(String[] args) {
    // Create a service object
    UserServiceImplService service = new UserServiceImplService();
    // Get the proxy object for the remote service
    UserServiceImpl userService = service.getUserServiceImplPort();
    System.out.println(userService.getClass().getName());
    // call the methods of the remote service object
    String result = userService.sayHello("Charcoal roasted oyster");
    System.out.println(result);
}

// Result outputCom.sun.proxy.$Proxy32 Hello Charcoal roasted oyster ~Copy the code

Remote service production and consumption through HttpClient

  • Let’s do another example here. Suppose you have a user system and an order system, and you want to implement the user system to access the order system to obtain order information for a user.

Remote service provider implementation

  • The process of providing a remote service is similar to responding to a Web request, except that the response is not<html>Tag, but ratherjsonThe same principle applies to the communication between the front and back ends of wechat applets.
  1. Create aorder-sysMaven project, specified to be packaged aswarThe package.
Click here to view the POM.xml file for general operations

<properties> <! RELEASE</spring.version> <jstl.version>1.2</jstl.version> < servlet - API version > 2.5 < / servlet - API. Version > < JSP - API. Version > 2.0 < / JSP - API. Version > < Jackson version > 2.9.0 < / Jackson version > < / properties > < dependencies > <! -- JSP dependencies --> <! -- Servlet dependencies --> <! --> <dependency> <groupId> JSTL </groupId> <artifactId> JSTL </artifactId> <version>${jstl.version}</version> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>servlet-api</artifactId> <version>${servlet-api.version}</version> <scope>provided</scope> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>jsp-api</artifactId> <version>${jsp-api.version}</version> <scope>provided</scope> </dependency> <! --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>${jackson.version}</version> </dependency> </dependencies> <build> <finalName>order</finalName> <plugins> <! Maven </groupId> <artifactId> tomcat7-plugin </artifactId> <version>2.2</version> <configuration> <path>/ ORDER </path> <port>7070</port> </configuration> </plugin> </plugins> </build></code></p>Copy the code


2. Create the order class

public class Order {
    private String id;
    private Double total;
    private String date;

    //get / set ...
}
Copy the code
  1. Provide services externally, package and publish toTomcaton
@Controller
public class OrderController {
    /** * Receive HTTP request, respond to order collection, asynchronous response * serialize list collection to JSON string response *@param uid
     * @return* /
    @RequestMapping("/loadOrderList2")
    @ResponseBody
    public List<Order> loadOrderList2(String uid){
        System.out.println("uid: " + uid);

        // Simulate order data
        Order o1 = new Order();
        o1.setId("111");
        o1.setTotal(333.33);
        o1.setDate("2019-4-29");

        Order o2 = new Order();
        o2.setId("222");
        o2.setTotal(444.44);
        o2.setDate("2019-5-29");

        Order o3 = new Order();
        o3.setId("333");
        o3.setTotal(555.55);
        o3.setDate("2019-6-29");

        List<Order> list = new ArrayList<>();
        list.add(o1);
        list.add(o2);
        list.add(o3);

        returnlist; }}Copy the code

Remote service consumer implementation

  1. Used on the service consumer sideHttpClientTo send a request, simulate a browser to send a POST/GET request.HttpClientEncapsulates the details of stitching a request for us, making it easy to send a request.
public static void main(String[] args) throws IOException {
    // The address to send remote HTTP requests
    String url = "http://localhost:7070/order/loadOrderList2";
    // Create an HttpClient object
    CloseableHttpClient client = HttpClients.createDefault();
    // Create an HttpPost object and send a POST request
    HttpPost method = new HttpPost(url);
    // Encapsulate the parameters sent to the service provider
    NameValuePair id = new BasicNameValuePair("uid"."10001");
    List<NameValuePair> params = new ArrayList<>();
    params.add(id);
    // Encapsulate the request body data
    method.setEntity(new UrlEncodedFormEntity(params, "UTF-8"));
    // Send a specific HTTP request
    HttpResponse response = client.execute(method);

    // Get specific data about the service provider's response
    HttpEntity entity = response.getEntity();
    // Get the HTTP response body
    InputStream is = entity.getContent();

    int len = 0;
    char[] buf = new char[1024];
    // Use character stream reading
    InputStreamReader reader = new InputStreamReader(is);
    StringBuffer sb = new StringBuffer();
    while((len = reader.read(buf)) ! = -1){
        sb.append(String.valueOf(buf, 0, len));
    }
    System.out.println(sb);

    // Parse the returned JSON string into an Order collection
    List<Order> list = JSON.parseArray(sb.toString(), Order.class);
    for(Order o : list){
        System.out.println(o.getId() + "\t" + o.getTotal() + "\t"+ o.getDate()); }}Copy the code

 

Production and consumption of remote services via spring's RestTemplate

  • Through a red envelope system and order system to demonstrate, the red envelope system access to the order system, obtain a user's order information, distributed red envelopes.
  • The order system continues to be usedHttpClientOrder system through accessloadOrderList2The order collection () method returns a Json string.

Remote service consumer implementation.

@Controller
public class RedController {
    // Inject the RestTemplate object provided by Spring
    @Autowired
    private RestTemplate restTemplate;
    /** * sends a remote HTTP request, consuming the HTTP service * to get a collection of order objects */
    @RequestMapping("/loadOrderList3")
    @ResponseBody
    public List<ResponseEntity<Order[]>> loadOrderList3(String uid){
        // Send the URL of the remote HTTP request
        String url = "http://localhost:7070/order/loadOrderList2";
        // Parameters to be sent to the remote service
        MultiValueMap<String, Object> params = new LinkedMultiValueMap<>();
        params.add("uid", uid);

        // Send a POST request through the RestTemplate object
        ResponseEntity<Order[]> entitys = restTemplate.postForEntity(url, params, Order[].class);

        // View the status code of the response
        System.out.println(entitys.getStatusCodeValue());

        // View the response header
        HttpHeaders headMap = entitys.getHeaders();
        for(Map.Entry<String, List<String>> m : headMap.entrySet()){
            System.out.println(m.getKey() + ":" + m.getValue());
        }

        returnArrays.asList(entitys); }}Copy the code