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

从零到一:使用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 17LTS版本打包方式选Jar微服务架构推荐Java版本保持与SDK一致依赖先勾选Spring WebWeb MVC支持MyBatis Framework数据库支持MySQL Driver数据库驱动点击生成后你会得到一个标准化的项目结构。我习惯把自动生成的README.md和HELP.md删掉保持项目干净。2.2 补充必要依赖打开pom.xml在 节点添加这些关键依赖!-- Druid连接池 -- dependency groupIdcom.alibaba/groupId artifactIddruid-spring-boot-starter/artifactId version1.2.8/version /dependency !-- Lombok简化代码 -- dependency groupIdorg.projectlombok/groupId artifactIdlombok/artifactId optionaltrue/optional /dependency !-- 测试用H2数据库 -- dependency groupIdcom.h2database/groupId artifactIdh2/artifactId scopetest/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?useSSLfalseserverTimezoneAsia/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.javaData 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.javaMapper public interface UserMapper { int insert(User user); int updateById(User user); int deleteById(Long id); User selectById(Long id); ListUser selectAll(); }然后在resources/mapper下创建UserMapper.xmlmapper namespacecom.example.demo.mapper.UserMapper sql idBase_Column_List id, username, email, create_time /sql insert idinsert useGeneratedKeystrue keyPropertyid INSERT INTO user(username, email) VALUES(#{username}, #{email}) /insert select idselectById resultTypeUser SELECT include refidBase_Column_List/ FROM user WHERE id #{id} /select /mapper4.3 Service层业务逻辑创建service/UserService.javapublic interface UserService { User createUser(UserDTO userDTO); User getUserById(Long id); ListUser 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 ResponseEntityUser 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 ResponseBodyAdviceObject { 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-implorg.apache.ibatis.logging.stdout.StdOutImpl5.3 单元测试示范SpringBootTest AutoConfigureMockMvc class UserControllerTest { Autowired private MockMvc mockMvc; Test void shouldCreateUser() throws Exception { String json { username: testuser, email: testexample.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 collectionlist itemitem separator, (#{item.username}, #{item.email}) /foreach /script) void batchInsert(ListUser users);二级缓存配置cache evictionLRU flushInterval60000 size512/6.3 接口安全加固添加Spring Security依赖dependency groupIdorg.springframework.boot/groupId artifactIdspring-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. 常见问题解决方案问题1MyBatis映射文件找不到检查mapper-locations路径是否正确确保resources目录标记为Resources Root在pom.xml中添加build resources resource directorysrc/main/resources/directory includes include**/*.xml/include /includes /resource /resources /build问题2数据库时区异常在连接字符串添加serverTimezoneAsia/Shanghai问题3Lombok不生效安装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接口层