在公益与商业融合的浪潮中,构建一个集领养、救助与商城于一体的流浪宠物管理系统,不仅能提升运营效率,更能为流浪动物带来更多关爱。本文基于SpringBoot2与Vue2,深度剖析该系统的架构设计、核心模块与代码实现,带你掌握全栈开发的核心技巧。

项目概览:功能与技术栈

该系统分为前台用户端与后台管理端。用户可浏览宠物信息、提交领养申请、参与救助互动、在商城购物;管理员则负责数据维护、订单处理与审核。技术栈方面,后端采用SpringBoot2 + MyBatis Plus + Shiro,前端使用Vue2 + Element UI,前后端通过RESTful API通信。数据库选用MySQL,并利用数据字典与全局拦截器提升代码复用性。

层级技术/框架说明
后端框架Spring Boot 2.2.2.RELEASE项目的基础框架,提供自动配置和快速开发能力。
持久层MyBatis Plus 2.3增强的MyBatis ORM框架,简化数据库操作。
安全控制Apache Shiro 1.3.2用于身份认证和权限管理。
数据库MySQL 5.7.32-log关系型数据库,存储系统业务数据。
前端框架Vue.js (后台管理)
layui (前台)
后台管理使用Vue + Element UI构建SPA;前台使用layui和jQuery。
前端组件Element UI, ECharts, Axios, Swiper丰富用户界面交互和数据可视化。
工具库Fastjson, Hutool, Commons-lang3用于JSON处理、工具方法、字符串操作等。

核心模块拆解:从宠物到订单

系统涵盖四大核心模块:流浪宠物管理支持用户按类型与状态筛选,管理员可审核领养申请;宠物用品商城实现商品浏览、购物车、下单支付与订单管理;流浪动物救助允许用户发布故事、互动(点赞/踩、留言、收藏);公告管理用于发布通知。每个模块均包含增删改查与状态流转,形成完整业务闭环。

数据库设计:表结构详解

数据库共设计15张表,涵盖用户、宠物、订单、交互与基础数据。用户相关表包括yonghuusers;核心业务表有chongwuchongwu_lingyangliulangdongwujiuzhuchongwuyongpin;交易相关表为cartchongwuyongpin_orderaddress;交互相关表包括liulangdongwujiuzhu_liuyanliulangdongwujiuzhu_collectionchongwuyongpin_commentback;基础数据有dictionaryconfignews

后端架构与权限控制

后端采用经典三层架构:Controller处理请求,Service实现业务,Dao通过MyBatis Plus操作数据库。权限控制使用Shiro框架,通过自定义@IgnoreAuth注解与AuthorizationInterceptor拦截器实现Token验证。数据字典通过dictionary表与DictionaryServletContextListener监听器,在启动时加载到全局ServletContext中,并在DictionaryService提供转换方法。此外,工具类如ValidatorUtilsSQLFilterPoiUtil增强了安全性与复用性。

关键代码实战解析

以下是流浪宠物实体类ChongwuEntity.java的代码,展示字段映射:

// 部分关键代码展示
package com.entity;
import com.baomidou.mybatisplus.annotations.TableId;
import com.baomidou.mybatisplus.annotations.TableName;
import com.fasterxml.jackson.annotation.JsonFormat;
import org.springframework.format.annotation.DateTimeFormat;
import java.util.Date;
@TableName("chongwu")
public class ChongwuEntity<T> implements Serializable {
  private static final long serialVersionUID = 1L;
  @TableId(type = IdType.AUTO)
  private Integer id;
  @TableField(value = "chongwu_name")
  private String chongwuName; // 宠物名称
  @TableField(value = "chongwu_photo")
  private String chongwuPhoto; // 宠物照片
  @TableField(value = "chongwu_types")
  private Integer chongwuTypes; // 宠物类型 (关联字典表)
  @TableField(value = "chongwu_status_types")
  private Integer chongwuStatusTypes; // 认领状态 (关联字典表)
  @TableField(value = "chongwu_content")
  private String chongwuContent; // 宠物简介
  @JsonFormat(locale="zh", timezone="GMT+8", pattern="yyyy-MM-dd HH:mm:ss")
  @DateTimeFormat
  @TableField(value = "create_time", fill = FieldFill.INSERT)
  private Date createTime; // 创建时间
  // ... 省略 getter 和 setter 方法 ...
  }

