从零到一:使用Spring Initializr与MyBatis快速构建RESTful API项目

📅 2026/7/15 2:31:36 👁️ 阅读次数 📝 编程学习
从零到一:使用Spring Initializr与MyBatis快速构建RESTful API项目

1. 为什么选择Spring Initializr和MyBatis组合

如果你正在寻找一个既能快速启动项目,又能灵活操作数据库的Java开发方案,Spring Initializr和MyBatis的组合绝对是你的不二之选。Spring Initializr就像个智能项目生成器,30秒就能搭好基础框架;而MyBatis则是数据库操作的瑞士军刀,既支持直观的SQL编写,又能与Spring无缝集成。

我去年接手过一个用户管理系统改造项目,老系统用的是纯JDBC,光是数据库连接代码就占了三成文件量。换成这个组合后,开发效率直接翻倍——用Spring Initializr生成的骨架项目自带依赖管理,MyBatis的XML映射文件让SQL维护变得清晰可控。最惊喜的是Druid连接池的监控功能,直接帮我们发现了三个隐藏的性能瓶颈。

这个技术栈特别适合:

  • 需要快速验证想法的创业团队
  • 传统企业级应用的现代化改造
  • 教学场景下的全栈开发演示
  • 中小型互联网产品的后端服务

2. 5分钟完成项目初始化

2.1 使用Spring Initializr生成项目骨架

