如何在gRPC微服务架构下集成Django与Spring Boot并实现CRUD操作?
解决方案:Django + Spring Boot(gRPC) + MongoDB 集成实现CRUD
1. 定义gRPC协议(通信契约)
先编写.proto文件,明确实体结构和CRUD服务接口,这是两端交互的核心标准。以User实体为例:
syntax = "proto3"; package user; // 用户实体结构 message User { string id = 1; string name = 2; string email = 3; int32 age = 4; } // 创建用户请求 message CreateUserRequest { string name = 1; string email = 2; int32 age = 3; } // 查询单个用户请求 message GetUserRequest { string id = 1; } // 更新用户请求 message UpdateUserRequest { string id = 1; string name = 2; string email = 3; int32 age = 4; } // 删除用户请求 message DeleteUserRequest { string id = 1; } // 通用响应格式 message CommonResponse { bool success = 1; string message = 2; } // gRPC服务接口定义 service UserService { rpc createUser(CreateUserRequest) returns (User); rpc getUser(GetUserRequest) returns (User); rpc updateUser(UpdateUserRequest) returns (User); rpc deleteUser(DeleteUserRequest) returns (CommonResponse); }
2. Spring Boot 端实现gRPC服务(操作MongoDB)
2.1 引入依赖
在pom.xml中添加gRPC和Spring Data MongoDB依赖:
<!-- gRPC Spring Boot Starter --> <dependency> <groupId>net.devh</groupId> <artifactId>grpc-server-spring-boot-starter</artifactId> <version>2.15.0.RELEASE</version> </dependency> <!-- Spring Data MongoDB --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-mongodb</artifactId> </dependency>
2.2 生成Java代码
添加Maven插件自动生成proto对应的Java类,在pom.xml的build节点下插入:
<extensions> <extension> <groupId>kr.motd.maven</groupId> <artifactId>os-maven-plugin</artifactId> <version>1.7.0</version> </extension> </extensions> <plugins> <plugin> <groupId>org.xolstice.maven.plugins</groupId> <artifactId>protobuf-maven-plugin</artifactId> <version>0.6.1</version> <configuration> <protocArtifact>com.google.protobuf:protoc:3.21.7:exe:${os.detected.classifier}</protocArtifact> <pluginId>grpc-java</pluginId> <pluginArtifact>io.grpc:protoc-gen-grpc-java:1.51.0:exe:${os.detected.classifier}</pluginArtifact> </configuration> <executions> <execution> <goals> <goal>compile</goal> <goal>compile-custom</goal> </goals> </execution> </executions> </plugin> </plugins>
执行mvn compile即可生成对应Java代码。
2.3 实现MongoDB实体与Repository
创建MongoDB映射实体:
import org.springframework.data.annotation.Id; import org.springframework.data.mongodb.core.mapping.Document; @Document(collection = "users") public class UserEntity { @Id private String id; private String name; private String email; private int age; // 构造函数、getter、setter }
编写Repository接口:
import org.springframework.data.mongodb.repository.MongoRepository; public interface UserRepository extends MongoRepository<UserEntity, String> { }
2.4 实现gRPC服务类
继承自动生成的UserServiceGrpc.UserServiceImplBase,实现CRUD逻辑:
import net.devh.boot.grpc.server.service.GrpcService; import io.grpc.Status; import io.grpc.StatusRuntimeException; import org.springframework.beans.factory.annotation.Autowired; @GrpcService public class UserGrpcService extends UserServiceGrpc.UserServiceImplBase { @Autowired private UserRepository userRepository; @Override public void createUser(CreateUserRequest request, StreamObserver<User> responseObserver) { UserEntity entity = new UserEntity(); entity.setName(request.getName()); entity.setEmail(request.getEmail()); entity.setAge(request.getAge()); UserEntity saved = userRepository.save(entity); User user = User.newBuilder() .setId(saved.getId()) .setName(saved.getName()) .setEmail(saved.getEmail()) .setAge(saved.getAge()) .build(); responseObserver.onNext(user); responseObserver.onCompleted(); } @Override public void getUser(GetUserRequest request, StreamObserver<User> responseObserver) { userRepository.findById(request.getId()) .ifPresentOrElse(entity -> { User user = User.newBuilder() .setId(entity.getId()) .setName(entity.getName()) .setEmail(entity.getEmail()) .setAge(entity.getAge()) .build(); responseObserver.onNext(user); responseObserver.onCompleted(); }, () -> { responseObserver.onError(new StatusRuntimeException(Status.NOT_FOUND)); }); } @Override public void updateUser(UpdateUserRequest request, StreamObserver<User> responseObserver) { userRepository.findById(request.getId()) .ifPresentOrElse(entity -> { entity.setName(request.getName()); entity.setEmail(request.getEmail()); entity.setAge(request.getAge()); UserEntity updated = userRepository.save(entity); User user = User.newBuilder() .setId(updated.getId()) .setName(updated.getName()) .setEmail(updated.getEmail()) .setAge(updated.getAge()) .build(); responseObserver.onNext(user); responseObserver.onCompleted(); }, () -> { responseObserver.onError(new StatusRuntimeException(Status.NOT_FOUND)); }); } @Override public void deleteUser(DeleteUserRequest request, StreamObserver<CommonResponse> responseObserver) { userRepository.findById(request.getId()) .ifPresentOrElse(entity -> { userRepository.delete(entity); CommonResponse response = CommonResponse.newBuilder() .setSuccess(true) .setMessage("User deleted successfully") .build(); responseObserver.onNext(response); responseObserver.onCompleted(); }, () -> { CommonResponse response = CommonResponse.newBuilder() .setSuccess(false) .setMessage("User not found") .build(); responseObserver.onNext(response); responseObserver.onCompleted(); }); } }
2.5 配置服务参数
在application.properties中设置gRPC端口和MongoDB连接:
grpc.server.port=9090 spring.data.mongodb.uri=mongodb://localhost:27017/your_database_name
3. Django 端集成gRPC客户端
3.1 安装依赖
通过pip安装gRPC相关包:
pip install grpcio grpcio-tools
3.2 生成Python代码
将.proto文件放到Django项目的proto目录下,执行命令生成Python代码:
python -m grpc_tools.protoc -I./proto --python_out=./your_django_app --grpc_python_out=./your_django_app ./proto/user.proto
执行后会生成user_pb2.py和user_pb2_grpc.py两个文件。
3.3 封装gRPC客户端工具
在Django app中编写工具类,简化gRPC调用:
import grpc import user_pb2 import user_pb2_grpc GRPC_SERVER_ADDRESS = 'localhost:9090' def get_user_stub(): channel = grpc.insecure_channel(GRPC_SERVER_ADDRESS) return user_pb2_grpc.UserServiceStub(channel) # 创建用户 def create_user(name, email, age): stub = get_user_stub() request = user_pb2.CreateUserRequest(name=name, email=email, age=age) return stub.createUser(request) # 查询用户 def get_user(user_id): stub = get_user_stub() request = user_pb2.GetUserRequest(id=user_id) try: return stub.getUser(request) except grpc.RpcError as e: if e.code() == grpc.StatusCode.NOT_FOUND: return None raise # 更新用户 def update_user(user_id, name, email, age): stub = get_user_stub() request = user_pb2.UpdateUserRequest(id=user_id, name=name, email=email, age=age) try: return stub.updateUser(request) except grpc.RpcError as e: if e.code() == grpc.StatusCode.NOT_FOUND: return None raise # 删除用户 def delete_user(user_id): stub = get_user_stub() request = user_pb2.DeleteUserRequest(id=user_id) return stub.deleteUser(request)
3.4 编写Django视图处理HTTP请求
编写视图函数映射HTTP请求到gRPC调用:
from django.http import JsonResponse from django.views.decorators.http import require_http_methods import json from .grpc_client import create_user, get_user, update_user, delete_user @require_http_methods(["POST"]) def create_user_view(request): data = json.loads(request.body) try: user = create_user(data['name'], data['email'], data['age']) return JsonResponse({ 'id': user.id, 'name': user.name, 'email': user.email, 'age': user.age }, status=201) except Exception as e: return JsonResponse({'error': str(e)}, status=500) @require_http_methods(["GET"]) def get_user_view(request, user_id): user = get_user(user_id) if not user: return JsonResponse({'error': 'User not found'}, status=404) return JsonResponse({ 'id': user.id, 'name': user.name, 'email': user.email, 'age': user.age }) @require_http_methods(["PUT"]) def update_user_view(request, user_id): data = json.loads(request.body) user = update_user(user_id, data['name'], data['email'], data['age']) if not user: return JsonResponse({'error': 'User not found'}, status=404) return JsonResponse({ 'id': user.id, 'name': user.name, 'email': user.email, 'age': user.age }) @require_http_methods(["DELETE"]) def delete_user_view(request, user_id): response = delete_user(user_id) return JsonResponse({ 'success': response.success, 'message': response.message }, status=200 if response.success else 404)
3.5 配置URL路由
在urls.py中添加路由映射:
from django.urls import path from .views import create_user_view, get_user_view, update_user_view, delete_user_view urlpatterns = [ path('users/', create_user_view, name='create_user'), path('users/<str:user_id>/', get_user_view, name='get_user'), path('users/<str:user_id>/update/', update_user_view, name='update_user'), path('users/<str:user_id>/delete/', delete_user_view, name='delete_user'), ]
4. 验证流程
- 启动MongoDB服务
- 启动Spring Boot应用,确保gRPC服务在9090端口正常运行
- 启动Django开发服务器
- 用curl或Postman测试各接口:
- POST
/users/创建用户 - GET
/users/{id}/查询用户 - PUT
/users/{id}/update/更新用户 - DELETE
/users/{id}/delete/删除用户
- POST
内容的提问来源于stack exchange,提问作者Asanabada Bhavesh
相关产品推荐
相关产品推荐

