简体   繁体   中英

Spring boot RESTful - three tier architecture

I am a dotnet developer but now I will be working on a spring boot application. One thing confusing me is how can we separate API layer, service layer and repository layer. In a dotnet project we create class projects for service and repository layers and a web project for API or presentation layer. But in maven based spring boot seems to be not familiar with this approach. Although I found in maven you can create separate modules but not sure this is the right way. Whatever the right way, Please share some example implementations. Any good opensouce project available that I can follow and make decision?

You use a Controller Class to route all your API requests into your application.

From your controller, your requests go to the service layer, where all your business logic is written. You perform all the application specific functions in service layer and then you can use the Repository layer for persisting all the data. Here you can use JPA repository for this.

You can create Modules like Controller, Service, and Repository (Mainly). You can use Entities and Dtos for all the Data transfer and Persistence purposes. Mainly the request flow is

Controller->Service->Repository(Optional).

You perform all the API routings in the controller.

Depending on the scale of your project and how you define the boundary of a module, there're multiple ways to organize your code.

For example, in my company, we're separating the code into module by business domain. We have projects called security , schedule , messaging , etc. Each project carries its own set of @Controller (which is the API endpoint), @Service and @Repository . Something like this.

项目结构

configuration is for @Configuration classes. controller is for @Controller classes. db.domain is for @Entity classes. db.repo is for @Repository interfaces. service is for @Service classes. dto is for custom classes which transform data from @Entity classes into some custom format for the API endpoints.

In your case, if you want to have separate projects for @Controller , @Service and @Repository , you just need to use Maven to declare the dependencies between your projects. For example, the @Service project should have the @Repository project as one of the dependencies.

In this scenario, it's a good idea to set up a multi-module Maven project . Subsequently, you can declare dependencies between any of your projects very easily.

In a dotnet project we create class projects for service and repository layers and a web project for API or presentation layer. But in maven based spring boot seems to be not familiar with this approach.

Indeed spring boot is not familiar with the separation of the modules. I'll try to explain why (this might be subjective opinion, but hopefully it will help to understand how these things work in java world)

Java modules are usually represented by JARs as a built artifacts. Well, technically there are "modules" in java 9+ but lets put them aside for this question. JAR is just a contains of classes zipped together.

In java you run a process that has JARs in its classpath (can read the classes from) + sometimes classes outside the jar.

Here is the thing: java doesn't care from which JAR the class is loaded, moreover usually no-one even tries to understand from which JAR the class is loaded. As long as the class exists in a classpath and java runtime can load it you're good to go.

Now spring boot is a "runtime" framework, in a sense that it doesn't really compile anything, you give it JARs with classes and it tries to load the project from them. For example component scanning of "com.foo.bar" will scan for classes in this package so that the class can be in any JAR in the classpath.

As for web layer. Spring / Spring boot has controllers like you've probably already figured out. For example: spring says: "I'll expose a web endpoint for classes annotated with @RestController annotation". It doesn't really care about the real jar that the annotated classes belongs to. As long as its subject to component scanning policy (there are other techniques as well) spring will load it.

So you can:

  1. Use package for web controllers. Usually this is good enough for small projects / microservices/ something to start with.

  2. Use a special maven module (that will create a jar) that in turn will be added as a dependency to the spring boot artifact, and then again, it doesn't matter in runtime.
    Usually this pays off if you have a complicated project or for example create a library that will automatically expose some endpoints once you plug it (read add as a dependency) to a project.

The second approach requires to understand how exactly you will manage dependencies (for example: web module will depend on business-logic-module because you'll create a dependency on some service from the controller and the controller won't have a dependency on service the code will not compile).

Two tips here that will probably save you some time if you go with multi-module:

  • avoid circular dependencies: in maven it won't work (build time) in spring usually it doesn't work, there are workarounds but they usually point on code smell. In short, don't go there
  • do not define a dependency that contains @SpringBootApplication usually you'll build it with spring boot maven plugin and the JAR of spring boot is not really a regular JAR, therefor maven dependency cannot be done this way).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM