Designing Modular Backend Services and API Management with Spring Cloud
This article explains how to build a highly extensible, modular backend service using Spring Cloud, demonstrates practical module composition and separation, discusses RESTful API design principles, presents concrete Java code examples for commands, controllers and pagination, and reviews popular API documentation tools such as Swagger, SpringDoc and Knife4j.
The article introduces a modular backend architecture that can be assembled from independent functional modules, allowing flexible combination and scaling according to project size and requirements.
It outlines the project structure and modular construction ideas, covering topics such as project layout, RESTful API design and management, gateway routing, DDD domain‑driven design, RPC modularization, distributed transactions, and event‑driven lifecycle logging.
Two practical examples are provided: Example 1 combines juejin-user and juejin-message into a single service via the startup module juejin-appliaction-system to reduce server resources, while Example 2 packages all three modules ( juejin-user , juejin-message , juejin-pin ) into a single monolithic application using juejin-appliaction-single for small‑scale projects.
The development environment is based on IDEA + Spring Cloud , and the article recommends reading the previous post on project structure before diving into modular concepts.
RESTful
RESTful APIs treat resources as first‑class entities and use HTTP methods (GET, POST, PUT, DELETE) to express CRUD operations. The author argues that while RESTful design is widely promoted, it may feel unnecessary for simple actions like login/logout, which can be expressed as /login and /logout or as resource‑oriented POST /sessions and DELETE /sessions .
Dialectical View
The article suggests avoiding dogmatic adherence to any single style; instead, adopt the ideas that best serve the project, such as using Spring Boot and Spring Cloud modules wisely.
API Design
Request Methods
Three common conventions are compared: using only POST, using POST for writes and GET for reads, and the standard RESTful approach that maps CRUD operations to HTTP verbs. The author recommends the RESTful style because it keeps URLs noun‑focused and lets the method convey the action.
Request Paths
Paths should preferably use hyphens instead of camelCase (e.g., work-order rather than workOrder ). When using only POST, a typical pattern is /pin/publish , /pin/update , etc.; the RESTful counterpart would be POST /pin , PUT /pin , DELETE /pin , GET /pin/list , GET /pin/page .
Request Parameters
Instead of passing entire domain entities as request bodies, the author advises defining dedicated DTO classes (e.g., CreatePinVO , PublishPinVO ) and using JSON bodies to keep the contract clear.
Response Results
Three response envelope styles are shown: a boolean‑based {"success":true,"message":"成功","object":null} , an integer‑based {"code":0,"message":"成功","object":null} , and a string‑based {"result":"SUCCESS","message":"成功","object":null} . The string‑based format is recommended for better extensibility.
API Example – Pin Module
Sample Java code demonstrates a Spring MVC controller for the juejin‑pin module, including command classes for create, update, and delete operations, a view object PinVO , pagination request PageQuery , and generic pagination response PageVO<T> . The controller methods are annotated with @RestController , @PostMapping , @PutMapping , @DeleteMapping , and @GetMapping :
@RestController
@RequestMapping("/pin")
public class PinController {
@PostMapping
public void create(@RequestBody PinCreateCommand create) {}
@PutMapping
public void update(@RequestBody PinUpdateCommand update) {}
@DeleteMapping
public void delete(@RequestBody PinDeleteCommand delete) {}
@GetMapping("/page")
public PageVO
page(PageQuery page) { return new PageVO<>(); }
} @Data
public class PinCreateCommand {
private String content;
private String clubId;
} @Data
public class PinUpdateCommand {
private String id;
private String clubId;
} @Data
public class PinDeleteCommand {
private String id;
} @Data
public class PinVO {
private String id;
private String content;
private String clubId;
private String clubName;
// likes and comments omitted
} @Data
public class PageQuery {
private long current = 1;
private long size = 10;
} @Data
public class PageVO
{
private List
records = Collections.emptyList();
private long total = 0;
private long size = 10;
private long current = 1;
private long pages = 1;
}API Management
After implementing APIs, documentation is essential for front‑end integration. The article reviews several tools:
Swagger (OpenAPI 3)
Adding io.swagger.core.v3 annotations to controllers and models generates interactive documentation. Example configuration with Springfox:
@EnableOpenApi
@Configuration
public class PinConfiguration {
@Bean
public Docket pinApi() {
return new Docket(DocumentationType.OAS_30)
.groupName("沸点")
.select()
.apis(RequestHandlerSelectors.basePackage("com.bytedance.juejin.pin"))
.paths(PathSelectors.any())
.build();
}
}For Spring Boot 2.6+, set spring.mvc.pathmatch.matching-strategy: ant_path_matcher to keep compatibility.
SpringDoc
SpringDoc is the modern alternative to Springfox. Dependency:
implementation 'org.springdoc:springdoc-openapi-ui:1.6.11'Configuration example:
@Configuration
public class PinConfiguration {
@Bean
public GroupedOpenApi pinApi() {
return GroupedOpenApi.builder()
.group("沸点")
.packagesToScan("com.bytedance.juejin.pin")
.build();
}
}Knife4j
Knife4j provides a more attractive UI for Swagger. It can be combined with either Springfox or SpringDoc:
implementation 'com.github.shijingsh:knife4j-spring-boot-starter:3.0.5'When used with SpringDoc, add implementation 'com.github.shijingsh:knife4j-springdoc-ui:3.0.5' and access the UI at /doc.html .
Recommendations
Use the API documentation tool only for generating specs; avoid embedding additional documentation inside the tool because it makes future migration difficult. Keep the source of truth in code annotations and regenerate the docs when the API changes.
Conclusion
Modular backend design, clear RESTful API contracts, and consistent documentation practices together improve maintainability and scalability. Developers should adopt the useful aspects of each methodology while remaining flexible to the project's actual needs.
Rare Earth Juejin Tech Community
Juejin, a tech community that helps developers grow.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.