1. 跑腿系统三端架构设计
跑腿系统的核心在于同时满足用户、骑手和管理后台三方的需求。我们采用前后端分离的架构,前端使用Vue.js框架,后端基于Spring Boot构建RESTful API。这种架构的优势在于:
- 前后端开发完全解耦,团队可以并行开发
- 前端可以灵活适配不同终端(Web/App/小程序)
- 后端服务可独立扩展和部署
- 接口定义清晰,便于自动化测试
三端的数据流转关系如下:
code复制用户端 → API网关 → 业务服务层 ← 管理后台
↑
骑手端
2. 技术栈选型与项目搭建
2.1 前端技术栈
我们选择Vue 3 + TypeScript作为前端主要技术栈:
bash复制# 创建Vue项目
npm init vue@latest errand-system -- --template vue-ts
关键依赖:
vue-router:路由管理pinia:状态管理axios:HTTP请求element-plus:UI组件库vite:构建工具
2.2 后端技术栈
Spring Boot基础配置:
java复制// pom.xml关键依赖
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.2.2</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
</dependencies>
3. 核心功能模块实现
3.1 用户端功能实现
用户下单流程的关键代码示例:
vue复制<!-- 下单表单组件 -->
<script setup lang="ts">
const form = reactive({
pickupAddress: '',
deliveryAddress: '',
goodsType: 1,
remark: ''
})
const submitOrder = async () => {
const { data } = await axios.post('/api/orders', form)
if(data.code === 200) {
ElMessage.success('下单成功')
}
}
</script>
3.2 骑手端功能实现
骑手接单的WebSocket实现:
java复制@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {
@Override
public void configureMessageBroker(MessageBrokerRegistry config) {
config.enableSimpleBroker("/topic");
config.setApplicationDestinationPrefixes("/app");
}
@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint("/ws")
.setAllowedOrigins("*")
.withSockJS();
}
}
3.3 管理后台实现
订单管理接口示例:
java复制@RestController
@RequestMapping("/admin/orders")
public class OrderAdminController {
@GetMapping
public PageResult<Order> listOrders(
@RequestParam(defaultValue = "1") Integer page,
@RequestParam(defaultValue = "10") Integer size) {
// 实现分页查询逻辑
}
@GetMapping("/stats")
public OrderStats getOrderStats() {
// 返回订单统计信息
}
}
4. 前后端联调与部署
4.1 接口规范设计
我们采用RESTful风格设计API,规范如下:
| 方法 | 路径 | 描述 |
|---|---|---|
| GET | /api/orders | 获取订单列表 |
| POST | /api/orders | 创建新订单 |
| GET | /api/orders/ | 获取订单详情 |
| PUT | /api/orders/ | 更新订单状态 |
4.2 跨域解决方案
Spring Boot配置CORS:
java复制@Configuration
public class CorsConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("*")
.allowedMethods("*")
.allowedHeaders("*");
}
}
4.3 项目部署
使用Docker部署后端服务:
dockerfile复制FROM openjdk:17-jdk-slim
COPY target/errand-system.jar app.jar
EXPOSE 8080
ENTRYPOINT ["java","-jar","app.jar"]
前端部署到Nginx:
nginx复制server {
listen 80;
server_name errand.example.com;
location / {
root /usr/share/nginx/html;
try_files $uri $uri/ /index.html;
}
location /api {
proxy_pass http://backend:8080;
}
}
5. 系统优化与扩展
5.1 性能优化措施
- 数据库索引优化:
sql复制CREATE INDEX idx_order_status ON orders(status);
CREATE INDEX idx_rider_location ON riders(latitude, longitude);
- 接口缓存策略:
java复制@Cacheable(value = "orderCache", key = "#orderId")
public Order getOrderDetail(Long orderId) {
// 查询数据库
}
5.2 安全防护方案
- JWT认证实现:
java复制public class JwtTokenProvider {
public String generateToken(UserDetails userDetails) {
// 生成token逻辑
}
public boolean validateToken(String token) {
// 验证token逻辑
}
}
- 敏感数据加密:
java复制@ColumnTransformer(
read = "AES_DECRYPT(UNHEX(phone_number), 'encryption-key')",
write = "HEX(AES_ENCRYPT(?, 'encryption-key'))"
)
private String phoneNumber;
6. 常见问题解决方案
6.1 跨域问题深度解决
除了基础的CORS配置,还需要注意:
- 预检请求(OPTIONS)处理
- 携带凭证的请求(Credentials)
- 复杂请求头处理
完整解决方案:
java复制@Bean
public CorsFilter corsFilter() {
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
CorsConfiguration config = new CorsConfiguration();
config.setAllowCredentials(true);
config.addAllowedOriginPattern("*");
config.addAllowedHeader("*");
config.addAllowedMethod("*");
source.registerCorsConfiguration("/**", config);
return new CorsFilter(source);
}
6.2 高并发场景应对
- 订单创建加分布式锁:
java复制public boolean createOrderWithLock(Order order) {
String lockKey = "order:lock:" + order.getUserId();
try {
Boolean locked = redisTemplate.opsForValue()
.setIfAbsent(lockKey, "1", 30, TimeUnit.SECONDS);
if(locked != null && locked) {
return createOrder(order);
}
throw new BusinessException("操作太频繁");
} finally {
redisTemplate.delete(lockKey);
}
}
- 使用消息队列削峰:
java复制@RabbitListener(queues = "order.queue")
public void processOrder(OrderMessage message) {
// 异步处理订单
}
7. 项目扩展方向
7.1 智能调度算法
基于骑手位置和订单分布的智能匹配:
java复制public List<Rider> findBestRiders(Order order) {
return riderRepository.findNearbyRiders(
order.getPickupLatitude(),
order.getPickupLongitude(),
5 // 5公里范围内
).stream()
.sorted(Comparator.comparingDouble(r ->
calculateDistance(r, order)))
.limit(3)
.collect(Collectors.toList());
}
7.2 大数据分析
使用ELK进行订单分析:
- 日志收集配置:
java复制@Configuration
public class LogbackConfig {
@Bean
public Logger logstashLogger() {
LoggerContext context = (LoggerContext) LoggerFactory.getILoggerFactory();
return context.getLogger("LOGSTASH");
}
}
- Kibana可视化看板:
- 订单量趋势图
- 骑手接单时效分析
- 热门配送区域热力图
8. 开发经验总结
在实际开发中,有几个关键点需要特别注意:
- 状态管理:订单状态流转要设计严谨的状态机,避免出现状态混乱
java复制public enum OrderStatus {
PENDING, // 待接单
ACCEPTED, // 已接单
PICKED_UP, // 已取货
DELIVERING, // 配送中
COMPLETED, // 已完成
CANCELLED // 已取消
}
- 位置服务:使用高德或百度地图API时,注意坐标系转换
java复制public class LocationUtils {
// GCJ02转WGS84
public static Point gcjToWgs84(double lat, double lng) {
// 实现坐标系转换
}
}
- 性能监控:集成Prometheus监控关键指标
java复制@RestController
@RequestMapping("/actuator")
public class MetricsController {
@GetMapping("/metrics")
public String metrics() {
// 暴露监控指标
}
}
- 测试策略:
- 单元测试覆盖核心业务逻辑
- 集成测试验证接口功能
- E2E测试模拟用户完整流程
java复制@SpringBootTest
class OrderServiceTest {
@Autowired
private OrderService orderService;
@Test
void testCreateOrder() {
Order order = new Order();
// 设置订单参数
Order result = orderService.createOrder(order);
assertNotNull(result.getId());
}
}
