Architektura mikrousług - praktyczna architektura SOA

W tym rozdziale opracujemy aplikację opartą na CRUD z architekturą SOA. W dalszej części kolejnych rozdziałów podzielimy tę usługę na mikrousługi i poznamy podstawową różnicę między architekturą SOA a mikrousługą.

Konfiguracja i instalacja systemu

W tej sekcji zbudujemy przykładową aplikację CRUD, która zwróci obiekt JSON jako odpowiedź za każdym razem, gdy wywołasz naszą usługę. Wykorzystamy ramy Jersey, aby opracować to samo. Poniżej przedstawiono kroki konfiguracji lokalnego środowiska systemowego.

Tworzenie aplikacji CRUD

Step 1- Będziemy używać NetBeans jako środowiska programistycznego. Pobierz i zainstaluj najnowszą wersję dostępną na oficjalnej stronie NetBeanshttps://netbeans.org/downloads/.

Step 2- Otwórz swoje NetBeans IDE. Przejdź do „Plik -> Nowy projekt”. Pojawi się następujący zrzut ekranu. Wybierz „Maven” jako kategorię i wybierz „Projekt z ArchType” jako projekt i naciśnij Dalej.

Spowoduje to pobranie wszystkich plików jar wymaganych do utworzenia pierwszego projektu Maven i usługi sieci Web RESTful.

Step 3- Po naciśnięciu przycisku Dalej w poprzednim kroku pojawia się następujący zrzut ekranu. Tutaj będziesz musiał określić Archetyp Mavena.

W polu wyszukiwania wyszukaj „Jersey-archType-Webapp (2.16)” i zaznacz pole wyboru „Pokaż starsze”.

Step 4- Po wybraniu tego samego nastąpi przekierowanie do następnego ekranu. Wybierz preferowany słoik z listy i naciśnij Dalej, aby kontynuować.

Step 5- Na tym etapie musisz podać nazwę swojego projektu i jego identyfikator grupy, a także szczegóły pakietu. Po podaniu wszystkich tych informacji naciśnij Zakończ, aby kontynuować.

Step 6- Konfiguracja obszaru roboczego została zakończona. Katalog projektu będzie wyglądał następująco.

Sprawdź swój folder „Dependencies”, a zobaczysz, że Maven automatycznie pobrał wszystkie wymagane pliki jar dla tego projektu.

Step 7- Twój obszar roboczy jest skonfigurowany i możesz zacząć od kodowania. Śmiało i utwórz cztery klasy i pakiety, jak wspomniano na poniższym zrzucie ekranu. Możesz stwierdzić, że MyResource.java jest już utworzony przez Maven, ponieważ Maven jest wystarczająco inteligentny, aby wykryć, że zamierzasz zbudować własną usługę internetową.

Step 8 - Po wykonaniu powyższego kroku skonstruujemy naszą klasę POJO, czyli UserProfile.java, w następujący sposób.

package com.tutorialspoint.userprofile.Model;

import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement
public class UserProfile {
   private long ProId;
   private String FName;
   private String LName;
   private String Add;
   public UserProfile(){}
   
   public UserProfile(long Proid, String Fname, String Lname,String Add) {
      this.ProId = Proid;
      this.FName = Fname;
      this.LName = Lname;
      this.Add = Add;
   }
   public long getProId() {
      return ProId;
   }
   public void setProId(long ProId) {
      this.ProId = ProId;
   }
   public String getFName() {
      return FName;
   }
   public void setFName(String FName) {
      this.FName = FName;
   }
   public String getLName() {
      return LName;
   }
   public void setLName(String LName) {
      this.LName = LName;
   }
   public String getAdd() {
      return Add;
   }
   public void setAdd(String Add) {
      this.Add = Add;
   }
}

