从零到一:使用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 1application-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.Driver3.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.StdOutImpl5.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 @Rollback6. 生产环境优化建议
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性能优化
- 批量操作:
@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);- 二级缓存配置:
<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:事务不回滚检查是否:
- 方法不是public
- 异常被catch没抛出
- 异常类型不是RuntimeException
- 没加@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接口层