本文最后更新于 303 天前,如有错误请邮件至 zhiligyi222na@gmail.com
一、安装需要的环境
下载并安装npm
npm -v
使用create-vue脚手架来初始化Vue 3项目
npm create vue@latest .
选择配置

安装项目依赖
npm install
Vue前端项目已经准备就绪,现在让我们创建Spring Boot后端项目。我们将使用Spring Initializr来初始化项目
powershell -Command Invoke-WebRequest -Uri 'https://start.spring.io/starter.zip?type=maven-project&language=java&platformVersion=3.3.2&packaging=jar&jvmVersion=17&groupId=com.example&artifactId=blog-backend&name=blog-backend&description=Blog%20Backend%20with%20Spring%20Boot&packageName=com.example.blog&dependencies=web,data-jpa,mysql,security,lombok' -OutFile blog-backend.zip
解压
powershell -Command Expand-Archive -Path blog-backend.zip -DestinationPath .\blog-backend
powershell -Command Expand-Archive -Path blog-backend.zip -DestinationPath ./blog-backend -Force
打开application.properties配置项
# 数据库配置
spring.datasource.url=jdbc:mysql://localhost:3306/blog_db?useSSL=false&serverTimezone=UTC&allowPublicKeyRetrieval=true
spring.datasource.username=root
spring.datasource.password=password
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
# JPA配置
spring.jpa.hibernate.ddl-auto=update
spring.jpa.show-sql=true
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL8Dialect
# 服务器配置
server.port=8080
# 允许跨域
spring.mvc.cors.allowed-origins=http://localhost:5173
spring.mvc.cors.allowed-methods=GET,POST,PUT,DELETE,OPTIONS
spring.mvc.cors.allowed-headers=*
接下来,我们需要创建实体类、仓库接口、服务类和控制器类等组件。让我们先创建所需的包结构。
powershell -Command mkdir -Path d:\code\MyBlog\blog-backend\src\main\java\com\example\blog\model
powershell -Command mkdir -Path d:\code\MyBlog\blog-backend\src\main\java\com\example\blog\repository
powershell -Command mkdir -Path d:\code\MyBlog\blog-backend\src\main\java\com\example\blog\service
powershell -Command mkdir -Path d:\code\MyBlog\blog-backend\src\main\java\com\example\blog\controller
powershell -Command mkdir -Path d:\code\MyBlog\blog-backend\src\main\java\com\example\blog\config
powershell -Command mkdir -Path d:\code\MyBlog\blog-backend\src\main\java\com\example\blog\dto
所有必要的包结构都已创建完成。现在,让我们开始实现后端的核心功能。首先,我们需要创建博客文章的实体类。
创建blog-backend\src\main\java\com\example\blog\model\Post.java实体类,我们需要创建博客文章的实体类。
package com.example.blog.model;
import jakarta.persistence.*;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.time.LocalDateTime;
@Entity
@Table(name = "posts")
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Post {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(nullable = false, length = 255)
private String title;
@Column(nullable = false, columnDefinition = "TEXT")
private String content;
@Column(nullable = false, length = 100)
private String author;
@Column(updatable = false)
private LocalDateTime createdAt;
private LocalDateTime updatedAt;
@PrePersist
protected void onCreate() {
createdAt = LocalDateTime.now();
updatedAt = LocalDateTime.now();
}
@PreUpdate
protected void onUpdate() {
updatedAt = LocalDateTime.now();
}
}
创建blog-backend\src\main\java\com\example\blog\repository\PostRepository.java接口,用于数据库操作。
package com.example.blog.repository;
import com.example.blog.model.Post;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import java.util.List;
@Repository
public interface PostRepository extends JpaRepository<Post, Long> {
// 按照创建时间降序获取所有文章
List<Post> findAllByOrderByCreatedAtDesc();
// 根据作者查找文章
List<Post> findByAuthor(String author);
// 根据标题模糊搜索
List<Post> findByTitleContaining(String keyword);
}
创建blog-backend\src\main\java\com\example\blog\service\PostService.java类来实现业务逻辑。
package com.example.blog.service;
import com.example.blog.model.Post;
import com.example.blog.repository.PostRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.Optional;
@Service
public class PostService {
private final PostRepository postRepository;
@Autowired
public PostService(PostRepository postRepository) {
this.postRepository = postRepository;
}
// 获取所有文章
public List<Post> getAllPosts() {
return postRepository.findAllByOrderByCreatedAtDesc();
}
// 获取指定id的文章
public Optional<Post> getPostById(Long id) {
return postRepository.findById(id);
}
// 创建新文章
public Post createPost(Post post) {
return postRepository.save(post);
}
// 更新文章
public Post updatePost(Long id, Post postDetails) {
Optional<Post> post = postRepository.findById(id);
if (post.isPresent()) {
Post updatedPost = post.get();
updatedPost.setTitle(postDetails.getTitle());
updatedPost.setContent(postDetails.getContent());
updatedPost.setAuthor(postDetails.getAuthor());
return postRepository.save(updatedPost);
} else {
throw new RuntimeException("Post not found with id: " + id);
}
}
// 删除文章
public void deletePost(Long id) {
postRepository.deleteById(id);
}
// 根据作者查找文章
public List<Post> getPostsByAuthor(String author) {
return postRepository.findByAuthor(author);
}
// 根据标题搜索文章
public List<Post> searchPostsByTitle(String keyword) {
return postRepository.findByTitleContaining(keyword);
}
}
创建blog-backend\src\main\java\com\example\blog\controller\PostController.java类来处理HTTP请求,提供RESTful API接口。
package com.example.blog.controller;
import com.example.blog.model.Post;
import com.example.blog.service.PostService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.util.List;
import java.util.Optional;
@RestController
@RequestMapping("/api/posts")
public class PostController {
private final PostService postService;
@Autowired
public PostController(PostService postService) {
this.postService = postService;
}
// 获取所有文章
@GetMapping
public ResponseEntity<List<Post>> getAllPosts() {
List<Post> posts = postService.getAllPosts();
return new ResponseEntity<>(posts, HttpStatus.OK);
}
// 获取指定id的文章
@GetMapping("/{id}")
public ResponseEntity<Post> getPostById(@PathVariable Long id) {
Optional<Post> post = postService.getPostById(id);
return post.map(value -> new ResponseEntity<>(value, HttpStatus.OK))
.orElseGet(() -> new ResponseEntity<>(HttpStatus.NOT_FOUND));
}
// 创建新文章
@PostMapping
public ResponseEntity<Post> createPost(@RequestBody Post post) {
Post createdPost = postService.createPost(post);
return new ResponseEntity<>(createdPost, HttpStatus.CREATED);
}
// 更新文章
@PutMapping("/{id}")
public ResponseEntity<Post> updatePost(@PathVariable Long id, @RequestBody Post postDetails) {
try {
Post updatedPost = postService.updatePost(id, postDetails);
return new ResponseEntity<>(updatedPost, HttpStatus.OK);
} catch (RuntimeException e) {
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
}
}
// 删除文章
@DeleteMapping("/{id}")
public ResponseEntity<Void> deletePost(@PathVariable Long id) {
postService.deletePost(id);
return new ResponseEntity<>(HttpStatus.NO_CONTENT);
}
// 根据作者查找文章
@GetMapping("/author/{author}")
public ResponseEntity<List<Post>> getPostsByAuthor(@PathVariable String author) {
List<Post> posts = postService.getPostsByAuthor(author);
return new ResponseEntity<>(posts, HttpStatus.OK);
}
// 根据标题搜索文章
@GetMapping("/search")
public ResponseEntity<List<Post>> searchPostsByTitle(@RequestParam String keyword) {
List<Post> posts = postService.searchPostsByTitle(keyword);
return new ResponseEntity<>(posts, HttpStatus.OK);
}
}
后端的核心功能类已经创建完成。接下来,我们需要配置Spring Security,以确保API的安全性。让我们创建一个blog-backend\src\main\java\com\example\blog\config\SecurityConfig.java类。
package com.example.blog.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
import org.springframework.security.web.SecurityFilterChain;
@Configuration
@EnableWebSecurity
public class SecurityConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.csrf(AbstractHttpConfigurer::disable)
.authorizeHttpRequests(auth -> auth
.requestMatchers("/api/posts/**").permitAll()
.anyRequest().authenticated()
);
return http.build();
}
}