Step 9- Teraz stworzymy naszą klasę Database. Ponieważ jest to część materiału edukacyjnego, nie będziemy używać żadnej bazy danych jako naszej bazy danych. Będziemy używać wbudowanej pamięci Java do pracy jako nasza pamięć tymczasowa. Jak widać w poniższym zestawie kodu, użyjemy MAP jako naszej bazy danych. Wszystkie operacje usługi sieciowej, które wykonujemy, będziemy pracować na tym MAP zdefiniowanym w klasie.

package com.tutorialspoint.userprofile.DAO;

import com.tutorialspoint.userprofile.Model.UserProfile;

import java.util.HashMap;
import java.util.Map;

public class DatabaseClass {
   private static Map<Long,UserProfile> messages = new HashMap<Long,UserProfile>();
   public static Map<Long,UserProfile> getUsers() {
      return messages; 
      // Each time this method will return entire map as an instance of database
   }
}

Step 10- Teraz zbudujmy naszą klasę usług. Śmiało i skopiuj, wklej następujący zestaw kodu w klasie „ProfileService.java”. To jest klasa, w której zadeklarujemy wszystkie nasze metody usług internetowych, które mają być ujawnione światu zewnętrznemu. Musimy utworzyć jedno odwołanie do naszej DatabaseClass, tak aby nasza tymczasowa baza danych była dostępna w tej klasie.

package com.tutorialspoint.userprofile.service;

import com.tutorialspoint.userprofile.DAO.DatabaseClass;
import com.tutorialspoint.userprofile.Model.UserProfile;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

public class ProfileService {
   private Map<Long,UserProfile> Userprofiles = DatabaseClass.getUsers();
   
   // Creating some predefine profile and populating the same in the map
   public ProfileService() {
      UserProfile m1 = new UserProfile(1L,"Tutorials1","Point1","TutorialsPoint.com");
      UserProfile m2 = new UserProfile(2L,"Tutorials2","Point2","TutorialsPoint.com2");
      UserProfile m3 = new UserProfile(3L,"Tutorials3","Point3","TutorialsPoint.com3");
      UserProfile m4 = new UserProfile(4L,"Tutorials4","Point4","TutorialsPoint.com4");
      
      Userprofiles.put(1L, m1);
      Userprofiles.put(2L, m2);
      Userprofiles.put(1L, m3);
      Userprofiles.put(2L, m4);
   }
   
   //Method to fetch all profile
   public List<UserProfile> getAllProfile() {
      List<UserProfile> list = new ArrayList<UserProfile>(Userprofiles.values());
      return list;
   }  // Method to fetch only one profile depending on the ID provided
   
   public UserProfile getProfile(long id) {
      return Userprofiles.get(id);
   }  //Method to add profile
   
   public UserProfile addProfile(UserProfile UserProfile) {
      UserProfile.setProId(Userprofiles.size()+1);
      Userprofiles.put(UserProfile.getProId(), UserProfile);
      return UserProfile;
   }  //method to update Profile

   public UserProfile UpdateProfile(UserProfile UserProfile) {
      if(UserProfile.getProId()<=0) { 
         return null;
      } else { 
         Userprofiles.put(UserProfile.getProId(), UserProfile);
         return UserProfile;
      }
   } //method to delete profile
   
   public void RemoveProfile(long Id) {
      Userprofiles.remove(Id);
   }
}

Step 11 - Na tym etapie utworzymy naszą klasę zasobów, która zostanie połączona z adresem URL i wywołana zostanie odpowiednia usługa.

package com.tutorialspoint.userprofile.Resource;

import com.tutorialspoint.userprofile.Model.UserProfile;
import com.tutorialspoint.userprofile.service.ProfileService;

import java.util.List;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;

@Path("/Profile")
@Consumes(MediaType.APPLICATION_XML)
@Produces(MediaType.APPLICATION_XML)

public class ProfileResource {
   ProfileService messageService = new ProfileService();
   
   @GET
   public List<UserProfile> getProfile() {
      return messageService.getAllProfile();
   }

