瑞萨 IOT-RA6M4 开发板运行 RT-Thread:BSP 快速上手、FSP 配置与 env 进阶指南
2026/9/25 5:10:03
视频看了几百小时还迷糊?关注我,几分钟让你秒懂!
很多刚入门 Java 的小伙伴在学完 Spring Boot 基础后,常常不知道如何实战。而“个人博客系统”是一个非常经典又实用的小型全栈项目:
今天我们就先聚焦后端部分,用Spring Boot + MyBatis + MySQL搭建一个简洁但完整的博客 API 接口服务。
假设你是博主小明,想搭建一个自己的技术博客网站,需要以下基本功能:
注意:本文只实现后端接口,前端 Vue 部分我们后续再讲。
| 技术 | 作用 |
|---|---|
| Spring Boot 3.x | 快速构建 Web 应用 |
| MyBatis-Plus | 简化数据库 CRUD 操作 |
| MySQL 8.0 | 存储文章和分类数据 |
| Lombok | 自动生成 getter/setter/toString |
| Hutool(可选) | 工具类库,简化开发 |
-- 博客分类表 CREATE TABLE blog_category ( id BIGINT AUTO_INCREMENT PRIMARY KEY, name VARCHAR(50) NOT NULL UNIQUE COMMENT '分类名称' ); -- 博客文章表 CREATE TABLE blog_post ( id BIGINT AUTO_INCREMENT PRIMARY KEY, title VARCHAR(200) NOT NULL, content TEXT NOT NULL, category_id BIGINT NOT NULL, create_time DATETIME DEFAULT CURRENT_TIMESTAMP, update_time DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, FOREIGN KEY (category_id) REFERENCES blog_category(id) );依赖选择:
application.yml配置spring: datasource: url: jdbc:mysql://localhost:3306/blog_db?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai username: root password: your_password driver-class-name: com.mysql.cj.jdbc.Driver mybatis-plus: configuration: map-underscore-to-camel-case: true global-config: db-config: id-type: auto// Category.java @Data @TableName("blog_category") public class Category { @TableId(type = IdType.AUTO) private Long id; private String name; } // Post.java @Data @TableName("blog_post") public class Post { @TableId(type = IdType.AUTO) private Long id; private String title; private String content; private Long categoryId; private LocalDateTime createTime; private LocalDateTime updateTime; // 用于返回时携带分类名称(非数据库字段) @TableField(exist = false) private String categoryName; }@Mapper public interface CategoryMapper extends BaseMapper<Category> {} @Mapper public interface PostMapper extends BaseMapper<Post> {}@Service public class PostService { @Autowired private PostMapper postMapper; @Autowired private CategoryMapper categoryMapper; public List<Post> getAllPosts() { List<Post> posts = postMapper.selectList(null); // 补充分类名称 for (Post post : posts) { Category category = categoryMapper.selectById(post.getCategoryId()); if (category != null) { post.setCategoryName(category.getName()); } } return posts; } public Post getPostById(Long id) { Post post = postMapper.selectById(id); if (post != null) { Category category = categoryMapper.selectById(post.getCategoryId()); post.setCategoryName(category != null ? category.getName() : "未知"); } return post; } public boolean savePost(Post post) { return postMapper.insert(post) > 0; } public boolean updatePost(Post post) { return postMapper.updateById(post) > 0; } public boolean deletePost(Long id) { return postMapper.deleteById(id) > 0; } }@RestController @RequestMapping("/api/posts") public class PostController { @Autowired private PostService postService; @GetMapping public ResponseEntity<List<Post>> listAll() { return ResponseEntity.ok(postService.getAllPosts()); } @GetMapping("/{id}") public ResponseEntity<Post> getById(@PathVariable Long id) { Post post = postService.getPostById(id); if (post == null) { return ResponseEntity.notFound().build(); } return ResponseEntity.ok(post); } @PostMapping public ResponseEntity<String> create(@RequestBody Post post) { if (postService.savePost(post)) { return ResponseEntity.ok("文章创建成功"); } return ResponseEntity.badRequest().body("创建失败"); } @PutMapping("/{id}") public ResponseEntity<String> update(@PathVariable Long id, @RequestBody Post post) { post.setId(id); if (postService.updatePost(post)) { return ResponseEntity.ok("更新成功"); } return ResponseEntity.badRequest().body("更新失败"); } @DeleteMapping("/{id}") public ResponseEntity<String> delete(@PathVariable Long id) { if (postService.deletePost(id)) { return ResponseEntity.ok("删除成功"); } return ResponseEntity.badRequest().body("删除失败"); } }// 错误示范! @GetMapping("/bad") public List<Post> badExample() { return postMapper.selectList(null); // 耦合严重,无法复用,难测试 }✅ 正确做法:分层架构(Controller → Service → Mapper),职责清晰。
// 如果 categoryId 对应的分类不存在,category.getName() 会 NPE! post.setCategoryName(category.getName());✅ 正确做法:判空处理,或使用 Optional。
有的接口返回String,有的返回Map,前端很难处理。
✅ 正确做法:统一封装响应体(如Result<T>),但为简化本例暂未使用。
blog_db数据库存在;mybatis-plus-boot-starter,不是普通 MyBatis;DATETIME对应 Java 的LocalDateTime(Spring Boot 2.7+ 支持自动转换);@CrossOrigin临时解决,生产环境应配置网关或 Nginx。后端 API 已就绪!接下来你可以:
/api/posts接口;视频看了几百小时还迷糊?关注我,几分钟让你秒懂!