Berbagi teknologi

Demo mulai cepat rmi terintegrasi Spring Boot

2024-07-12

한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina

1.Apa itu RMI?

RMI (Remote Method Invocation) adalah pemanggilan metode jarak jauh, yang merupakan ide dasar dalam pemrograman terdistribusi. Ada banyak teknologi untuk mengimplementasikan pemanggilan metode jarak jauh, seperti CORBA dan WebService, keduanya tidak bergantung pada setiap bahasa pemrograman. Java RMI adalah mekanisme pemanggilan metode jarak jauh yang dirancang khusus untuk lingkungan Java. Ini adalah Java API yang digunakan untuk mengimplementasikan panggilan prosedur jarak jauh (RPC) yang dapat secara langsung mengirimkan objek Java berseri dan mengumpulkan pengumpulan sampah. Implementasinya bergantung pada JVM, sehingga mendukung panggilan dari satu JVM ke JVM lainnya. Di Java RMI, server jarak jauh mengimplementasikan metode Java tertentu dan menyediakan antarmuka. Klien hanya perlu menyediakan parameter yang sesuai sesuai dengan definisi kelas antarmuka untuk memanggil metode jarak jauh. Objek dikodekan dan ditransmisikan melalui serialisasi. Jadi eksploitasi kerentanan deserialisasi yang biasa sering kali melibatkan RMI, dan itulah maksudnya. Protokol komunikasi yang diandalkan RMI adalah JRMP (Java Remote Message Protocol, Java Remote Message Exchange Protocol). Protokol ini disesuaikan untuk Java dan mengharuskan server dan klien harus ditulis dalam Java.

proses interaktif

arsitektur_rmi

pendaftaran

Proses interaksi dapat diringkas secara singkat sebagai:

  1. Pertama, mulai layanan RMI Registry. Saat memulai, Anda dapat menentukan port tempat layanan mendengarkan, atau Anda dapat menggunakan port default (1099);
  2. Kedua, sisi server pertama-tama membuat instance kelas implementasi yang menyediakan layanan secara lokal, dan kemudian mendaftarkan kelas implementasi yang baru saja dibuat instance-nya ke RMI Registry melalui metode bind atau rebind dari kelas Penamaan/Konteks/Registry yang disediakan oleh RMI dan memaparkannya ke luar nama dunia;
  3. Terakhir, klien menggunakan antarmuka lokal dan nama yang dikenal (yaitu, nama yang diekspos oleh RMI Registry) untuk mendapatkan kelas implementasi dari Layanan RMI menggunakan metode pencarian kelas Penamaan/Konteks/Registry yang disediakan oleh RMI. Dengan cara ini, meskipun tidak ada kelas implementasi dari kelas ini secara lokal, semua metode ada di antarmuka, dan metode objek dapat dipanggil dari jarak jauh;

2. Rekayasa kode

Tujuan eksperimental

Bereksperimenlah dengan layanan rmi sederhana dan panggil melalui klien

server rmi

Ini adalah proyek sisi server yang terutama menyediakan antarmuka layanan rmi

pom.xml
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <project xmlns="http://maven.apache.org/POM/4.0.0"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  5. <parent>
  6. <artifactId>rmi</artifactId>
  7. <groupId>com.et</groupId>
  8. <version>1.0-SNAPSHOT</version>
  9. </parent>
  10. <modelVersion>4.0.0</modelVersion>
  11. <artifactId>rmi-server</artifactId>
  12. <properties>
  13. <maven.compiler.source>8</maven.compiler.source>
  14. <maven.compiler.target>8</maven.compiler.target>
  15. </properties>
  16. <dependencies>
  17. <dependency>
  18. <groupId>org.springframework.boot</groupId>
  19. <artifactId>spring-boot-starter-web</artifactId>
  20. </dependency>
  21. <dependency>
  22. <groupId>org.springframework.boot</groupId>
  23. <artifactId>spring-boot-autoconfigure</artifactId>
  24. </dependency>
  25. <dependency>
  26. <groupId>org.springframework.boot</groupId>
  27. <artifactId>spring-boot-starter-test</artifactId>
  28. <scope>test</scope>
  29. </dependency>
  30. <dependency>
  31. <groupId>org.springframework.boot</groupId>
  32. <artifactId>spring-boot-starter-data-jpa</artifactId>
  33. </dependency>
  34. <dependency>
  35. <groupId>com.et</groupId>
  36. <artifactId>rmi-common</artifactId>
  37. <version>1.0-SNAPSHOT</version>
  38. </dependency>
  39. <dependency>
  40. <groupId>com.h2database</groupId>
  41. <artifactId>h2</artifactId>
  42. <version>1.4.200</version>
  43. </dependency>
  44. </dependencies>
  45. </project>
