一、项目背景与意义
随着城市化进程的加快和生活节奏的提速,宠物(尤其是猫、狗等萌宠)已成为越来越多家庭的重要成员。然而,宠物主人在饲养过程中面临着社交需求、知识获取、宠物丢失寻回等诸多痛点。传统的线下宠物社群和寻宠启事方式效率低下、信息传播范围有限。
“萌宠”社交与寻宠平台旨在利用互联网技术,构建一个集宠物社交、知识分享、寻宠互助、周边服务于一体的综合性平台。其核心意义在于:
- 构建宠物主人社区:为宠物主人提供一个分享养宠心得、展示宠物日常、结识同城宠友的线上空间,缓解孤独感,增强归属感。
- 提升寻宠效率与成功率:通过基于地理位置(LBS)的实时信息发布与推送,一旦宠物走失,可迅速将寻宠启事扩散至周边用户,形成“全民寻宠”网络,极大提高找回概率。
- 整合宠物服务生态:连接宠物医院、美容店、商店、寄养家庭等周边服务,为用户提供一站式解决方案。
- 技术实践价值:该项目综合运用了Spring Boot、MyBatis、Redis、Elasticsearch、WebSocket、第三方地图API等主流技术栈,是一个典型的中大型全栈Web应用,对学习者掌握企业级开发流程、微服务架构思想具有重要实践意义。
二、技术栈选型
本项目采用前后端分离架构,后端基于Spring Boot构建。
后端技术栈
- 核心框架:Spring Boot 2.7.x
- 安全框架:Spring Security + JWT (JSON Web Token)
- 数据持久层:MyBatis-Plus (简化CRUD操作)
- 数据库:MySQL 8.0 (主业务数据) + Redis 7.x (缓存、会话、验证码)
- 搜索与推荐:Elasticsearch 7.x (用于寻宠启事、帖子、用户的全文搜索与智能推荐)
- 实时通信:WebSocket (STOMP协议,用于聊天、系统通知)
- 文件存储:阿里云OSS / 腾讯云COS (存储用户头像、宠物图片、帖子图片)
- 第三方服务:
- 高德地图/腾讯地图API (LBS定位、地理围栏、路径规划)
- 短信服务 (阿里云短信,用于注册、登录验证)
- 对象存储服务 (如上所述)
- 消息队列:RabbitMQ (异步处理图片审核、消息推送、数据同步至ES等任务)
- API文档:SpringDoc OpenAPI 3 (Swagger UI)
- 部署与监控:Docker, Nginx, Spring Boot Admin, Prometheus + Grafana
前端技术栈 (简述)
- 框架:Vue 3 + TypeScript + Vite
- UI组件库:Element Plus / Ant Design Vue
- 状态管理:Pinia
- 路由:Vue Router
- HTTP客户端:Axios
- 地图组件:基于高德/腾讯地图JS API封装的Vue组件
- 实时通信:SockJS-client + stompjs
三、核心功能模块设计
1. 用户系统
- 注册/登录(手机号+验证码、密码、第三方登录)
- JWT令牌认证与刷新
- 用户个人资料管理(头像、昵称、养宠信息)
- 宠物档案管理(添加/编辑宠物信息、上传照片)
2. 社交模块
- 动态/帖子:发布图文/视频动态,支持点赞、评论、收藏、分享。
- 关注/粉丝系统:用户间互相关注,形成社交网络。
- 话题/圈子:按宠物品种、疾病、行为训练等创建话题圈子。
- 私信聊天:基于WebSocket的实时一对一、群组聊天。
3. 寻宠互助模块 (核心)
- 发布寻宠启事:填写丢失宠物信息、最后出现地点(地图选点)、时间、联系方式、悬赏金额等,并上传宠物照片。
- LBS信息推送:根据启事发布地点,向平台内一定半径范围内的其他用户推送通知。
- 线索提供与反馈:其他用户可在启事下留言提供线索,或通过私信联系发布者。
- 启事状态管理:标记为“寻找中”、“已找到”、“已结束”。
- 智能匹配与推荐:利用Elasticsearch,根据用户发布的宠物特征(品种、颜色、体型)和地点,匹配历史启事或相似宠物,提高效率。
4. 周边服务模块
- 服务商家入驻与展示:医院、美容店、商店等。
- 服务预约:在线预约洗澡、美容、体检等服务。
- 商品商城:宠物食品、用品电商(可集成第三方或自营)。
5. 后台管理系统
- 用户、内容(动态、评论)、寻宠启事审核与管理。
- 服务商家审核与管理。
- 数据统计与分析看板。
- 系统配置(如敏感词过滤、推送规则)。
四、核心代码示例 (Spring Boot后端)
1. JWT工具类与Spring Security配置
import io.jsonwebtoken.Claims; import io.jsonwebtoken.Jwts; import io.jsonwebtoken.SignatureAlgorithm; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; import java.util.Date; import java.util.HashMap; import java.util.Map; @Component public class JwtUtil { @Value("${jwt.secret}") private String secret; @Value("${jwt.expiration}") private Long expiration; // 生成Token public String generateToken(String username) { Map<String, Object> claims = new HashMap<>(); claims.put("username", username); return Jwts.builder() .setClaims(claims) .setSubject(username) .setIssuedAt(new Date()) .setExpiration(new Date(System.currentTimeMillis() + expiration * 1000)) .signWith(SignatureAlgorithm.HS512, secret) .compact(); } // 验证并解析Token public Claims parseToken(String token) { return Jwts.parser() .setSigningKey(secret) .parseClaimsJws(token) .getBody(); } // 检查Token是否过期 public boolean isTokenExpired(String token) { return parseToken(token).getExpiration().before(new Date()); } }2. 寻宠启事发布接口 (Controller层)
import com.example.petplatform.dto.LostPetPostDTO; import com.example.petplatform.service.LostPetService; import com.example.petplatform.vo.ResultVO; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import lombok.RequiredArgsConstructor; import org.springframework.web.bind.annotation.*; import javax.validation.Valid; @RestController @RequestMapping("/api/lost-pet") @RequiredArgsConstructor @Tag(name = "寻宠启事管理") public class LostPetController { private final LostPetService lostPetService; @PostMapping("/post") @Operation(summary = "发布寻宠启事") public ResultVO<Long> postLostPet(@RequestBody @Valid LostPetPostDTO dto, @RequestHeader("Authorization") String token) { // 1. 从token中解析用户ID (略) Long userId = getUserIdFromToken(token); // 2. 调用服务层 Long postId = lostPetService.createLostPetPost(dto, userId); // 3. 异步推送至消息队列,进行LBS推送和ES索引 // ... return ResultVO.success(postId); } @GetMapping("/search") @Operation(summary = "搜索附近的寻宠启事") public ResultVO<List<LostPetVO>> searchNearby(@RequestParam Double lat, @RequestParam Double lng, @RequestParam(defaultValue = "5") Double radiusKm, @RequestParam(required = false) String keyword) { List<LostPetVO> list = lostPetService.searchNearby(lat, lng, radiusKm, keyword); return ResultVO.success(list); } }3. 服务层实现 (集成Elasticsearch与Redis)
import com.example.petplatform.entity.LostPetPost; import com.example.petplatform.repository.LostPetPostRepository; import com.example.petplatform.search.LostPetPostDocument; import com.example.petplatform.search.LostPetSearchRepository; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.util.concurrent.TimeUnit; @Service @Slf4j @RequiredArgsConstructor public class LostPetServiceImpl implements LostPetService { private final LostPetPostRepository lostPetPostRepository; // MyBatis-Plus Mapper private final LostPetSearchRepository lostPetSearchRepository; // Spring Data Elasticsearch Repository private final RedisTemplate<String, Object> redisTemplate; private final GeoPushService geoPushService; // 地理推送服务 @Override @Transactional public Long createLostPetPost(LostPetPostDTO dto, Long userId) { // 1. DTO 转 Entity,保存至MySQL LostPetPost post = convertToEntity(dto, userId); lostPetPostRepository.insert(post); Long postId = post.getId(); // 2. 异步构建ES文档并保存 (可通过消息队列) LostPetPostDocument doc = convertToDocument(post); lostPetSearchRepository.save(doc); // 3. 将启事ID和地理位置存入Redis GeoSet,用于快速查询附近启事 String geoKey = "lost_pet:geo"; redisTemplate.opsForGeo().add(geoKey, new RedisGeoCommands.GeoLocation<>( postId.toString(), new Point(dto.getLongitude(), dto.getLatitude()) )); // 设置过期时间,例如30天 redisTemplate.expire(geoKey, 30, TimeUnit.DAYS); // 4. 触发LBS推送任务 geoPushService.pushToNearbyUsers(postId, dto.getLatitude(), dto.getLongitude()); return postId; } @Override public List<LostPetVO> searchNearby(Double lat, Double lng, Double radiusKm, String keyword) { List<LostPetVO> results = new ArrayList<>(); // 1. 如果有关键词,优先使用Elasticsearch进行全文+地理位置混合查询 if (StringUtils.hasText(keyword)) { results = lostPetSearchRepository.findByKeywordAndLocation(keyword, lat, lng, radiusKm); } else { // 2. 无关键词,使用Redis Geo查询附近的启事ID Distance distance = new Distance(radiusKm, Metrics.KILOMETERS); GeoResults<RedisGeoCommands.GeoLocation<Object>> geoResults = redisTemplate.opsForGeo() .radius("lost_pet:geo", new Circle(new Point(lng, lat), distance)); // 3. 根据ID从MySQL或缓存中获取详细信息 // ... } return results; } }4. WebSocket配置与消息处理 (简易版)
import org.springframework.context.annotation.Configuration; import org.springframework.messaging.simp.config.MessageBrokerRegistry; import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker; import org.springframework.web.socket.config.annotation.StompEndpointRegistry; import org.springframework.web.socket.config.annotation.WebSocketMessageBrokerConfigurer; @Configuration @EnableWebSocketMessageBroker public class WebSocketConfig implements WebSocketMessageBrokerConfigurer { @Override public void registerStompEndpoints(StompEndpointRegistry registry) { // 客户端连接端点,允许跨域 registry.addEndpoint("/ws").setAllowedOriginPatterns("*").withSockJS(); } @Override public void configureMessageBroker(MessageBrokerRegistry registry) { // 消息代理前缀,客户端订阅地址以 /topic 或 /user 开头 registry.enableSimpleBroker("/topic", "/queue"); // 客户端发送消息到服务器的前缀 registry.setApplicationDestinationPrefixes("/app"); // 点对点消息前缀,默认 /user registry.setUserDestinationPrefix("/user"); } } // 消息控制器示例 @Controller public class ChatController { @MessageMapping("/chat.send") @SendTo("/topic/public") public ChatMessage sendMessage(@Payload ChatMessage chatMessage) { return chatMessage; } @MessageMapping("/chat.private.{userId}") public void sendPrivateMessage(@Payload ChatMessage message, @DestinationVariable String userId) { // 处理私信逻辑,发送给特定用户 simpMessagingTemplate.convertAndSendToUser(userId, "/queue/private", message); } }五、总结与展望
本项目“萌宠社交与寻宠平台”是一个具有实际社会价值和技术挑战的全栈应用。通过Spring Boot为核心的后端技术栈,实现了高并发、可扩展、安全可靠的系统架构。核心的寻宠模块结合了LBS、实时推送和智能搜索,是技术亮点所在。
未来可扩展方向:
- AI图像识别:接入宠物图片识别API,用户上传走失宠物照片后,自动匹配平台内相似宠物或网络上的寻宠信息。
- 智能穿戴设备集成:与宠物智能项圈厂商合作,实现宠物位置实时追踪与电子围栏告警。
- 微服务化改造:将用户、社交、寻宠、服务等模块拆分为独立微服务,提升系统弹性和部署灵活性。
- 大数据分析:分析用户行为与宠物数据,提供个性化的内容推荐和健康养宠建议。
该项目的设计与实现涵盖了现代Web开发的多个关键技术面,是学习和掌握Spring Boot生态及互联网产品开发的优秀实践案例。