   @GET
   @Path("/{ProID}")
   public UserProfile getProfile(@PathParam("ProID")long Id) {
      return messageService.getProfile(Id);
   }

   @POST
   public UserProfile addProfile(UserProfile profile) {
      return messageService.addProfile(profile);
   }

   @PUT
   @Path("/{proID}")
   public UserProfile UpdateProfile(@PathParam("proID")long Id,UserProfile UserProfile) {
      UserProfile.setProId(Id);
      return messageService.UpdateProfile(UserProfile);
   }
   
   @DELETE
   @Path("/{ProID}")
   public void deleteProfile(@PathParam("ProID")long Id) {
      messageService.RemoveProfile(Id);
   }
}

Step 12- Wyczyść skompiluj projekt i uruchom go. Jeśli wszystko pójdzie dobrze, podczas uzyskiwania dostępu do przeglądarki powinieneś otrzymać następujące dane wyjściowehttp://localhost:8080/UserProfile/webapi/Profile” URL.

Możesz zobaczyć, że różne wpisy są wypełniane przy użyciu reprezentacji XML.

Różne metody można przetestować za pomocą programu Postman, stosując odpowiedni adres URL metody.

@GET method - Poniższy zrzut ekranu pokazuje, w jaki sposób możemy uzyskać pożądany wynik dla żądania get, które zwraca wszystkie dane użytkownika.

@POST- Poniższe żądanie może posłużyć do przetestowania naszej metody Post. Zwróć uwagę, jak proId został wygenerowany automatycznie.

@PUT- Ta metoda zaktualizuje wpisy. Poniższy zrzut ekranu pokazuje, jak Jersey pobiera proId z adresu URL żądania i aktualizuje tę samą odpowiedź profilu użytkownika.

W ten sam sposób możesz sprawdzić inne metody dostępne w twoich usługach internetowych.

W poprzedniej sekcji opracowaliśmy jedną usługę, która ujawni funkcjonalność CRUD. Teraz ilekroć próbujemy zaimplementować tę usługę w naszej aplikacji, musimy stworzyć klienta tej aplikacji i dołączyć go do naszej aplikacji. W tym rozdziale dowiemy się, jak zbudować tę funkcjonalność przy użyciu koncepcji mikrousług. Poniżej znajduje się schematyczne przedstawienie naszej aplikacji zbudowanej przy użyciu powyższych kroków.

Aktor powinien być punktem wyjścia dla naszej usługi. W tym przypadku „ProfileResource.java” pełni rolę aktora. Ta klasa będzie wywoływać różne metody do wykonywania różnych operacji, takich jak dodawanie, aktualizowanie i usuwanie.

Rozkład aplikacji CRUD

Zgodnie z główną zasadą mikrousług, dla każdego z modułów musimy mieć tylko jedno zadanie biznesowe, stąd jeden aktor nie powinien odpowiadać za wszystkie cztery funkcjonalności CRUD. Rozważmy następujący przykład, w którym wprowadziliśmy kilka nowych ról, tak aby koncepcyjnie było jasne, że Microservice jest architektoniczną reprezentacją SOA.

„Użytkownik główny” to użytkownik, który komunikuje się z „Kontrolerem aplikacji” w celu zaspokojenia jego potrzeb. „Kontroler aplikacji” to ten, który po prostu dzwoni do różnych „menedżerów zasobów” w zależności od żądania ze strony użytkownika końcowego. „Menedżer zasobów” wykonuje zadanie, które jest wymagane do wykonania. Rzućmy okiem na różne role różnych jednostek aplikacji.

  • End User/Main Users - Żądania niektórych zasobów do kontrolera aplikacji.

  • Application - Odbiera żądanie i przekazuje je do określonego menedżera zasobów.

  • Resource Manager - Wykonuje rzeczywistą pracę polegającą na aktualizowaniu, usuwaniu i dodawaniu użytkowników.

Zobacz, jak całkowita odpowiedzialność jednej klasy jest rozdzielana między różne inne klasy.