流浪宠物控制器ChongwuController.java处理前端请求:

// 部分关键代码展示
package com.controller;
import com.entity.ChongwuEntity;
import com.service.ChongwuService;
import com.utils.PageUtils;
import com.utils.R;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/chongwu")
public class ChongwuController {
@Autowired
private ChongwuService chongwuService;
// 前端列表查询接口
@IgnoreAuth
@RequestMapping("/list")
public R list(@RequestParam Map<String, Object> params) {
  // 处理分页和查询参数
  PageUtils page = chongwuService.queryPage(params);
  // 返回分页数据
  return R.ok().put("data", page);
  }
  // 前端详情查询接口,同时增加点击次数
  @RequestMapping("/detail/{id}")
  public R detail(@PathVariable("id") Long id) {
  ChongwuEntity chongwu = chongwuService.selectById(id);
  if (chongwu != null) {
  // 点击数量加1
  chongwu.setChongwuClicknum(chongwu.getChongwuClicknum() + 1);
  chongwuService.updateById(chongwu);
  // ... 省略数据转换 ...
  return R.ok().put("data", chongwu);
  } else {
  return R.error(511, "查不到数据");
  }
  }
  // ... 省略其他方法 ...
  }

MyBatis Plus映射文件ChongwuDao.xml演示多表联查,关联chongwudictionary表,查询chongwu_typeschongwu_status_types

