Spring Boot + MyBatis-Plus 实战中的那些“坑”与思考 —— 以身份认证服务为例

最近自己在折腾全栈 DDD 架构时,踩了一些"坑",也有不少思考,特此记录。这篇文章适合有一点 Java 基础、正在搞全栈、追求代码结构和工程规范的你。

1. 背景与业务场景

做后台服务,身份认证登录注册总是绕不过去,特别是要支持"邮箱、手机号、第三方登录(微信、QQ、Github)"这种后续可扩展需求时,表设计就很重要了。

我的目标很简单:

  • 数据库要能灵活扩展多种登录方式
  • 业务分层要体现DDD思想
  • 后端要多数据源适配(PostgreSQL为主,MySQL也能兼容)
  • 前后端联调不被安全框架挡住路
  • 关键配置要清楚,后续不踩重复的坑

2. 表结构这样设计,未来少掉头发

大致SQL如下,推荐每一列都写上中文注释(强烈建议!):

sql 复制代码
CREATE TABLE identity.users (
    id BIGSERIAL PRIMARY KEY,           -- 用户ID
    email VARCHAR(64) UNIQUE,           -- 邮箱
    phone VARCHAR(32) UNIQUE,           -- 手机号
    password VARCHAR(255) NOT NULL,     -- 密码
    nickname VARCHAR(64),               -- 昵称
    avatar VARCHAR(255),                -- 头像
    is_email_verified BOOLEAN DEFAULT FALSE, -- 邮箱是否已验证
    is_phone_verified BOOLEAN DEFAULT FALSE, -- 手机号是否已验证
    status SMALLINT DEFAULT 1,          -- 状态
    last_login_at TIMESTAMP,            -- 上次登录时间
    created_at TIMESTAMP DEFAULT now(), -- 创建时间
    updated_at TIMESTAMP DEFAULT now(), -- 更新时间
    created_by VARCHAR(64),             -- 创建人
    updated_by VARCHAR(64),             -- 修改人
    wechat_unionid VARCHAR(64),         -- 微信unionId(扩展)
    qq_openid VARCHAR(64),              -- QQ openId(扩展)
    github_id VARCHAR(64),              -- github账号(扩展)
    version INT DEFAULT 0,              -- 乐观锁
    is_deleted BOOLEAN DEFAULT FALSE    -- 软删除
);

小建议:

表名、字段名都尽量"意图明确",小写蛇形,严格区分限界上下文(如 identity.users)。写注释不仅是对自己负责,也是对团队和未来的你负责。

3. 多数据源这样配,PostgreSQL / MySQL 随便切

用 dynamic-datasource-spring-boot-starter,YAML配置极其简单(节选):

yaml 复制代码
spring:
  datasource:
    dynamic:
      primary: pg
      datasource:
        pg:
          driver-class-name: org.postgresql.Driver
          url: jdbc:postgresql://localhost:5432/your_db?currentSchema=identity
          username: postgres
          password: your_password
        mysql:
          driver-class-name: com.mysql.cj.jdbc.Driver
          url: jdbc:mysql://localhost:3306/your_db?serverTimezone=Asia/Shanghai
          username: root
          password: your_password

想切库,代码里加@DS("mysql")@DS("pg")即可。是不是有种"撸起袖子就能干"的感觉?

4. 你的后端代码,分层要自觉

领域层、应用层、基础设施层、接口层......大家都懂,但真能做到清晰分层,其实是对自我约束的磨炼。

一个标准认证流程,推荐结构如下:

  • Controller(接口层,处理请求响应)
  • Service(应用层,编排业务逻辑)
  • Mapper(基础设施层,数据库操作,MyBatis-Plus自动管理)
  • Domain(领域层,定义实体/聚合)

代码示例:

java 复制代码
// Mapper接口
@Mapper
public interface UserMapper extends BaseMapper<User> {}

// Service接口
public interface UserService {
    User register(User user);
    User login(String email, String password);
}

// Service实现
@Service
public class UserServiceImpl implements UserService {
    @Autowired
    private UserMapper userMapper;
    // ...具体逻辑
}

人话解释:

Controller 不要注入 Mapper,也不要写 if else 业务细节。分层,是为了"今天自己看、明天同事看、后天重构都不难受"。

5. 说一说 MyBatis-Plus 的"坑"

最大的大坑:@MapperScan配置太宽导致BindingException!

真实血泪:

java 复制代码
@MapperScan("pers.seekersferry.*") // ❌ 致命!把service等接口全当Mapper扫描了!

结果所有的service接口也被MyBatis-Plus"当成Mapper"去找SQL语句,必然报错:

bash 复制代码
Invalid bound statement (not found): pers.seekersferry.identity.application.service.UserService.register

修正方案:

java 复制代码
@MapperScan("pers.seekersferry.identity.infrastructure.mapper")

只扫描Mapper包,永远不要一把梭所有包。

另一个常见误区:@Mapper写错地方

@Mapper 只写在Mapper接口(如UserMapper),绝不能写在Service接口。

6. Spring Security 默认401/403的那些"小惊喜"

很多人一开始加上spring-boot-starter-security就疯了------接口全部 401,swagger也打不开,开发体验直接爆炸。

人话解决方案:

本地开发阶段,把所有接口都放开(安全的事以后再说),加一个安全配置类:

java 复制代码
@Configuration
public class SecurityConfig {
    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http
            .csrf(csrf -> csrf.disable())
            .authorizeHttpRequests(authorize -> authorize
                .anyRequest().permitAll()
            );
        return http.build();
    }
}

友情提醒:

生产环境一定要收紧权限,但开发联调阶段别给自己添堵。

7. @MapperScan能写在yaml里吗?

答案很干脆:不能!

  • yaml 只能配 mapper-locations、type-aliases-package 这类属性,扫描 Mapper 包必须在 Java 里用注解或者配置类。
  • 以后看到"为什么我的service也被当Mapper了?"第一反应就该查MapperScan!

8. 结语:规范不是负担,是"防脱发"的最佳姿势

每一次规范的小坚持,都是在为自己的效率和团队的可维护性加分。

遇到bug和踩坑,别慌,debug和Google是最靠谱的好朋友。别让配置文件和注解把你绕晕,读源码、翻官方文档、反思自己的调用链,一步步就能爬出来

希望这篇文章对同为全栈的你,有点共鸣、有点实用,也祝你的后端工程越来越稳,"长久在线,头发依旧"。


如果你有类似经历或者更骚气的踩坑,欢迎留言交流!

相关推荐
街霸星星几秒前
使用 vfox 高效配置 Java 开发环境:一份全面指南
java
♛暮辞5 分钟前
java程序远程写入字符串到hadoop伪分布式
java·hadoop·分布式
巴拉巴巴巴拉33 分钟前
IDEA 2024.1 配置 MyBatis Generator 详细教程
java·intellij-idea·mybatis
努力的小郑36 分钟前
Spring Boot整合阿里云OSS企业级实践:高可用文件存储解决方案
spring boot·后端·阿里云
巴拉巴巴巴拉39 分钟前
IDEA 中 Maven 配置:当前项目与新项目的统一设置方法
java·maven·intellij-idea
半新半旧1 小时前
Java并发8--并发安全容器详解
java·python·安全
远望樱花兔1 小时前
【Java】【力扣】101.对称二叉树
java·开发语言·leetcode
努力学算法的蒟蒻1 小时前
解决Maven版本不兼容问题的终极方案
java·maven
星逝*1 小时前
Java实战:实时聊天应用开发(附GitHub链接)
java·开发语言·python
leobertlan1 小时前
杂篇-有感而发,写于2025年7月
java·前端·程序员