微服务架构 - SOA 实践
在本章中,我们将开发一个基于 SOA 架构的 CRUD 应用程序。在后面的章节中,我们会将这个服务分解为微服务,并了解SOA和微服务架构之间的基本区别。
系统配置和设置
在本节中,我们将构建一个示例 CRUD 应用程序,每当我们调用服务时,它将返回一个 JSON 对象作为响应。我们将使用 Jersey 框架来开发它。以下是设置本地系统环境的步骤。
开发 CRUD 应用程序
步骤 1 - 我们将使用 NetBeans 作为开发 IDE。请在 NetBeans 官方网站https://netbeans.org/downloads/上下载并安装最新版本。
步骤 2 - 打开 NetBeans IDE。转到“文件->新建项目”。弹出以下屏幕截图。选择“Maven”作为类别,然后选择“Project from ArchType”作为项目,然后单击“下一步”。
这将下载创建您的第一个 Maven 项目和 RESTful Web 服务所需的所有 jar 文件。
步骤 3 - 在上一步中点击“下一步”按钮后,将显示以下屏幕截图。在这里,您必须指定 Maven 原型。
在搜索框中,搜索“Jersey-archType-Webapp(2.16)”并选中“显示旧版本”复选框。
步骤 4 - 选择相同内容后,您将被重定向到以下屏幕。从列表中选择首选 jar,然后单击“下一步”继续。
步骤 5 - 在此步骤中,您需要提供项目名称及其组 ID 以及包详细信息。提供所有这些信息后,单击“完成”继续。
步骤 6 - 您已完成工作区设置。项目目录如下所示。
查看你的“Dependencies”文件夹,你会发现Maven已经自动下载了该项目所需的所有jar文件。
步骤 7 - 您的工作区已设置完毕,您可以开始编码。继续创建四个类和包,如下面的屏幕截图所示。您可以发现 MyResource.java 已经由 Maven 创建,因为 Maven 足够聪明,可以检测到您将要构建自己的 Web 服务。
步骤 8 - 完成上述步骤后,我们将构造 POJO 类 UserProfile.java,如下所示。
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; } }
步骤 9 - 现在我们将创建数据库类。由于这是学习材料的一部分,我们不会使用任何 DB 作为我们的数据库。我们将使用内置的 Java 内存作为临时内存。正如您在下面的代码集中看到的,我们将使用 MAP 作为数据库。我们执行的所有 Web 服务操作都将在该类中定义的 MAP 上进行。
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 } }
步骤 10 - 现在让我们构建我们的服务类。继续将以下代码集复制粘贴到“ProfileService.java”类中。我们将在这个类中声明要向外部世界公开的所有 Web 服务方法。我们需要创建 DatabaseClass 的一个引用,以便可以在此类中访问我们的临时数据库。
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); } }
步骤 11 - 在此步骤中,我们将创建与 URL 链接的资源类,并调用相应的服务。
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); } }
步骤 12 - 清理构建项目并运行它。如果一切顺利,那么您应该在访问http://localhost:8080/UserProfile/webapi/Profile” URL时在浏览器中获得以下输出。
您可以看到不同的条目是使用 XML 表示形式填充的。
通过应用正确的方法 URL,可以使用 Postman 测试不同的方法。
@GET 方法- 下面的屏幕截图演示了我们如何获得 get 请求所需的结果,该结果返回所有用户详细信息。
@POST - 以下请求可用于测试我们的 Post 方法。请注意 proId 是如何自动生成的。
@PUT - 此方法将更新条目。以下屏幕截图演示了 Jersey 如何从请求 URL 获取 proId 并更新相同的用户配置文件回复。
以同样的方式,您可以检查 Web 服务中是否有其他可用的方法。
在上一节中,我们开发了一项将公开 CRUD 功能的服务。现在,每当我们尝试在应用程序中实现此服务时,我们都需要创建此应用程序的客户端并将其附加到我们的应用程序。在本章中,我们将学习如何使用微服务的概念来构建此功能。以下是使用上述步骤构建的应用程序的图示。
演员应该是我们服务的入口点。在这种情况下,“ProfileResource.java”履行参与者的职责。该类会调用不同的方法来执行不同的操作,例如添加、更新和删除。
CRUD应用分解
根据微服务的主要原则,每个模块只需要一个业务任务,因此一个参与者不应该负责所有四个 CRUD 功能。考虑以下示例,我们在其中引入了一些新角色,以便您从概念上清楚地了解微服务是 SOA 的架构表示。
“主用户”是与“应用程序控制器”通信以满足自身需求的用户。“应用程序控制器”只是根据最终用户的请求调用不同的“资源管理器”。“资源管理器”完成需要完成的工作。让我们快速了解一下应用程序不同单元的不同角色。
最终用户/主要用户- 向应用程序控制器请求一些资源。
应用程序- 接收请求并将其转发到特定的资源管理器。
资源管理器- 执行更新、删除和添加用户的实际工作。
查看一个类的总责任如何在不同的其他类之间分配。