konfigurasi
  1. package com.et.rmi.server.config;
  2. import com.et.rmi.server.dao.CustomerRepository;
  3. import com.et.rmi.server.model.Customer;
  4. import com.et.rmi.server.service.CustomerServiceImpl;
  5. import om.et.rmi.common.CustomerService;
  6. import org.springframework.boot.ApplicationArguments;
  7. import org.springframework.boot.ApplicationRunner;
  8. import org.springframework.context.annotation.Bean;
  9. import org.springframework.remoting.rmi.RmiServiceExporter;
  10. import org.springframework.stereotype.Component;
  11. import java.util.logging.Logger;
  12. @Component
  13. public class RmiServerApplicationRunner implements ApplicationRunner {
  14. private CustomerRepository repository;
  15. private CustomerServiceImpl customerService;
  16. private final Logger log = Logger.getLogger(this.getClass().getName());
  17. public RmiServerApplicationRunner(CustomerServiceImpl customerService) {
  18. this.customerService = customerService;
  19. }
  20. @Override
  21. public void run(ApplicationArguments args) throws Exception {
  22. Customer customer1 = new Customer("John", "Smith", "123-456-7890");
  23. customerService.saveCustomer(customer1);
  24. customerService.getCustomers().forEach(System.out::println);
  25. }
  26. @Bean
  27. public RmiServiceExporter customerServiceExporter() {
  28. RmiServiceExporter customerServiceExporter = new RmiServiceExporter();
  29. customerServiceExporter.setRegistryPort(1199);
  30. customerServiceExporter.setServiceName("customerService");
  31. customerServiceExporter.setServiceInterface(CustomerService.class);
  32. customerServiceExporter.setService(customerService);
  33. log.info("Started RMI Server");
  34. return customerServiceExporter;
  35. }
  36. }
melayani
  1. package com.et.rmi.server.service;
  2. import com.et.rmi.server.dao.CustomerRepository;
  3. import com.et.rmi.server.mapper.CustomerMapper;
  4. import com.et.rmi.server.model.Customer;
  5. import om.et.rmi.common.CustomerDTO;
  6. import om.et.rmi.common.CustomerService;
  7. import org.springframework.stereotype.Service;
  8. import java.util.List;
  9. @Service
  10. public class CustomerServiceImpl implements CustomerService {
  11. private CustomerRepository repository;
  12. public CustomerServiceImpl(CustomerRepository repository) {
  13. this.repository = repository;
  14. }
  15. @Override
  16. public CustomerDTO getCustomer(long id) {
  17. Customer customer = repository.findById(id).orElseThrow(IllegalArgumentException::new);
  18. CustomerMapper mapper = new CustomerMapper();
  19. CustomerDTO dto = mapper.mapToDTO(customer);
  20. System.out.println(dto);
  21. return dto;
  22. }
  23. public List<Customer> getCustomers() {
  24. return (List<Customer>)repository.findAll();
  25. }
  26. public void saveCustomer(Customer customer) {
  27. repository.save(customer);
  28. }
  29. }
jalan
  1. package com.et.rmi.server.dao;
  2. import com.et.rmi.server.model.Customer;
  3. import org.springframework.data.repository.CrudRepository;
  4. import org.springframework.stereotype.Repository;
  5. import java.util.Optional;
  6. @Repository
  7. public interface CustomerRepository extends CrudRepository<Customer, Long> {
  8. Optional<Customer> findById(long id);
  9. }
