智慧零工便捷的平台后端编写实战:Spring Boot 3 + MyBatis-Flex 现代化架构

本文将详细分享我使用Spring Boot 3.3.5 + MyBatis-Flex + SQLite构建零工平台后端系统的完整经验,包含架构设计、技术选型、核心功能实现和生产部署。

项目背景

随着零工经济的快速发展,我决定开发一个现代化的零工服务平台。后端系统需要支持工作发布、申请匹配、用户管理、支付结算等复杂业务场景,同时要保证高性能、高可用和易扩展。

项目概览

  • 项目名称: 智慧零工平台后端系统
  • 技术栈: Spring Boot 3.3.5 + Java 21 + MyBatis-Flex + SQLite
  • 项目地址: GitHub - Gigplatform_backend
  • API文档: 24个业务模块,100+接口
  • 部署方式: 宝塔面板 + PM2 + Nginx

原文链接:https://blog.ybyq.wang/archives/543.html

技术选型分析

为什么选择Spring Boot 3?

  1. Java 21支持: 享受最新的语言特性和性能优化
  2. 原生镜像: 支持GraalVM原生编译,启动更快
  3. 响应式编程: 内置WebFlux支持
  4. 可观测性: 增强的监控和链路追踪
  5. 安全性: 升级的Spring Security

MyBatis-Flex vs MyBatis-Plus

经过对比,我选择了MyBatis-Flex:

// MyBatis-Flex 优势示例
// 1. 类型安全的查询
List<
Job> jobs = queryWrapper
.select(JOB.ALL_COLUMNS
)
.from(JOB
)
.where(JOB.STATUS.eq("ACTIVE"
)
)
.and(JOB.SALARY.ge(5000
)
)
.orderBy(JOB.CREATE_TIME.desc(
)
)
.limit(10
)
.list(
)
;
// 2. 智能字段映射
@Table
("t_job"
)
public
class Job {

@Id
(keyType = KeyType.Auto
)
private Long id;
@Column
("job_title"
)
private String title;
// 自动处理驼峰命名
private String companyName;
// -> company_name
}

SQLite的选择

对于中小型项目,SQLite具有独特优势:

  • 零配置: 无需独立数据库服务器
  • 高性能: 本地文件访问,减少网络开销
  • 事务支持: 完整的ACID特性
  • 跨平台: 易于开发和部署
  • 成本低: 降低运维复杂度

架构设计

整体架构

┌─────────────────┐    ┌─────────────────┐    ┌─────────────────┐
│   前端应用       │    │   API网关        │    │   负载均衡       │
│  (uni-app)      │◄───│   (Nginx)       │◄───│                │
└─────────────────┘    └─────────────────┘    └─────────────────┘
│
▼
┌─────────────────────────┐
│      Spring Boot        │
│    (业务逻辑层)          │
└─────────────────────────┘
│
┌───────────────┼───────────────┐
▼               ▼               ▼
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│  认证授权     │ │  业务服务     │ │  数据访问     │
│  (JWT)      │ │  (Service)   │ │ (MyBatis)   │
└─────────────┘ └─────────────┘ └─────────────┘
│
▼
┌─────────────────┐
│   SQLite 数据库  │
└─────────────────┘

项目模块结构

com.example.backend/
├── controller/           # 控制器层
│   ├── AuthController           # 认证授权
│   ├── JobsController          # 工作管理
│   ├── UsersController         # 用户管理
│   └── ...                     # 其他业务控制器
├── service/             # 业务逻辑层
│   ├── impl/           # 实现类
│   └── interfaces/     # 接口定义
├── mapper/             # 数据访问层
├── entity/             # 实体类
├── config/             # 配置类
├── common/             # 公共组件
│   ├── Result.java     # 统一返回结果
│   ├── JwtUtil.java    # JWT工具
│   └── JwtFilter.java  # JWT过滤器
└── BackendApplication.java # 启动类

核心功能实现

1. JWT认证体系

@Component
public
class JwtUtil {

@Value
("${jwt.secret:default-secret}"
)
private String secret;
@Value
("${jwt.expiration:86400}"
)
private Long expiration;
public String generateToken(String username) {

Date expirationDate =
new Date(System.currentTimeMillis(
) + expiration * 1000
)
;
return Jwts.builder(
)
.setSubject(username)
.setIssuedAt(
new Date(
)
)
.setExpiration(expirationDate)
.signWith(SignatureAlgorithm.HS512
, secret)
.compact(
)
;
}
public Claims getClaimsFromToken(String token) {

try {

return Jwts.parser(
)
.setSigningKey(secret)
.parseClaimsJws(token)
.getBody(
)
;
}
catch (Exception e) {

return
null
;
}
}
public
boolean validateToken(String token) {

try {

Claims claims = getClaimsFromToken(token)
;
return claims !=
null &&
!claims.getExpiration(
).before(
new Date(
)
)
;
}
catch (Exception e) {

return false
;
}
}
}
// JWT过滤器
@Component
public
class JwtFilter
implements Filter {

@Autowired
private JwtUtil jwtUtil;
@Override
public
void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain)
throws IOException
, ServletException {

HttpServletRequest httpRequest = (HttpServletRequest
) request;
HttpServletResponse httpResponse = (HttpServletResponse
) response;
// 跳过认证的路径
String path = httpRequest.getRequestURI(
)
;
if (isPublicPath(path)
) {

chain.doFilter(request, response)
;
return
;
}
String token = extractToken(httpRequest)
;
if (token ==
null || !jwtUtil.validateToken(token)
) {

httpResponse.setStatus(HttpStatus.UNAUTHORIZED.value(
)
)
;
httpResponse.getWriter(
).write(
JSON.toJSONString(Result.error(102
, "未登录,请先登录"
)
)
)
;
return
;
}
// 设置用户信息到上下文
Claims claims = jwtUtil.getClaimsFromToken(token)
;
LoginUser loginUser =
new LoginUser(
)
;
loginUser.setUsername(claims.getSubject(
)
)
;
UserContext.setCurrentUser(loginUser)
;
chain.doFilter(request, response)
;
}
}

2. 统一结果封装

@Data
@AllArgsConstructor
@NoArgsConstructor
public
class Result<
T> {

private Integer code;
private String message;
private T data;
public
static <
T> Result<
T> success(
) {

return
new Result<
>(0
, "调用成功"
,
null
)
;
}
public
static <
T> Result<
T> success(T data) {

return
new Result<
>(0
, "调用成功"
, data)
;
}
public
static <
T> Result<
T> error(Integer code, String message) {

return
new Result<
>(code, message,
null
)
;
}
public
static <
T> Result<
T> error(String message) {

return
new Result<
>(200
, message,
null
)
;
}
}
// 全局异常处理
@RestControllerAdvice
public
class GlobalExceptionHandler {

@ExceptionHandler
(Exception.
class
)
public Result<
String> handleException(Exception e
posted on 2025-06-08 18:30  ljbguanli  阅读(51)  评论(0)    收藏  举报