去年刚入职某互联网公司时,我发现自己对Spring Boot的理解还停留在学校实验室的水平。为了快速适应企业级开发,我决定从零开始搭建一个完整的博客系统。这个项目不仅帮我梳理了Spring Boot的核心技术栈,后来还意外成为了学弟学妹们最爱的"期末作业参考模板"。
选择博客系统作为练手项目有几个优势:首先业务场景明确,包含典型的CRUD操作;其次技术栈覆盖面广,能练习到前后端交互、数据库设计等核心技能;最重要的是,这类项目有大量可借鉴的开源实现,遇到问题时容易找到解决方案。
Spring Boot的自动配置特性让开发者能快速搭建项目骨架。相比传统SSM框架需要手动配置大量XML,Spring Boot通过starter依赖就能集成常用组件。例如引入spring-boot-starter-web就自动配置了Tomcat和Spring MVC,这对新手特别友好。
MyBatis-Plus作为MyBatis的增强工具,提供了以下实用功能:
实测在开发文章管理模块时,使用MyBatis-Plus比纯MyBatis减少了约40%的样板代码。
虽然项目前端用了简单的Thymeleaf模板,但后端完全按照RESTful规范设计。这种架构有两大好处:
这里分享一个接口设计的小技巧:所有API响应都封装成统一格式:
java复制public class ResDTO<T> {
private Integer code; // 状态码
private String msg; // 提示信息
private T data; // 业务数据
// 成功静态方法
public static <T> ResDTO<T> success(T data) {
ResDTO<T> resDTO = new ResDTO<>();
resDTO.setCode(200);
resDTO.setMsg("success");
resDTO.setData(data);
return resDTO;
}
}
原始代码中的文章查询没有做分页处理,当数据量增大时会导致性能问题。改进方案是集成MyBatis-Plus的分页插件:
java复制@Configuration
public class MyBatisPlusConfig {
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new PaginationInnerInterceptor());
return interceptor;
}
}
java复制@GetMapping("/list")
public ResDTO<Page<Article>> list(
@RequestParam(defaultValue = "1") Integer pageNum,
@RequestParam(defaultValue = "10") Integer pageSize) {
Page<Article> page = new Page<>(pageNum, pageSize);
return ResDTO.success(articleService.page(page));
}
新手常犯的错误是直接存储明文密码。正确做法是使用Spring Security的BCryptPasswordEncoder:
java复制@Service
public class UserServiceImpl implements UserService {
@Autowired
private PasswordEncoder passwordEncoder;
@Override
public void register(UserReqDTO userReqDTO) {
User user = new User();
user.setPassword(passwordEncoder.encode(userReqDTO.getPassword()));
// 其他字段设置...
userMapper.insert(user);
}
}
BCrypt会自动加盐处理,相同密码每次加密结果都不同,有效防止彩虹表攻击。
除了项目已有的主键索引,还应该为常用查询字段添加索引:
sql复制-- 文章表按创建时间倒序查询
ALTER TABLE article ADD INDEX idx_create_time (create_time DESC);
-- 用户登录时需要按username或email查询
ALTER TABLE user ADD INDEX idx_username_password (username, password);
ALTER TABLE user ADD INDEX idx_email_password (email, password);
有几个容易踩坑的细节:
企业项目通常需要区分开发、测试、生产环境。Spring Boot支持通过profile指定配置:
code复制application-dev.properties # 开发环境
application-test.properties # 测试环境
application-prod.properties # 生产环境
bash复制mvn spring-boot:run -Dspring-boot.run.profiles=prod
推荐使用Swagger自动生成API文档,只需添加依赖:
xml复制<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-boot-starter</artifactId>
<version>3.0.0</version>
</dependency>
配置类示例:
java复制@Configuration
@EnableSwagger2
public class SwaggerConfig {
@Bean
public Docket api() {
return new Docket(DocumentationType.SWAGGER_2)
.select()
.apis(RequestHandlerSelectors.basePackage("org.example.controller"))
.paths(PathSelectors.any())
.build();
}
}
症状:查询返回的字段值为null
解决方案:
properties复制mybatis.configuration.map-underscore-to-camel-case=true
典型场景:在同一个类中方法A调用方法B,方法B的事务注解不生效
原因:Spring事务基于AOP实现,自调用会绕过代理
解决方案:
如果想进一步提升项目完整度,可以考虑:
我在实际开发中遇到过最棘手的问题是N+1查询问题。当查询文章列表时,如果每条文章都要单独查询作者信息,会产生大量SQL。解决方案是使用MyBatis的@Many注解实现一对多关联查询,或者直接写join查询SQL。