SpringBoot学习日记 Day10:企业级博客系统开发实战(一)
一、项目启航:从零搭建企业级博客系统
今天开始真正意义上的企业级项目实战!我将把前9天学到的所有知识融会贯通,构建一个可部署的博客系统。这就像用乐高积木搭建城堡,每个模块都要严丝合缝。
二、项目初始化:打好坚实基础
1. 一键创建项目骨架
# 使用Spring Initializr快速创建项目
spring init --dependencies=web,data-jpa,mysql,security,validation,actuator,redis \--groupId=com.example --artifactId=blog-system \--name=BlogSystem --package-name=com.example.blog \--java-version=11
2. 项目结构设计
src/
├── main/
│ ├── java/com/example/blog/
│ │ ├── config/ # 配置类
│ │ ├── controller/ # 控制层
│ │ ├── entity/ # 实体类
│ │ ├── repository/ # 数据访问
│ │ ├── service/ # 服务层
│ │ ├── dto/ # 数据传输对象
│ │ ├── security/ # 安全相关
│ │ └── BlogApplication.java
│ └── resources/
│ ├── application.yml
│ ├── application-dev.yml
│ ├── application-prod.yml
│ └── static/
└── test/ # 测试代码
3. 多环境配置
application.yml(公共配置):
spring:profiles:active: devjackson:date-format: yyyy-MM-dd HH:mm:sstime-zone: GMT+8server:servlet:context-path: /apilogging:pattern:console: "%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n"application-dev.yml(开发环境):
spring:datasource:url: jdbc:mysql://localhost:3306/blog_dev?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghaiusername: rootpassword: 123456driver-class-name: com.mysql.cj.jdbc.Driverjpa:hibernate:ddl-auto: updateshow-sql: trueh2:console:enabled: falsedebug: true
三、核心技术集成:一站式配置
1. Swagger3文档配置
@Configuration
@OpenAPIDefinition(info = @Info(title = "博客系统API文档",version = "1.0",description = "企业级博客系统接口文档",contact = @Contact(name = "开发者", email = "dev@example.com"))
)
public class SwaggerConfig {@Beanpublic OpenAPI customOpenAPI() {return new OpenAPI().components(new Components().addSecuritySchemes("JWT", new SecurityScheme().type(SecurityScheme.Type.HTTP).scheme("bearer").bearerFormat("JWT"))).addSecurityItem(new SecurityRequirement().addList("JWT"));}
}
2. 统一响应体设计
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Result<T> {private Integer code;private String message;private T data;private Long timestamp;public static <T> Result<T> success(T data) {return new Result<>(200, "成功", data, System.currentTimeMillis());}public static <T> Result<T> error(Integer code, String message) {return new Result<>(code, message, null, System.currentTimeMillis());}
}
3. 全局异常处理增强
@RestControllerAdvice
@Slf4j
public class GlobalExceptionHandler {@ExceptionHandler(BusinessException.class)public Result<Void> handleBusinessException(BusinessException e) {log.warn("业务异常: {}", e.getMessage());return Result.error(e.getCode(), e.getMessage());}@ExceptionHandler(AccessDeniedException.class)public Result<Void> handleAccessDeniedException(AccessDeniedException e) {log.warn("权限拒绝: {}", e.getMessage());return Result.error(403, "没有访问权限");}@ExceptionHandler(Exception.class)public Result<Void> handleException(Exception e) {log.error("系统异常: ", e);return Result.error(500, "系统繁忙,请稍后再试");}
}
四、用户模块:安全与认证体系
1. 用户实体设计
@Data
@Entity
@Table(name = "users")
@Where(clause = "is_deleted = 0")
public class User {@Id@GeneratedValue(strategy = GenerationType.IDENTITY)private Long id;@Column(unique = true, nullable = false)private String username;@Column(nullable = false)private String password;@Column(unique = true)private String email;private String avatar;@Enumerated(EnumType.STRING)private UserRole role = UserRole.USER;@CreationTimestampprivate LocalDateTime createTime;@UpdateTimestampprivate LocalDateTime updateTime;private Boolean isDeleted = false;public enum UserRole {USER, ADMIN}
}
2. JWT认证体系
@Component
@RequiredArgsConstructor
public class JwtAuthenticationFilter extends OncePerRequestFilter {private final JwtUtils jwtUtils;private final UserDetailsService userDetailsService;@Overrideprotected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {try {String jwt = parseJwt(request);if (jwt != null && jwtUtils.validateJwtToken(jwt)) {String username = jwtUtils.getUserNameFromJwtToken(jwt);UserDetails userDetails = userDetailsService.loadUserByUsername(username);UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));SecurityContextHolder.getContext().setAuthentication(authentication);}} catch (Exception e) {logger.error("Cannot set user authentication: {}", e);}filterChain.doFilter(request, response);}private String parseJwt(HttpServletRequest request) {String headerAuth = request.getHeader("Authorization");if (StringUtils.hasText(headerAuth) && headerAuth.startsWith("Bearer ")) {return headerAuth.substring(7);}return null;}
}
3. 用户服务实现
@Service
@RequiredArgsConstructor
public class UserService {private final UserRepository userRepository;private final PasswordEncoder passwordEncoder;private final JwtUtils jwtUtils;@Transactionalpublic User register(RegisterDTO dto) {if (userRepository.existsByUsername(dto.getUsername())) {throw new BusinessException("用户名已存在");}if (userRepository.existsByEmail(dto.getEmail())) {throw new BusinessException("邮箱已存在");}User user = new User();user.setUsername(dto.getUsername());user.setPassword(passwordEncoder.encode(dto.getPassword()));user.setEmail(dto.getEmail());return userRepository.save(user);}public String login(LoginDTO dto) {User user = userRepository.findByUsername(dto.getUsername()).orElseThrow(() -> new BusinessException("用户不存在"));if (!passwordEncoder.matches(dto.getPassword(), user.getPassword())) {throw new BusinessException("密码错误");}return jwtUtils.generateToken(user.getUsername());}
}
五、文章模块:核心业务实现
1. 文章实体设计
@Data
@Entity
@Table(name = "articles")
public class Article {@Id@GeneratedValue(strategy = GenerationType.IDENTITY)private Long id;@Column(nullable = false)private String title;@Column(columnDefinition = "TEXT")private String content;private String summary;@ManyToOne@JoinColumn(name = "user_id")private User author;private Integer viewCount = 0;@Enumerated(EnumType.STRING)private ArticleStatus status = ArticleStatus.DRAFT;@CreationTimestampprivate LocalDateTime createTime;@UpdateTimestampprivate LocalDateTime updateTime;public enum ArticleStatus {DRAFT, PUBLISHED, DELETED}
}
2. 文章服务层
@Service
@RequiredArgsConstructor
@Transactional(readOnly = true)
public class ArticleService {private final ArticleRepository articleRepository;public Page<Article> getPublishedArticles(Pageable pageable) {return articleRepository.findByStatus(ArticleStatus.PUBLISHED, pageable);}public Article getArticleById(Long id) {return articleRepository.findById(id).orElseThrow(() -> new BusinessException("文章不存在"));}@Transactionalpublic Article createArticle(Article article, User author) {article.setAuthor(author);article.setStatus(ArticleStatus.DRAFT);return articleRepository.save(article);}@Transactionalpublic Article updateArticle(Long id, Article updatedArticle, User currentUser) {Article article = getArticleById(id);if (!article.getAuthor().getId().equals(currentUser.getId())) {throw new BusinessException("没有修改权限");}article.setTitle(updatedArticle.getTitle());article.setContent(updatedArticle.getContent());article.setSummary(updatedArticle.getSummary());return articleRepository.save(article);}
}
六、Docker化部署:生产环境准备
1. Dockerfile配置
# 构建阶段
FROM maven:3.8.4-openjdk-11 AS builder
WORKDIR /app
COPY pom.xml .
COPY src ./src
RUN mvn package -DskipTests# 运行阶段
FROM openjdk:11-jre-slim
WORKDIR /app# 安装时区配置
RUN apt-get update && apt-get install -y tzdata
ENV TZ=Asia/Shanghai# 复制应用
COPY --from=builder /app/target/blog-system-0.0.1.jar app.jar# 创建非root用户
RUN groupadd -r spring && useradd -r -g spring spring
USER springEXPOSE 8080
ENTRYPOINT ["java", "-jar", "/app.jar"]
2. Docker Compose编排
version: '3.8'services:app:build: .ports:- "8080:8080"environment:- SPRING_PROFILES_ACTIVE=prod- DB_PASSWORD=mysql123depends_on:- mysql- redisrestart: unless-stoppedmysql:image: mysql:8.0environment:MYSQL_ROOT_PASSWORD: rootpassMYSQL_DATABASE: blog_prodMYSQL_USER: blog_userMYSQL_PASSWORD: mysql123volumes:- mysql_data:/var/lib/mysqlrestart: unless-stoppedredis:image: redis:6.2-alpineports:- "6379:6379"volumes:- redis_data:/datarestart: unless-stoppedvolumes:mysql_data:redis_data:
七、今日成果验收
✅ 已完成功能:
- 项目骨架搭建和多环境配置
- Swagger3 API文档集成
- 统一响应体和异常处理
- JWT认证安全体系
- 用户注册登录功能
- 文章基础CRUD操作
- Docker化部署配置
🚀 启动验证:
# 开发环境启动
mvn spring-boot:run -Dspring-boot.run.profiles=dev
# Docker编译运行
docker-compose up --build
# 访问验证
curl http://localhost:8080/api/v1/articles
八、明日开发计划
1. 评论系统实现:嵌套评论、回复功能
2. 权限控制增强:角色权限、操作拦截
3. 数据统计功能:浏览量统计、用户活跃度
4. 缓存优化:Redis缓存热点数据
5. 前端界面集成:Vue/React前端项目
今日感悟:企业级项目开发就像建造大楼,地基(项目结构)要牢固,管线(配置集成)要规范,每个模块(功能实现)都要精心设计。明天继续完善这座"大楼"!
如果遇到任何问题,欢迎在评论区交流讨论。完整代码已上传GitHub,需要的朋友可以私信获取!