一、项目背景与意义随着城市化进程的加快和生活节奏的提速宠物尤其是猫、狗等萌宠已成为越来越多家庭的重要成员。然而宠物主人在饲养过程中面临着社交需求、知识获取、宠物丢失寻回等诸多痛点。传统的线下宠物社群和寻宠启事方式效率低下、信息传播范围有限。“萌宠”社交与寻宠平台旨在利用互联网技术构建一个集宠物社交、知识分享、寻宠互助、周边服务于一体的综合性平台。其核心意义在于构建宠物主人社区为宠物主人提供一个分享养宠心得、展示宠物日常、结识同城宠友的线上空间缓解孤独感增强归属感。提升寻宠效率与成功率通过基于地理位置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 ViteUI组件库Element Plus / Ant Design Vue状态管理Pinia路由Vue RouterHTTP客户端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) { MapString, 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 ResultVOLong 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 ResultVOListLostPetVO searchNearby(RequestParam Double lat, RequestParam Double lng, RequestParam(defaultValue 5) Double radiusKm, RequestParam(required false) String keyword) { ListLostPetVO 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 RedisTemplateString, 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 ListLostPetVO searchNearby(Double lat, Double lng, Double radiusKm, String keyword) { ListLostPetVO 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); GeoResultsRedisGeoCommands.GeoLocationObject 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生态及互联网产品开发的优秀实践案例。