从单体到微服务:一个文科生的Java实战手记
大家好,我是一个自学转码成功的前文科生。三年前,我连“后端”是干啥的都不清楚,如今却在一家互联网公司做Java微服务开发。今天写这篇教程,是因为我深知零基础入门的痛苦——当初看“微服务”三个字,以为是什么高深莫测的黑科技,其实它只是把一个大程序拆成几个小程序,各干各的活儿,再互相配合。
如果你正在学Java,也想搞懂微服务到底怎么玩,那这篇文章就是为你写的。我会用最直白的语言、最真实的代码,带你从零搭建一个微服务系统。不讲空理论,只讲能跑起来的东西。
为什么要把单体拆成微服务?
想象一下你开了一家小餐馆:
- 单体架构 就像一个人包办所有事:点菜、炒菜、上菜、收钱……忙得脚不沾地,一旦他生病,整个店就停摆。
- 微服务架构 则是分工明确:前台点单、厨师炒菜、服务员上菜、收银员结账。哪怕厨师请假,其他人还能照常运转。
在软件开发中,单体应用(Monolithic Application)就是一个大JAR包,所有功能模块(用户管理、订单处理、支付等)都塞在一起。初期开发快,但随着业务增长,代码越来越臃肿,改一个小功能可能要重新部署整个系统,风险高、效率低。
而微服务(Microservices)把系统拆成多个独立的小服务,每个服务只负责一个业务功能,可以单独开发、测试、部署和扩展。
我当初学的时候,最大的误区就是以为微服务是“高级玩家才配用”的东西。其实不是!只要你有清晰的业务边界,哪怕只有两个服务,也算微服务。
环境准备:5分钟搭好开发环境
我们要用 Java + Spring Boot + Spring Cloud 来实战。别怕,这些工具对新手很友好。
所需工具清单
| 工具 | 版本建议 | 作用 |
|---|---|---|
| JDK | 17 或 21 | Java运行环境 |
| Maven | 3.8+ | 项目依赖管理 |
| IDE | IntelliJ IDEA(社区版免费) | 写代码 |
| Postman | 最新版 | 测试API |
安装步骤(Mac/Windows通用)
安装JDK
访问 Oracle官网 或使用 SDKMAN!(推荐)安装JDK 17。# Mac/Linux 用户可用 SDKMAN! curl -s "https://get.sdkman.io" | bash sdk install java 17.0.10-oracle验证安装
java -version mvn -v能看到版本号就说明OK。
创建Spring Boot项目
打开 Spring Initializr,选择:- Project: Maven
- Language: Java
- Spring Boot: 3.2.x
- Dependencies: Spring Web, Spring Boot DevTools
点击“Generate”,下载ZIP并解压,用IDEA打开即可。
💡 避坑指南:不要一上来就装Eureka、Nacos这些注册中心!先学会写两个能互相调用的服务,再加治理组件。
核心概念:微服务到底“微”在哪?
1. 服务拆分:按业务能力划分
不是随便切一刀就算微服务。要按业务边界来拆。比如电商系统可拆为:
- user-service(用户管理)
- order-service(订单处理)
- product-service(商品信息)
每个服务有自己的数据库,互不干扰。
2. 服务通信:HTTP or 消息队列?
服务之间怎么“说话”?最简单的方式是 HTTP REST API。
例如:order-service 需要知道用户信息,就向 user-service 发一个HTTP请求。
3. 服务发现:怎么找到对方?
当服务多了,IP和端口会变来变去。这时候需要一个“电话簿”——服务注册中心(如 Nacos、Eureka)。每个服务启动时把自己登记上去,其他服务查这个“电话簿”就能找到它。
我们先跳过注册中心,用手动配置URL的方式体验通信,后面再升级!
实战项目:打造你的第一个微服务系统
我们做一个极简的“用户-订单”系统,包含两个服务:
user-service:提供用户信息查询order-service:创建订单,并调用 user-service 获取用户名
第一步:创建 user-service
用 Spring Initializr 创建项目,命名为
user-service,加入 Spring Web。创建用户实体类:
// User.java public class User { private Long id; private String name; // 构造函数、getter/setter 省略(可用Lombok简化) public User(Long id, String name) { this.id = id; this.name = name; } // getter... }创建控制器:
// UserController.java @RestController @RequestMapping("/users") public class UserController { @GetMapping("/{id}") public User getUser(@PathVariable Long id) { // 模拟数据库查询 if (id == 1L) { return new User(1L, "张三"); } return new User(id, "未知用户"); } }修改
application.yml,指定端口:server: port: 8081启动应用,访问
http://localhost:8081/users/1,应返回 JSON 用户数据。
第二步:创建 order-service
新建
order-service项目,同样加入 Spring Web。添加用户类(和上面一样,实际项目中可抽成公共模块):
public class User { private Long id; private String name; // ...构造函数和getter }创建订单类:
public class Order { private Long id; private Long userId; private String productName; private String userName; // 从user-service获取 // 构造函数、getter/setter }关键:如何调用 user-service?
使用 Spring 提供的
RestTemplate(最简单的HTTP客户端):// OrderService.java @Service public class OrderService { private final RestTemplate restTemplate; public OrderService(RestTemplate restTemplate) { this.restTemplate = restTemplate; } public Order createOrder(Long userId, String product) { // 调用 user-service 获取用户信息 String userUrl = "http://localhost:8081/users/" + userId; User user = restTemplate.getForObject(userUrl, User.class); return new Order(1001L, userId, product, user.getName()); } }配置 RestTemplate Bean(在主类或配置类中):
@SpringBootApplication public class OrderServiceApplication { public static void main(String[] args) { SpringApplication.run(OrderServiceApplication.class, args); } @Bean public RestTemplate restTemplate() { return new RestTemplate(); } }创建订单控制器:
@RestController @RequestMapping("/orders") public class OrderController { private final OrderService orderService; public OrderController(OrderService orderService) { this.orderService = orderService; } @PostMapping public Order createOrder(@RequestParam Long userId, @RequestParam String product) { return orderService.createOrder(userId, product); } }配置端口为 8082:
server: port: 8082
第三步:测试整个流程
- 先启动
user-service(端口8081) - 再启动
order-service(端口8082) - 用 Postman 发送 POST 请求到:
POST http://localhost:8082/orders?userId=1&product=Java教程 - 你应该收到类似响应:
{ "id": 1001, "userId": 1, "productName": "Java教程", "userName": "张三" }
🎉 恭喜!你已经完成了第一个微服务调用!
常见问题:新手踩坑实录
Q1:为什么我的 order-service 调用 user-service 报错?
常见原因:
- user-service 没启动(先启动被调用方!)
- URL写错(检查端口号是不是8081)
- 网络防火墙拦截(本地开发一般不会)
解决方法:先用浏览器直接访问 http://localhost:8081/users/1,确认能返回JSON,再测调用。
Q2:每次都要写死URL(localhost:8081),不灵活怎么办?
你说对了!这就是为什么需要服务注册中心。下一阶段你可以引入 Nacos:
- 下载 Nacos 并启动(官网)
- 在两个服务的
pom.xml中加入:<dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> </dependency> - 配置
application.yml:spring: application: name: user-service # 服务名 cloud: nacos: discovery: server-addr: localhost:8848 - 用
@LoadBalanced注解让 RestTemplate 支持服务名调用:@Bean @LoadBalanced public RestTemplate restTemplate() { return new RestTemplate(); } - 调用时不再写IP,而是写服务名:
String url = "http://user-service/users/" + userId;
这样,无论 user-service 部署在哪台机器、哪个端口,order-service 都能自动找到它。
Q3:微服务是不是越多越好?
绝对不是! 我见过有人把“登录”、“注册”、“找回密码”都拆成三个服务,结果维护成本爆炸。
建议:初期2-3个服务足够。等团队大了、业务复杂了,再按需拆分。记住:微服务是为了降低复杂度,不是制造复杂度。
学习建议:下一步怎么走?
你已经迈出了关键一步。接下来,我建议按这个路径深入:
掌握服务治理基础
- 学习 Nacos/Eureka(服务注册与发现)
- 学习 OpenFeign(比 RestTemplate 更优雅的声明式调用)
- 学习 Spring Cloud LoadBalancer(负载均衡)
解决分布式问题
- 分布式事务(Seata)
- 链路追踪(SkyWalking)
- 配置中心(Nacos Config)
容器化部署
- 学 Docker:把每个服务打包成镜像
- 学 Docker Compose:一键启动所有服务
我的开发心得:不要追求“一步到位”。先跑通流程,再优化细节。我第一版微服务连日志都没打,但能跑就行。后来才慢慢加上监控、熔断、限流。
结语:文科生也能玩转微服务
写这篇教程,是因为我想告诉所有非科班的朋友:技术没有想象中那么可怕。微服务的核心思想——解耦、专注、协作——其实在生活中处处可见。
你不需要一开始就懂 Kubernetes、Service Mesh。从两个能互相调用的 Spring Boot 应用开始,就已经走在正确的路上了。
记住我的话:代码跑起来,比什么都重要。
下次见!如果你在实践中有任何问题,欢迎留言交流。技术分享的路上,我们一起成长。

评论 0