pemeta
  1. package com.et.rmi.server.mapper;
  2. import com.et.rmi.server.model.Customer;
  3. import om.et.rmi.common.CustomerDTO;
  4. public class CustomerMapper {
  5. public CustomerMapper() {
  6. }
  7. public CustomerDTO mapToDTO(Customer customer){
  8. CustomerDTO dto = new CustomerDTO();
  9. dto.setFirstName(customer.getFirstName());
  10. dto.setLastName(customer.getLastName());
  11. dto.setSocialSecurityCode(customer.getSocialSecurityCode());
  12. return dto;
  13. }
  14. }
model
  1. package com.et.rmi.server.model;
  2. import javax.persistence.*;
  3. @Entity
  4. @SequenceGenerator(name = "CUST_SEQ", initialValue = 1_000_001)
  5. public class Customer {
  6. @Id
  7. @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "CUST_SEQ")
  8. private long id;
  9. private String firstName;
  10. private String lastName;
  11. private String socialSecurityCode;
  12. public Customer() {
  13. }
  14. public Customer(String firstName, String lastName, String socialSecurityCode) {
  15. this.firstName = firstName;
  16. this.lastName = lastName;
  17. this.socialSecurityCode = socialSecurityCode;
  18. }
  19. public long getId() {
  20. return id;
  21. }
  22. public String getFirstName() {
  23. return firstName;
  24. }
  25. public void setFirstName(String firstName) {
  26. this.firstName = firstName;
  27. }
  28. public String getLastName() {
  29. return lastName;
  30. }
  31. public void setLastName(String lastName) {
  32. this.lastName = lastName;
  33. }
  34. public String getSocialSecurityCode() {
  35. return socialSecurityCode;
  36. }
  37. public void setSocialSecurityCode(String socialSecurityCode) {
  38. this.socialSecurityCode = socialSecurityCode;
  39. }
  40. @Override
  41. public String toString() {
  42. return "Customer{" +
  43. "id=" + id +
  44. ", firstName='" + firstName + ''' +
  45. ", lastName='" + lastName + ''' +
  46. ", socialSecurityCode='" + socialSecurityCode + ''' +
  47. '}';
  48. }
  49. }
properti aplikasi
spring.jpa.show-sql=false
spring.jpa.hibernate.ddl-auto=update
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.H2Dialect

klien rmi

Ini adalah proyek klien, yang sebagian besar memanggil layanan rmi jarak jauh.

pom.xml
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <project xmlns="http://maven.apache.org/POM/4.0.0"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  5. <parent>
  6. <artifactId>rmi</artifactId>
  7. <groupId>com.et</groupId>
  8. <version>1.0-SNAPSHOT</version>
  9. </parent>
  10. <modelVersion>4.0.0</modelVersion>
  11. <artifactId>rmi-cilent</artifactId>
  12. <properties>
  13. <maven.compiler.source>8</maven.compiler.source>
  14. <maven.compiler.target>8</maven.compiler.target>
  15. </properties>
  16. <dependencies>
  17. <dependency>
  18. <groupId>org.springframework.boot</groupId>
  19. <artifactId>spring-boot-starter-web</artifactId>
  20. </dependency>
  21. <dependency>
  22. <groupId>org.springframework.boot</groupId>
  23. <artifactId>spring-boot-autoconfigure</artifactId>
  24. </dependency>
  25. <dependency>
  26. <groupId>org.springframework.boot</groupId>
  27. <artifactId>spring-boot-starter-test</artifactId>
  28. <scope>test</scope>
  29. </dependency>
  30. <dependency>
  31. <groupId>com.et</groupId>
  32. <artifactId>rmi-common</artifactId>
  33. <version>1.0-SNAPSHOT</version>
  34. </dependency>
  35. </dependencies>
  36. </project>
pengontrol
  1. package com.et.rmi.client.controller;
  2. import om.et.rmi.common.CustomerDTO;
  3. import om.et.rmi.common.CustomerService;
  4. import org.springframework.http.MediaType;
  5. import org.springframework.http.ResponseEntity;
  6. import org.springframework.remoting.rmi.RmiProxyFactoryBean;
  7. import org.springframework.stereotype.Controller;
  8. import org.springframework.web.bind.annotation.PathVariable;
  9. import org.springframework.web.bind.annotation.RequestMapping;
  10. import org.springframework.web.bind.annotation.RequestMethod;
  11. @Controller
  12. @RequestMapping(value = "customers")
  13. public class CustomerController {
  14. private RmiProxyFactoryBean proxyFactoryBean;
  15. public CustomerController(RmiProxyFactoryBean proxyFactoryBean) {
  16. this.proxyFactoryBean = proxyFactoryBean;
  17. }
  18. @RequestMapping(value = "{id}", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
  19. public ResponseEntity<CustomerDTO> getCustomer(@PathVariable long id) {
  20. CustomerService service = (CustomerService) proxyFactoryBean.getObject();
  21. CustomerDTO dto = service.getCustomer(id);
  22. return ResponseEntity.ok(dto);
  23. }
  24. }
konfigurasi
  1. package com.et.rmi.client.config;
  2. import om.et.rmi.common.CustomerService;
  3. import org.springframework.context.annotation.Bean;
  4. import org.springframework.remoting.rmi.RmiProxyFactoryBean;
  5. import org.springframework.stereotype.Component;
  6. import org.springframework.util.StringUtils;
  7. import java.util.logging.Logger;
  8. @Component
  9. public class Config {
  10. public final Logger log = Logger.getLogger(this.getClass().getName());
  11. @Bean
  12. public RmiProxyFactoryBean proxyFactoryBean() {
  13. String remoteHost = System.getProperty("RMI_SERVER_HOST");
  14. if(StringUtils.isEmpty(remoteHost)){
  15. remoteHost="127.0.0.1";
  16. }
  17. String rmiHost = String.format("rmi://%s:1199/customerService", remoteHost);
  18. log.info("RMI Host name is " + rmiHost);
  19. RmiProxyFactoryBean proxy = new RmiProxyFactoryBean();
  20. proxy.setServiceInterface(CustomerService.class);
  21. proxy.setServiceUrl(rmiHost);
  22. proxy.afterPropertiesSet();
  23. return proxy;
  24. }
  25. }
properti aplikasi
server.port=8081

rmi-umum

Ini adalah paket publik yang harus dirujuk oleh server dan klien.

  1. package om.et.rmi.common;
  2. import java.io.Serializable;
  3. public class CustomerDTO implements Serializable {
  4. private String firstName;
  5. private String lastName;
  6. private String socialSecurityCode;
  7. public CustomerDTO() {
  8. }
  9. public String getFirstName() {
  10. return firstName;
  11. }
  12. public void setFirstName(String firstName) {
  13. this.firstName = firstName;
  14. }
  15. public String getLastName() {
  16. return lastName;
  17. }
  18. public void setLastName(String lastName) {
  19. this.lastName = lastName;
  20. }
  21. public String getSocialSecurityCode() {
  22. return socialSecurityCode;
  23. }
  24. public void setSocialSecurityCode(String socialSecurityCode) {
  25. this.socialSecurityCode = socialSecurityCode;
  26. }
  27. @Override
  28. public String toString() {
  29. final StringBuffer sb = new StringBuffer("CustomerDTO{");
  30. sb.append("firstName='").append(firstName).append(''');
  31. sb.append(", lastName='").append(lastName).append(''');
  32. sb.append(", socialSecurityCode='").append(socialSecurityCode).append(''');
  33. sb.append('}');
  34. return sb.toString();
  35. }
  36. }
  1. package om.et.rmi.common;
  2. public interface CustomerService {
  3. CustomerDTO getCustomer(long id);
  4. }

Di atas hanyalah beberapa kode kunci. Untuk semua kode, silakan lihat repositori kode di bawah ini.

penyimpanan kode

3. Tes

  • Mulai layanan server rmi
  • Mulai layanan rmi-klien
  • Kunjungi http://127.0.0.1:8081/customers/1000001
  • kembali{"firstName":"John","lastName":"Smith","socialSecurityCode":"123-456-7890"}

4. Kutipan