{"id":14972997,"url":"https://github.com/macrozheng/mall-tiny","last_synced_at":"2025-05-14T05:10:34.635Z","repository":{"id":37753277,"uuid":"201566059","full_name":"macrozheng/mall-tiny","owner":"macrozheng","description":"mall-tiny是一款基于SpringBoot+MyBatis-Plus的快速开发脚手架，拥有完整的权限管理功能，可对接Vue前端，开箱即用。","archived":false,"fork":false,"pushed_at":"2024-11-25T06:42:46.000Z","size":509,"stargazers_count":1981,"open_issues_count":22,"forks_count":1230,"subscribers_count":50,"default_branch":"master","last_synced_at":"2025-04-12T19:43:05.088Z","etag":null,"topics":["docker","mybatis","mybatis-plus","mysql","redis","springboot","springsecurity"],"latest_commit_sha":null,"homepage":"https://www.macrozheng.com","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/macrozheng.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2019-08-10T02:03:02.000Z","updated_at":"2025-04-08T08:43:04.000Z","dependencies_parsed_at":"2025-01-10T12:32:29.596Z","dependency_job_id":"7e203dc5-611d-4de0-84f7-af87ee8fac59","html_url":"https://github.com/macrozheng/mall-tiny","commit_stats":{"total_commits":36,"total_committers":1,"mean_commits":36.0,"dds":0.0,"last_synced_commit":"a81ec4740a0c7c99a06ebffb43a14168beadffc3"},"previous_names":[],"tags_count":2,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/macrozheng%2Fmall-tiny","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/macrozheng%2Fmall-tiny/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/macrozheng%2Fmall-tiny/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/macrozheng%2Fmall-tiny/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/macrozheng","download_url":"https://codeload.github.com/macrozheng/mall-tiny/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254076849,"owners_count":22010611,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["docker","mybatis","mybatis-plus","mysql","redis","springboot","springsecurity"],"created_at":"2024-09-24T13:47:54.768Z","updated_at":"2025-05-14T05:10:34.592Z","avatar_url":"https://github.com/macrozheng.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"# mall-tiny\n\n\u003cp\u003e\n    \u003ca href=\"#公众号\"\u003e\u003cimg src=\"http://macro-oss.oss-cn-shenzhen.aliyuncs.com/mall/badge/%E5%85%AC%E4%BC%97%E5%8F%B7-macrozheng-blue.svg\" alt=\"公众号\"\u003e\u003c/a\u003e\n    \u003ca href=\"#公众号\"\u003e\u003cimg src=\"http://macro-oss.oss-cn-shenzhen.aliyuncs.com/mall/badge/%E4%BA%A4%E6%B5%81-%E5%BE%AE%E4%BF%A1%E7%BE%A4-2BA245.svg\" alt=\"交流\"\u003e\u003c/a\u003e    \n    \u003ca href=\"https://github.com/macrozheng/mall\"\u003e\u003cimg src=\"http://macro-oss.oss-cn-shenzhen.aliyuncs.com/mall/badge/%E5%90%8E%E5%8F%B0%E9%A1%B9%E7%9B%AE-mall-blue.svg\" alt=\"后台项目\"\u003e\u003c/a\u003e\n    \u003ca href=\"https://github.com/macrozheng/mall-admin-web\"\u003e\u003cimg src=\"http://macro-oss.oss-cn-shenzhen.aliyuncs.com/mall/badge/%E5%89%8D%E7%AB%AF%E9%A1%B9%E7%9B%AE-mall--admin--web-green.svg\" alt=\"前端项目\"\u003e\u003c/a\u003e\n\u003c/p\u003e\n\n## 友情提示\n\n\u003e 1. **快速体验项目**：[在线访问地址](https://www.macrozheng.com/admin/index.html) 。\n\u003e 2. **全套学习教程**：[《mall学习教程》](https://www.macrozheng.com) 。\n\u003e 3. **视频教程（2023最新版）**：[《mall视频教程》](https://www.macrozheng.com/mall/catalog/mall_video.html) 。\n\u003e 4. **微服务版本**：基于Spring Cloud 2021 \u0026 Alibaba的项目：[mall-swarm](https://github.com/macrozheng/mall-swarm) 。\n\u003e 5. **SpringBoot 3.x版本**：已支持SpringBoot 3.x + JDK 17，具体参考[3.x分支](https://github.com/macrozheng/mall-tiny/tree/3.x) 。\n\n## 简介\n\nmall-tiny是一款基于SpringBoot+MyBatis-Plus的快速开发脚手架，拥有完整的权限管理功能，可对接Vue前端，开箱即用。\n\n## 项目演示\n\nmall-tiny项目可无缝对接`mall-admin-web`前端项目，秒变权限管理系统。前端项目地址：https://github.com/macrozheng/mall-admin-web\n\n![](./images/mall_tiny_start_09.png)\n\n## 技术选型\n\n| 技术                   | 版本    | 说明             |\n| ---------------------- | ------- | ---------------- |\n| SpringBoot             | 2.7.0   | 容器+MVC框架     |\n| SpringSecurity         | 5.7.1   | 认证和授权框架   |\n| MyBatis                | 3.5.9   | ORM框架          |\n| MyBatis-Plus           | 3.5.1   | MyBatis增强工具  |\n| MyBatis-Plus Generator | 3.5.1   | 数据层代码生成器 |\n| Swagger-UI             | 3.0.0   | 文档生产工具     |\n| Redis                  | 5.0     | 分布式缓存       |\n| Docker                 | 18.09.0 | 应用容器引擎     |\n| Druid                  | 1.2.9   | 数据库连接池     |\n| Hutool                 | 5.8.0   | Java工具类库     |\n| JWT                    | 0.9.1   | JWT登录支持      |\n| Lombok                 | 1.18.24 | 简化对象封装工具 |\n\n## 数据库表结构\n\n![](./images/mall_tiny_start_01.png)\n\n- 化繁为简，仅保留了权限管理功能相关的9张表，方便自由定制；\n\n- 数据库源文件地址：https://github.com/macrozheng/mall-tiny/blob/master/sql/mall_tiny.sql\n\n## 使用流程\n\n### 环境搭建\n\n简化依赖服务，只需安装最常用的MySql和Redis服务即可，服务安装具体参考[mall在Windows环境下的部署](https://www.macrozheng.com/mall/deploy/mall_deploy_windows.html) ，数据库中需要导入`mall_tiny.sql`脚本。\n\n### 开发规约\n\n#### 项目包结构\n\n``` lua\nsrc\n├── common -- 用于存放通用代码\n|   ├── api -- 通用结果集封装类\n|   ├── config -- 通用配置类\n|   ├── domain -- 通用封装对象\n|   ├── exception -- 全局异常处理相关类\n|   └── service -- 通用业务类\n├── config -- SpringBoot中的Java配置\n├── domain -- 共用封装对象\n├── generator -- MyBatis-Plus代码生成器\n├── modules -- 存放业务代码的基础包\n|   └── ums -- 权限管理模块业务代码\n|       ├── controller -- 该模块相关接口\n|       ├── dto -- 该模块数据传输封装对象\n|       ├── mapper -- 该模块相关Mapper接口\n|       ├── model -- 该模块相关实体类\n|       └── service -- 该模块相关业务处理类\n└── security -- SpringSecurity认证授权相关代码\n    ├── annotation -- 相关注解\n    ├── aspect -- 相关切面\n    ├── component -- 认证授权相关组件\n    ├── config -- 相关配置\n    └── util -- 相关工具类\n```\n\n#### 资源文件说明\n\n``` lua\nresources\n├── mapper -- MyBatis中mapper.xml存放位置\n├── application.yml -- SpringBoot通用配置文件\n├── application-dev.yml -- SpringBoot开发环境配置文件\n├── application-prod.yml -- SpringBoot生产环境配置文件\n└── generator.properties -- MyBatis-Plus代码生成器配置\n```\n\n#### 接口定义规则\n\n- 创建表记录：POST /{控制器路由名称}/create\n\n- 修改表记录：POST /{控制器路由名称}/update/{id}\n\n- 删除指定表记录：POST /{控制器路由名称}/delete/{id}\n\n- 分页查询表记录：GET /{控制器路由名称}/list\n\n- 获取指定记录详情：GET /{控制器路由名称}/{id}\n\n- 具体参数及返回结果定义可以运行代码查看Swagger-UI的Api文档：http://localhost:8080/swagger-ui/\n\n![](./images/mall_tiny_start_02.png)\n\n### 项目运行\n\n直接运行启动类`MallTinyApplication`的`main`函数即可。\n\n### 业务代码开发流程\n\n#### 创建业务表\n\n\u003e 创建好`pms`模块的所有表，需要注意的是一定要写好表字段的`注释`，这样实体类和接口文档中就会自动生成字段说明了。\n\n![](./images/mall_tiny_start_03.png)\n\n#### 使用代码生成器\n\n\u003e 运行`MyBatisPlusGenerator`类的main方法来生成代码，可直接生成controller、service、mapper、model、mapper.xml的代码，无需手动创建。\n\n- 代码生成器支持两种模式，一种生成单表的代码，比如只生成`pms_brand`表代码可以先输入`pms`，后输入`pms_brand`；\n\n![](./images/mall_tiny_start_04.png)\n\n- 生成代码结构一览；\n\n![](./images/mall_tiny_start_05.png)\n\n- 另一种直接生成整个模块的代码，比如生成`pms`模块代码可以先输入`pms`，后输入`pms_*`。\n\n![](./images/mall_tiny_start_06.png)\n\n#### 编写业务代码\n\n##### 单表查询\n\n\u003e 由于MyBatis-Plus提供的增强功能相当强大，单表查询几乎不用手写SQL，直接使用ServiceImpl和BaseMapper中提供的方法即可。\n\n比如我们的菜单管理业务实现类`UmsMenuServiceImpl`中的方法都直接使用了这些方法。\n\n```java\n/**\n * 后台菜单管理Service实现类\n * Created by macro on 2020/2/2.\n */\n@Service\npublic class UmsMenuServiceImpl extends ServiceImpl\u003cUmsMenuMapper,UmsMenu\u003eimplements UmsMenuService {\n\n    @Override\n    public boolean create(UmsMenu umsMenu) {\n        umsMenu.setCreateTime(new Date());\n        updateLevel(umsMenu);\n        return save(umsMenu);\n    }\n\n    @Override\n    public boolean update(Long id, UmsMenu umsMenu) {\n        umsMenu.setId(id);\n        updateLevel(umsMenu);\n        return updateById(umsMenu);\n    }\n\n    @Override\n    public Page\u003cUmsMenu\u003e list(Long parentId, Integer pageSize, Integer pageNum) {\n        Page\u003cUmsMenu\u003e page = new Page\u003c\u003e(pageNum,pageSize);\n        QueryWrapper\u003cUmsMenu\u003e wrapper = new QueryWrapper\u003c\u003e();\n        wrapper.lambda().eq(UmsMenu::getParentId,parentId)\n                .orderByDesc(UmsMenu::getSort);\n        return page(page,wrapper);\n    }\n\n    @Override\n    public List\u003cUmsMenuNode\u003e treeList() {\n        List\u003cUmsMenu\u003e menuList = list();\n        List\u003cUmsMenuNode\u003e result = menuList.stream()\n                .filter(menu -\u003e menu.getParentId().equals(0L))\n                .map(menu -\u003e covertMenuNode(menu, menuList)).collect(Collectors.toList());\n        return result;\n    }\n\n    @Override\n    public boolean updateHidden(Long id, Integer hidden) {\n        UmsMenu umsMenu = new UmsMenu();\n        umsMenu.setId(id);\n        umsMenu.setHidden(hidden);\n        return updateById(umsMenu);\n    }\n}\n```\n\n##### 分页查询\n\n\u003e 对于分页查询MyBatis-Plus原生支持，不需要再整合其他插件，直接构造Page对象，然后调用ServiceImpl中的page方法即可。\n\n```java\n/**\n * 后台菜单管理Service实现类\n * Created by macro on 2020/2/2.\n */\n@Service\npublic class UmsMenuServiceImpl extends ServiceImpl\u003cUmsMenuMapper,UmsMenu\u003eimplements UmsMenuService {\n    @Override\n    public Page\u003cUmsMenu\u003e list(Long parentId, Integer pageSize, Integer pageNum) {\n        Page\u003cUmsMenu\u003e page = new Page\u003c\u003e(pageNum,pageSize);\n        QueryWrapper\u003cUmsMenu\u003e wrapper = new QueryWrapper\u003c\u003e();\n        wrapper.lambda().eq(UmsMenu::getParentId,parentId)\n                .orderByDesc(UmsMenu::getSort);\n        return page(page,wrapper);\n    }\n}\n```\n\n##### 多表查询\n\n\u003e 对于多表查询，我们需要手写mapper.xml中的SQL实现，由于之前我们已经生成了mapper.xml文件，所以我们直接在Mapper接口中定义好方法，然后在mapper.xml写好SQL实现即可。\n\n- 比如说我们需要写一个根据用户ID获取其分配的菜单的方法，首先我们在`UmsMenuMapper`接口中添加好`getMenuList`方法；\n\n```java\n/**\n * \u003cp\u003e\n * 后台菜单表 Mapper 接口\n * \u003c/p\u003e\n *\n * @author macro\n * @since 2020-08-21\n */\npublic interface UmsMenuMapper extends BaseMapper\u003cUmsMenu\u003e {\n\n    /**\n     * 根据后台用户ID获取菜单\n     */\n    List\u003cUmsMenu\u003e getMenuList(@Param(\"adminId\") Long adminId);\n\n}\n```\n\n- 然后在`UmsMenuMapper.xml`添加该方法的对应SQL实现即可。\n\n```xml\n\u003c?xml version=\"1.0\" encoding=\"UTF-8\"?\u003e\n\u003c!DOCTYPE mapper PUBLIC \"-//mybatis.org//DTD Mapper 3.0//EN\" \"http://mybatis.org/dtd/mybatis-3-mapper.dtd\"\u003e\n\u003cmapper namespace=\"com.macro.mall.tiny.modules.ums.mapper.UmsMenuMapper\"\u003e\n\n    \u003cselect id=\"getMenuList\" resultType=\"com.macro.mall.tiny.modules.ums.model.UmsMenu\"\u003e\n        SELECT\n            m.id id,\n            m.parent_id parentId,\n            m.create_time createTime,\n            m.title title,\n            m.level level,\n            m.sort sort,\n            m.name name,\n            m.icon icon,\n            m.hidden hidden\n        FROM\n            ums_admin_role_relation arr\n                LEFT JOIN ums_role r ON arr.role_id = r.id\n                LEFT JOIN ums_role_menu_relation rmr ON r.id = rmr.role_id\n                LEFT JOIN ums_menu m ON rmr.menu_id = m.id\n        WHERE\n            arr.admin_id = #{adminId}\n          AND m.id IS NOT NULL\n        GROUP BY\n            m.id\n    \u003c/select\u003e\n    \n\u003c/mapper\u003e\n```\n\n### 项目部署\n\nmall-tiny已经集成了Docker插件，可以打包成Docker镜像来部署，具体参考：[使用Maven插件为SpringBoot应用构建Docker镜像](https://www.macrozheng.com/project/maven_docker_fabric8.html)\n\n安装好MySQL和Redis服务后，直接使用如下命令运行即可。\n\n```bash\ndocker run -p 8080:8080 --name mall-tiny \\\n--link mysql:db \\\n--link redis:redis \\\n-e 'spring.profiles.active'=prod \\\n-v /etc/localtime:/etc/localtime \\\n-v /mydata/app/mall-tiny/logs:/var/logs \\\n-d mall-tiny/mall-tiny:1.0.0-SNAPSHOT\n```\n\n### 其他说明\n\n#### SpringSecurity相关\n\n\u003e 由于使用了SpringSecurity来实现认证和授权，部分接口需要token才可以访问，访问需要认证授权接口流程如下。\n\n- 访问Swagger-UI接口文档：http://localhost:8080/swagger-ui/\n\n- 调用登录接口获取token；\n\n![](./images/mall_tiny_start_07.png)\n\n- 点击右上角Authorize按钮输入token，然后访问相关接口即可。\n\n![](./images/mall_tiny_start_08.png)\n\n#### 请求参数校验\n\n\u003e 默认集成了`Jakarta Bean Validation`参数校验框架，只需在参数对象属性中添加`javax.validation.constraints`包中的注解注解即可实现校验功能，这里以登录参数校验为例。\n\n- 首先在登录请求参数中添加`@NotEmpty`注解；\n\n```java\n/**\n * 用户登录参数\n * Created by macro on 2018/4/26.\n */\n@Data\n@EqualsAndHashCode(callSuper = false)\npublic class UmsAdminLoginParam {\n    @NotEmpty\n    @ApiModelProperty(value = \"用户名\",required = true)\n    private String username;\n    @NotEmpty\n    @ApiModelProperty(value = \"密码\",required = true)\n    private String password;\n}\n```\n\n- 然后在登录接口中添加`@Validated`注解开启参数校验功能即可。\n\n```java\n/**\n * 后台用户管理\n * Created by macro on 2018/4/26.\n */\n@Controller\n@Api(tags = \"UmsAdminController\", description = \"后台用户管理\")\n@RequestMapping(\"/admin\")\npublic class UmsAdminController {\n\n    @ApiOperation(value = \"登录以后返回token\")\n    @RequestMapping(value = \"/login\", method = RequestMethod.POST)\n    @ResponseBody\n    public CommonResult login(@Validated @RequestBody UmsAdminLoginParam umsAdminLoginParam) {\n        String token = adminService.login(umsAdminLoginParam.getUsername(), umsAdminLoginParam.getPassword());\n        if (token == null) {\n            return CommonResult.validateFailed(\"用户名或密码错误\");\n        }\n        Map\u003cString, String\u003e tokenMap = new HashMap\u003c\u003e();\n        tokenMap.put(\"token\", token);\n        tokenMap.put(\"tokenHead\", tokenHead);\n        return CommonResult.success(tokenMap);\n    }\n}\n```\n\n## 公众号\n\n加微信群交流，关注公众号「**macrozheng**」回复「**加群**」即可。\n\n![公众号图片](http://macro-oss.oss-cn-shenzhen.aliyuncs.com/mall/banner/qrcode_for_macrozheng_258.jpg)\n\n## 许可证\n\n[Apache License 2.0](https://github.com/macrozheng/mall-tiny/blob/master/LICENSE)\n\nCopyright (c) 2018-2022 macrozheng\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmacrozheng%2Fmall-tiny","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmacrozheng%2Fmall-tiny","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmacrozheng%2Fmall-tiny/lists"}