<!-- 部分关键代码展示 -->
    <mapper namespace="com.dao.ChongwuDao">
      <sql id="Base_Column_List">
      a.id as id
      ,a.chongwu_name as chongwuName
      ,a.chongwu_photo as chongwuPhoto
      -- ... 其他基础字段
    </sql>
      <select id="selectListView" parameterType="map" resultType="com.entity.view.ChongwuView">
      SELECT
      <include refid="Base_Column_List" />
      , b.index_name as chongwuValue
      , c.index_name as chongwuStatusValue
      FROM chongwu a
      LEFT JOIN dictionary b ON a.chongwu_types = b.code_index AND b.dic_code = 'chongwu_types'
      LEFT JOIN dictionary c ON a.chongwu_status_types = c.code_index AND c.dic_code = 'chongwu_status_types'
      <where>
      <if test="params.ids != null"> ... </if>
          <if test=" params.chongwuName != null and params.chongwuName != '' ">
          and a.chongwu_name like CONCAT('%',#{params.chongwuName},'%')
        </if>
        <!-- ... 其他查询条件 -->
        </where>
        order by a.${params.orderBy} desc
      </select>
    </mapper>

商品订单处理逻辑ChongwuyongpinOrderController.java涉及库存扣减、余额校验与事务管理:

// 部分关键代码展示
@RestController
@RequestMapping("/chongwuyongpinOrder")
public class ChongwuyongpinOrderController {
@Autowired
private ChongwuyongpinOrderService chongwuyongpinOrderService;
@Autowired
private ChongwuyongpinService chongwuyongpinService;
@Autowired
private YonghuService yonghuService;
@Autowired
private CartService cartService;
@RequestMapping("/order")
public R add(@RequestParam Map<String, Object> params, HttpServletRequest request) {
  // 1. 获取订单参数:地址ID、支付方式、商品列表等
  Integer userId = (Integer) request.getSession().getAttribute("userId");
  // ...
  // 2. 遍历购物车商品,逐一处理
  for (Map<String, Object> map : chongwuyongpins) {
    ChongwuyongpinEntity chongwuyongpinEntity = chongwuyongpinService.selectById(chongwuyongpinId);
    // 3. 校验库存
    if(chongwuyongpinEntity.getChongwuyongpinKucunNumber() < buyNumber) {
    return R.error(chongwuyongpinEntity.getChongwuyongpinName()+"的库存不足");
    }
    // 4. 更新库存
    chongwuyongpinEntity.setChongwuyongpinKucunNumber(chongwuyongpinEntity.getChongwuyongpinKucunNumber() - buyNumber);
    // 5. 计算价格,并校验用户余额是否充足
    if(chongwuyongpinOrderPaymentTypes == 1) { // 余额支付
    if(yonghuEntity.getNewMoney() - money < 0 ) {
    return R.error("余额不足,请充值!!!");
    }
    // 扣减余额
    yonghuEntity.setNewMoney(yonghuEntity.getNewMoney() - money);
    }
    // 创建订单详情对象...
    }
    // 6. 批量插入订单、更新商品库存、更新用户余额、清空购物车
    chongwuyongpinOrderService.insertBatch(chongwuyongpinOrderList);
    chongwuyongpinService.updateBatchById(chongwuyongpinList);
    yonghuService.updateById(yonghuEntity);
    cartService.deleteBatchIds(cartIds);
    return R.ok();
    }
    // ... 其他方法 ...
    }

前端页面chongwuyongpin/detail.html实现商品详情与购物车交互:

<!-- 部分关键代码展示 -->
    <div class="detail-item">
    <!-- 数量加减按钮 -->
    <button type="button" @click="buyNumber>0?buyNumber--:buyNumber">-</button>
      <input type="number" v-model="buyNumber" id="buyNumber" disabled="disabled" />
    <button type="button" @click="buyNumber++">+</button>
      <!-- 加入购物车按钮 -->
          <button @click="addChongwuyongpinCart()" type="button">
          添加到购物车
        </button>
      </div>
      <script>
        // ... 省略Vue实例定义 ...
        methods: {
        // 添加到购物车方法
        addChongwuyongpinCart() {
        // 1. 检查库存
        if (this.detail.chongwuyongpinKucunNumber < this.buyNumber) {
        layui.layer.msg(`库存不足`, { icon: 5 });
        return false;
        }
        // 2. 检查购物车是否已存在该商品
        layui.http.request('cart/list', 'get', {
        yonghuId: localStorage.getItem('userid'),
        chongwuyongpinId: this.detail.id,
        }, (res) => {
        if(res.data.list.length > 0) {
        layui.layer.msg("该商品已经添加到购物车", { icon: 5 });
        return false;
        }
        // 3. 发起请求,将商品加入购物车
        layui.http.requestJson('cart/add', 'post', {
        yonghuId: localStorage.getItem('userid'),
        chongwuyongpinId: this.detail.id,
        buyNumber: this.buyNumber,
        }, (res) => {
        if(res.code==0){
        layui.layer.msg('添加到购物车成功', { icon: 6 });
        }
        });
        });
        }
        }
      </script>

前端开发亮点:Vue2与UI交互

在前端开发中,我们利用Vue2的组件化与Element UI构建了响应式界面。例如,商品详情页的数量选择器与加入购物车功能,通过v-model双向绑定与axios异步请求实现流畅体验。对于UI开发,我们遵循模块化设计,将宠物列表、救助故事、购物车等拆分为独立组件,便于维护与扩展。与React或Angular相比,Vue2的学习曲线更平缓,且生态丰富,适合中小型项目快速迭代。

实践建议:在开发中,注意使用路由懒加载优化首屏加载速度,并利用Vuex管理全局状态(如用户登录信息与购物车数据),避免组件间数据传递混乱。

[AFFILIATE_SLOT_1]

系统截图与运行效果

以下是系统运行时的部分截图,展示前台首页、宠物列表、商品详情、购物车、订单管理、后台数据维护等界面:img1img2img3img4img5img6img7img8img9img10img11img12img13img14img15img16img17img18img19img20img21img22img23img24img25img26img27img28img29img30img31img32img33img34img35img36img37img38img39img40img41

项目总结与扩展思考

该系统功能全面,覆盖领养、救助、电商与公告,形成业务闭环。技术选型成熟,SpringBoot2 + MyBatis Plus + Vue2组合保证了开发效率与可维护性。交互设计完善,点赞/踩、留言、收藏、购物车等功能提升了用户体验。数据字典、统一拦截器、全局异常处理等设计增强了系统健壮性。

扩展方向:未来可引入Redis缓存热点数据,使用Elasticsearch实现宠物与商品的全文搜索,或集成微信支付与小程序,提升移动端体验。对于前端工具,可尝试迁移至Vue3 + Vite或React + Next.js,以获得更好的性能与SSR支持。

[AFFILIATE_SLOT_2]

⚠️ 注意事项:在开发中务必注意SQL注入防护(使用MyBatis Plus的预编译机制),并合理设计数据库索引以优化查询性能。同时,建议在订单处理逻辑中引入消息队列(如RabbitMQ)以解耦与削峰。