打开IDE(推荐IntelliJ IDEA),选择File -> New -> Project,在左侧选择Spring Initializr。这里有个小技巧:把Server URL改成阿里云的镜像(https://start.aliyun.com),国内下载依赖会快很多。

关键配置项:

  • Project SDK选Java 17(LTS版本)
  • 打包方式选Jar(微服务架构推荐)
  • Java版本保持与SDK一致
  • 依赖先勾选:
    • Spring Web(Web MVC支持)
    • MyBatis Framework(数据库支持)
    • MySQL Driver(数据库驱动)

点击生成后,你会得到一个标准化的项目结构。我习惯把自动生成的README.md和HELP.md删掉,保持项目干净。

2.2 补充必要依赖

打开pom.xml,在 节点添加这些关键依赖:

<!-- Druid连接池 --> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid-spring-boot-starter</artifactId> <version>1.2.8</version> </dependency> <!-- Lombok简化代码 --> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> <!-- 测试用H2数据库 --> <dependency> <groupId>com.h2database</groupId> <artifactId>h2</artifactId> <scope>test</scope> </dependency>

记得刷新Maven项目。有次我忘了刷新,找了半小时为什么注解不生效,这个坑希望大家别踩。

3. 数据库连接配置实战

3.1 多环境配置技巧

在resources目录下创建:

  • application-dev.yml(开发环境)
  • application-prod.yml(生产环境)
  • application.yml(主配置)

application.yml内容示例:

spring: profiles: active: dev # 默认使用开发环境 datasource: type: com.alibaba.druid.pool.DruidDataSource druid: initial-size: 5 min-idle: 5 max-active: 20 test-while-idle: true validation-query: SELECT 1

application-dev.yml配置开发数据库:

server: port: 8080 spring: datasource: url: jdbc:mysql://localhost:3306/dev_db?useSSL=false&serverTimezone=Asia/Shanghai username: dev_user password: dev123 driver-class-name: com.mysql.cj.jdbc.Driver

3.2 MyBatis配置详解

在application.yml继续添加:

mybatis: mapper-locations: classpath:mapper/*.xml type-aliases-package: com.example.demo.entity configuration: map-underscore-to-camel-case: true # 自动驼峰转换 default-fetch-size: 100 default-statement-timeout: 30

建议在测试类中添加这个配置检查:

@SpringBootTest class DatasourceTest { @Autowired DataSource dataSource; @Test void testConnection() throws SQLException { System.out.println("当前使用连接池:" + dataSource.getClass()); Connection conn = dataSource.getConnection(); System.out.println("连接实例:" + conn); conn.close(); } }

4. 三层架构实现增删改查

4.1 实体层设计

创建entity/User.java:

@Data @NoArgsConstructor @AllArgsConstructor public class User { private Long id; private String username; private String email; private LocalDateTime createTime; }

建议给时间字段加上注解:

@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") private LocalDateTime createTime;

4.2 Mapper层开发

先创建mapper/UserMapper.java:

@Mapper public interface UserMapper { int insert(User user); int updateById(User user); int deleteById(Long id); User selectById(Long id); List<User> selectAll(); }

然后在resources/mapper下创建UserMapper.xml:

<mapper namespace="com.example.demo.mapper.UserMapper"> <sql id="Base_Column_List"> id, username, email, create_time </sql> <insert id="insert" useGeneratedKeys="true" keyProperty="id"> INSERT INTO user(username, email) VALUES(#{username}, #{email}) </insert> <select id="selectById" resultType="User"> SELECT <include refid="Base_Column_List"/> FROM user WHERE id = #{id} </select> </mapper>

4.3 Service层业务逻辑

创建service/UserService.java:

public interface UserService { User createUser(UserDTO userDTO); User getUserById(Long id); List<User> listUsers(); void deleteUser(Long id); }

实现类中加入业务校验:

@Service @RequiredArgsConstructor public class UserServiceImpl implements UserService { private final UserMapper userMapper; @Override @Transactional(rollbackFor = Exception.class) public User createUser(UserDTO userDTO) { if (userMapper.existsByUsername(userDTO.getUsername())) { throw new BusinessException("用户名已存在"); } User user = new User(); BeanUtils.copyProperties(userDTO, user); user.setCreateTime(LocalDateTime.now()); userMapper.insert(user); return user; } }

4.4 Controller层RESTful设计

@RestController @RequestMapping("/api/users") @RequiredArgsConstructor public class UserController { private final UserService userService; @PostMapping public ResponseEntity<User> createUser(@Valid @RequestBody UserDTO userDTO) { User user = userService.createUser(userDTO); return ResponseEntity.created(URI.create("/users/"+user.getId())).body(user); } @GetMapping("/{id}") public User getUser(@PathVariable Long id) { return userService.getUserById(id); } }

建议统一返回格式:

@ControllerAdvice public class ResponseAdvice implements ResponseBodyAdvice<Object> { @Override public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) { if (body instanceof ApiResponse) { return body; } return ApiResponse.success(body); } }

5. 接口测试与调试技巧

5.1 Postman高级用法

创建测试集合时,建议按功能模块分组。比如:

  • 用户管理
  • 订单管理
  • 权限管理

在Tests标签页可以添加自动化断言:

pm.test("Status code is 200", function() { pm.response.to.have.status(200); }); pm.test("Response time is less than 200ms", function() { pm.expect(pm.response.responseTime).to.be.below(200); });

5.2 日志排查技巧

在application.yml中添加:

logging: level: root: info org.springframework.web: debug com.example.demo.mapper: trace # 打印SQL

开发时开启SQL日志:

# 显示带参数值的完整SQL mybatis.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl

5.3 单元测试示范

@SpringBootTest @AutoConfigureMockMvc class UserControllerTest { @Autowired private MockMvc mockMvc; @Test void shouldCreateUser() throws Exception { String json = """ { "username": "testuser", "email": "test@example.com" } """; mockMvc.perform(post("/api/users") .contentType(MediaType.APPLICATION_JSON) .content(json)) .andExpect(status().isCreated()) .andExpect(jsonPath("$.data.username").value("testuser")); } }

记得在测试类上加事务注解,避免污染数据库:

@Transactional @Rollback

6. 生产环境优化建议

6.1 Druid监控配置

spring: datasource: druid: stat-view-servlet: enabled: true login-username: admin login-password: admin reset-enable: false web-stat-filter: enabled: true exclusions: "*.js,*.gif,*.jpg,*.css,/druid/*"

访问 http://localhost:8080/druid 查看监控

6.2 MyBatis性能优化

  1. 批量操作:
@Insert("<script>" + "INSERT INTO user(username, email) VALUES " + "<foreach collection='list' item='item' separator=','>" + "(#{item.username}, #{item.email})" + "</foreach>" + "</script>") void batchInsert(List<User> users);
  1. 二级缓存配置:
<cache eviction="LRU" flushInterval="60000" size="512"/>

6.3 接口安全加固

添加Spring Security依赖:

<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency>

基础安全配置:

@Configuration @EnableWebSecurity public class SecurityConfig { @Bean public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { http .csrf().disable() .authorizeRequests() .antMatchers("/api/public/**").permitAll() .anyRequest().authenticated() .and() .httpBasic(); return http.build(); } }

7. 常见问题解决方案

问题1:MyBatis映射文件找不到

  • 检查mapper-locations路径是否正确
  • 确保resources目录标记为Resources Root
  • 在pom.xml中添加:
<build> <resources> <resource> <directory>src/main/resources</directory> <includes> <include>**/*.xml</include> </includes> </resource> </resources> </build>

问题2:数据库时区异常在连接字符串添加:

serverTimezone=Asia/Shanghai

问题3:Lombok不生效

  • 安装Lombok插件
  • 开启注解处理:Settings -> Build -> Annotation Processors

问题4:事务不回滚检查是否:

  1. 方法不是public
  2. 异常被catch没抛出
  3. 异常类型不是RuntimeException
  4. 没加@Transactional注解

8. 项目结构优化建议

推荐的分包方式:

com.example.demo ├── config # 配置类 ├── constant # 常量定义 ├── controller # 控制器 ├── service # 服务层 │ ├── impl # 服务实现 ├── mapper # MyBatis映射接口 ├── entity # 数据库实体 ├── dto # 数据传输对象 ├── vo # 视图对象 ├── util # 工具类 └── exception # 异常处理

在启动类添加扫描注解:

@SpringBootApplication @MapperScan("com.example.demo.mapper") @ComponentScan("com.example.demo") public class DemoApplication { public static void main(String[] args) { SpringApplication.run(DemoApplication.class, args); } }

对于大型项目,可以考虑模块化拆分:

demo-project ├── demo-common # 公共模块 ├── demo-dao # 数据访问层 ├── demo-service # 业务逻辑层 └── demo-web # Web接口层