1. 项目背景与核心需求
高校校园交流墙这类应用在大学生群体中有着广泛的使用场景。记得我刚上大学时,学生们还在用贴吧、QQ群来发布二手交易、活动通知和失物招领信息,信息分散且难以管理。现在基于SpringBoot开发一个专门的校园交流平台,不仅能解决信息聚合的问题,还能针对校园场景做深度定制。
这个项目的核心要解决三个问题:
- 信息分类管理:课程讨论、二手交易、活动通知等不同类型内容需要清晰分类
- 用户身份验证:确保发帖人确实是本校师生
- 内容安全过滤:防止不当言论和垃圾信息
2. 技术架构设计
2.1 基础框架选型
选择SpringBoot 3.1.5版本作为基础框架,这个版本在性能和安全方面都有显著提升。配套使用:
- Spring Security 6.1.5:处理认证授权
- MyBatis-Plus 3.5.3.1:简化数据库操作
- Redis 7.0:缓存热点数据和会话管理
提示:SpringBoot 3.x需要JDK17+,建议使用Amazon Corretto-17作为生产环境JDK
2.2 数据库设计
采用MySQL 8.0作为主数据库,主要表结构设计:
CREATE TABLE `post` ( `id` bigint NOT NULL AUTO_INCREMENT, `title` varchar(100) NOT NULL, `content` text NOT NULL, `category_id` int NOT NULL COMMENT '1-课程讨论 2-二手交易 3-失物招领', `user_id` bigint NOT NULL, `view_count` int DEFAULT '0', `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (`id`), KEY `idx_category` (`category_id`), KEY `idx_user` (`user_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;2.3 安全方案设计
认证流程:
- 学生通过学校统一身份认证系统登录
- 教师使用工号+密码+短信验证码登录
- 所有接口都需要携带JWT token
内容安全:
- 使用HanLP进行敏感词过滤
- 图片上传前进行鉴黄检测
- 夜间23:00-6:00发帖需要额外验证
3. 核心功能实现
3.1 帖子发布模块
@RestController @RequestMapping("/api/post") public class PostController { @Autowired private PostService postService; @PostMapping public Result<Long> createPost(@Valid @RequestBody CreatePostDTO dto) { Long userId = SecurityUtil.getCurrentUserId(); return Result.success(postService.createPost(userId, dto)); } @GetMapping("/{id}") public Result<PostVO> getPost(@PathVariable Long id) { return Result.success(postService.getPost(id)); } }3.2 内容搜索实现
使用Elasticsearch 8.7实现全文检索,关键配置:
spring: elasticsearch: uris: http://localhost:9200 connection-timeout: 1s socket-timeout: 30s搜索接口实现:
public interface PostSearchRepository extends ElasticsearchRepository<PostDocument, Long> { Page<PostDocument> findByTitleOrContent(String title, String content, Pageable pageable); @Query("{\"bool\": {\"must\": [{\"match\": {\"title\": \"?0\"}}]}}") Page<PostDocument> findByTitleUsingCustomQuery(String title, Pageable pageable); }3.3 实时通知功能
使用WebSocket实现新帖子通知:
@Configuration @EnableWebSocketMessageBroker public class WebSocketConfig implements WebSocketMessageBrokerConfigurer { @Override public void configureMessageBroker(MessageBrokerRegistry config) { config.enableSimpleBroker("/topic"); config.setApplicationDestinationPrefixes("/app"); } @Override public void registerStompEndpoints(StompEndpointRegistry registry) { registry.addEndpoint("/ws") .setAllowedOriginPatterns("*") .withSockJS(); } }4. 部署与性能优化
4.1 Docker部署方案
FROM amazoncorretto:17-alpine-jdk VOLUME /tmp COPY target/campus-wall-*.jar app.jar ENTRYPOINT ["java","-jar","/app.jar"]启动命令:
docker build -t campus-wall . docker run -d -p 8080:8080 --name wall \ -e SPRING_PROFILES_ACTIVE=prod \ -e SPRING_DATASOURCE_URL=jdbc:mysql://mysql:3306/campus_wall \ campus-wall4.2 缓存策略设计
- 热点帖子缓存:
@Cacheable(value = "posts", key = "#postId") public PostVO getPost(Long postId) { return postMapper.selectById(postId); }- 分页查询缓存:
@Cacheable(value = "postPages", key = "#categoryId+'-'+#page+'-'+#size") public Page<PostVO> getPostPage(Integer categoryId, int page, int size) { Page<Post> p = new Page<>(page, size); LambdaQueryWrapper<Post> query = new LambdaQueryWrapper<>(); query.eq(Post::getCategoryId, categoryId) .orderByDesc(Post::getCreateTime); return postMapper.selectPage(p, query); }5. 踩坑经验分享
文件上传超时问题:
- 默认情况下SpringBoot文件上传有1MB大小限制
- 需要配置:
spring.servlet.multipart.max-file-size=10MB - 如果使用Nginx反向代理,还需要设置:
client_max_body_size 10m
MyBatis-Plus分页失效:
- 必须注册分页插件:
@Bean public MybatisPlusInterceptor mybatisPlusInterceptor() { MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor(); interceptor.addInnerInterceptor(new PaginationInnerInterceptor()); return interceptor; }跨域问题解决方案:
@Configuration public class CorsConfig implements WebMvcConfigurer { @Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/**") .allowedOrigins("*") .allowedMethods("*") .maxAge(3600); } }
这个项目从技术选型到部署上线大约用了3周时间,最大的收获是理解了校园场景下的特殊需求。比如学生更关注界面简洁和响应速度,而管理员则更重视内容审核和数据统计。下次如果再开发类似项目,我会优先考虑引入消息队列来处理高并发场景下的通知发送。