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 provides
java.rmi
Package, 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)
- create
UserService
Interface.
// The interface of the service to be published
public interface UserService extends Remote {
public String helloRmi(String name) throws RemoteException;
}
Copy the code
- create
UserServiceImpl
The implementation class
- Pay attention to,
UserServiceImpl
In addition to the implementationUserService
Interfaces, but also inheritanceUnicastRemoteObject
Class, you can think of it as a class that is published for others to call whenUserServiceImpl
After implementing this class,UserServiceImpl
It 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
- 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
- the
rmi-provider
The project ofUserService
Interface withUserServiceImpl
Implementation classes are copied to thisrmi-consumer
This step can be optimized for decoupling, we can create one morermi-resource
The project,rmi-provider
andrmi-consumer
Rely on togetherrmi-resource
Project and then put the resource files such as those used by the remote serviceUserService
Such as in thermi-resource
In the project) - 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 consumers
http + xml
To communicate.
Remote service provider implementation.
- Start by creating the remote service interface
UserService
And its implementation classesUserServiceImpl
.
- Note, use
WebService
The 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
- Publish remote services, procedures and
rmi
Similarly, you need to provide the remote service access address and the specific remote service implementation class, usedEndpoint
Of 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
- and
rmi
The 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
? wdsl
In 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.
- 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 in
bin
Directory, the name iswsimport
- 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 projectp 填wdslAddress 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 ratherjson
The same principle applies to the communication between the front and back ends of wechat applets.
- Create a
order-sys
Maven project, specified to be packaged aswar
The 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
- Provide services externally, package and publish to
Tomcat
on
@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
- Used on the service consumer side
HttpClient
To send a request, simulate a browser to send a POST/GET request.HttpClient
Encapsulates 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 used
HttpClient
Order system through accessloadOrderList2
The 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