- 绪论
1.1 研究意义
日益发展的信息技术,互联网经济的快速兴起,网上的购物日益受到人们的关注,蔬菜水果网上批发市场模式也必然成为其潮流发展一部分。 基于 springboot 技术的水果在线批发系统借助于遍布全球的互联网, 进行水果的市场消费流动,因此水果的批发既可以在本地进行,也可以在异地进行。 网上进行水果批发既可以省下许多时间体力,也可以节省来回的花销成本,更可以足不出户就可以了解到水果批发市场的行情,消费者可以吃到想吃的新鲜的水果。生产者以及批发销售商可以获得更多客户资源和批发渠道,进而提升蔬菜水果批发销量和规模。轻轻松松实现买卖交易。本课题利用 Java springboot 技术开发一个水果系统,为消费者和批发商提供一个平台,降低了成本、时间占用,也解决了交通困难等系列问题,促进人们生活消费水平。
1.2 国内外研究现状、水平和发展趋势
随着农村市场经济发展,尤其是我国加入WTO ,融入经济全球化潮流,水果业已进入国内外市场经济发展新时期,农业、农村与市场联系越来越紧密,我国水果产业也进入新历史发展阶段。水果产业部门、科技部门、涉农单位对水果产业信息化的认识逐步提高,积极探索水果产业信息体系如何向广大农民企业提供更服务。蔬菜经营场所封闭性、分散性和生产手段落后等特点决定了水果产业的发展起到巨大推动作用。为了更好地服务于农业、农村、农民,推进农业现代化进程,农业信息体系建设已迫在眉睫。随着电子商务在批发市场运用深化,一部分批发市场"蒸发"了,悄然退出市场、使有形市场和无形市场相结合从而产生一种新模式。对绝大多数市场来说,在组织创新上,当前最易采取形式是有形市场与无形市场相结合的方式。可以充分利用有形市场的优势,创办网上市场,搭建网上交易平台为市场经营者建立网上水果商铺,进行网上水果商品宣传,引导经营者开展网上交易,实行与现货交易并行的电子商务模式。农业网站发展表明,互联网和农业的结合正在逐渐深入,这是农业现代化发展需要,同时也是农村电子商务自身发展必然趋势, 为农产品销售电子商务的发展提供了保障在广大购物者渐渐对产品性价比要求越来越高的今天,我们发现必须要有一套完善的采购经销体系、才能不断提高产品质量同时降低产品的价格,所以减少产品销售中间环节成本增加势在必行。为此创办电子商务果蔬商城网站,让优质新鲜的蔬菜水果在网站直接面消费者,一提高网站可以提供比在商店购物中更为详尽资料、历史渊源以及顾客评论等信息,顾客可以方便地从琳琅满目的各类精品蔬菜水果中快速查询出需要的产品;另一方面也少商店运营成本,将价格实惠转让给顾客、使电子商务果蔬商城网站的发展成为必然。
1.3项目的可行性研究设计
此系统需要java面向对象编程基础,数据库应用知识以及功能分析。根据目前阶段所掌握的知识,根据这学期以及之前学习掌握的java编程知识和数据库应用知识以及前端知识做出一个这样的基于、springboot轻量级框架网页版的水果超市平台。
1. 4相关技术简介
1.4.1 spring
Spring框架是Java平台上的一种开源应用框架,提供具有控制反转特性容器。尽管Spring框架自身对编程模型没有限制,以至于后来让它作为EJB(EnterpriseJavaBeans)模型的补充,甚至是替补。Spring框架为开发提供了一系列的解决方案,比如利用控制反转核心特性,并通过依赖注入实现控制反转来实现管理对象生命周期的容器化,利用面向切面编程进行声明式事务管理,整合多种持久化技术管理数据访问,提供大量优秀的Web框架方便开发等。Spring框架具有控制反转(IOC)特性,它提供了一种通过Java的反射机制对Java对象进行统一的配置管理的方法。Spring框架利用容器管理对象生命周期,容器可以通过扫描XML文件配置对象。Spring框架具有面向切面编程(AOP)框架,SpringAOP框架基于代理模式,运行时可配置;AOP框架主要针对模块之间的交叉关注点进行模块化。Spring框架的AOP框架仅提供基本的AOP特性,Spring框架下的事务管理、远程访问等功能均可以通过使用SpringAOP技术实现。Spring的事务管理框架为Java平台带来了一种抽象机制,使本地和全局事务以及嵌套事务能够与保存点一起工作,并且几乎可以在Java平台的任何环境中工作。Spring集成多种事务模板,系统可以通过事务模板、XML或Java注解进行事务配置,并且事务框架集成了消息传递和缓存等功能。Spring数据访问框架解决了开发人员在应用程序中使用数据库时遇到的常见困难。它不仅对Java:JDBC、MyBATIs、Hibernate、Java数据对象(JDO)、ApacheOJB和ApacheCayne等所有流行的数据访问框架中提供支持,同时还可以与Spring的事务管理一起使用,为数据访问提供了灵活的抽象。Spring框架最初是没有打算构建一个自己的WebMVC框架,其开发人员在开发过程中认为现有的Web框架的呈现层和请求处理层之间以及请求处理层和模型之间的分离不够,于是创建了SpringMVC。
1.4.2 mybatis
mybatis是对jdbc的封装,它让数据库底层操作变的透明。mybatis的操作都是围绕一个sqlSessionFactory实例展开。mybatis通过配置文件关联到各实体类Mapper文件,Mapper文件中配置了每个类对数据库所需进行的sql语句映射。在每次与数据库交互,通过sqlSessionFactory拿到一个sqlSession,再执行sql。页面发送请求给控制器,控制器调用业务层处理,逻辑层向持久层发送请求,持久层与数据库交互,将结果返回给业务层,业务层将处理逻辑发送给控制器,控制器再调用视图展现数据。
1.4.3 Shiro权限框架
shiro是一个安全框架,是Apache的一个项目。shiro提供了:认证、授权、加密、会话管理、与web集成、缓存等模块。
1.1、模块介绍
Authentication:用户身份识别,可以是登录;
Authorization:授权,权限验证,验证某个已认证的用户是否拥有某个权限功能;即判断用户是否能做事情,常见:验证某个用户是否拥有某个角色。或者细粒度的验证某个用户对某资源是否具有某个权限。
Session Manager:会话管理,用户登录后就是一次会话,在没有退出之前,所有信息都在会话中;会话可以是普通 JavaSE 环境的,也可以是如 Web 环境的。
Cryptography:加密,保护数据的安全性,密码加密存储到数据库,而不是明文存储。
Web Support:Web支持,可以非常容易的集成到 javaweb 环境。
Caching:缓存,比如用户登录后,其用户信息、拥有的角色/权限不必每次去查,这样可以提高效率。
Concurrency:shiro 支持多线程应用的并发验证,即如在一个线程中开启另一个线程,能把权限自动传播过去。
Testing:提供测试支持。
2、核心概念
Subject:主体,代表了当前操作用户,这个用户不一定是具体的人,与当前应用交互的任何东西都是subject,即抽象概念。所有Subject都绑定到SecurityManager,与Subject交互都会委托给SercurityManager;
SecurityManager:安全管理器;即所有与subject安全有关的操作都会与SecurityManager交互;且它管理着所有的Subject;它负责与里面的各个组件交互,也可以把它理解成springmvc中DispatcherServlet前端控制器。
Realm:域,安全数据源。shiro从Realm获取安全数据(如用户、权限),就是说SecurityManager验证用户身份,那么它需要从Realm得到用户相应角色、权限进行验证用户是否能进行操作;可以把Realm看成DataSource,即安全数据源。
从上图可以看出:
1、应用代码通过Subject来进行认证和授权,而Subject又委托给SecurityManager;
2、SecurityManager要验证用户身份,那么它需要从Realm中获取相对应的用户、角色、权限进行比较以确定用户身份是否合法。
总结:shiro不提供维护用户、权限,而是通过Realm让开发人员自己注入。
3、shiro内部架构介绍
-
Subject:主体,看到主体可以是任何与应用交互"用户"。
-
SecurityManager:相当于 SpringMVC 中的 DispatcherServlet 或者 Struts2 中的FilterDispatcher。它是 Shiro 的核心,所有具体的交互都通过 SecurityManager 进行控制。它管理着所有 Subject、且负责进行认证和授权、及会话、缓存的管理。
-
Authenticator:认证器,负责主体认证的,这是一个扩展点,如果用户觉得 Shiro 默认的不好,我们可以自定义实现。其需要认证策略(Authentication Strategy),即什么情况下算用户认证通过了。
-
Authrizer:授权器,或者访问控制器。它用来决定主体是否有权限进行相应的操作,即控制着用户能访问应用中的哪些功能。
-
Realm:可以有1个或多个 Realm,可以认为是安全实体数据源,即用于获取安全实体的。它可以是 JDBC 实现,也可以是 LDAP 实现,或者内存实现等。
-
SessionManager:如果写过 Servlet 就应该知道 Session 的概念,Session 需要有人去管理它的生命周期,这个组件就是 SessionManager。而 Shiro 并不仅仅可以用在 Web 环境,也可以用在如普通的 JavaSE 环境。
-
SessionDAO:DAO 大家都用过,数据访问对象,用于会话的 CRUD。我们可以自定义 SessionDAO 的实现,控制 session 存储的位置。如通过 JDBC 写到数据库或通过 jedis 写入 redis 中。另外 SessionDAO 中可以使用 Cache 进行缓存,以提高性能。
-
CacheManager:缓存管理器。它来管理如用户、角色、权限等的缓存的。因为这些数据基本上很少去改变,放到缓存中后可以提高访问的性能。
-
Cryptography:密码模块,Shiro 提高了一些常见的加密组件用于如密码加密/解密的。
4、过滤器
当 Shiro 被运用到 web 项目时,Shiro 会自动创建一些默认的过滤器对客户端请求进行过滤。以下是 Shiro 提供的过滤器:
|-------------------|------------------------------------------------------------------|
| 过滤器简称 | 对应的 Java 类 |
| anon | org.apache.shiro.web.filter.authc.AnonymousFilter |
| authc | org.apache.shiro.web.filter.authc.FormAuthenticationFilter |
| authcBasic | org.apache.shiro.web.filter.authc.BasicHttpAuthenticationFilter |
| perms | org.apache.shiro.web.filter.authz.PermissionsAuthorizationFilter |
| port | org.apache.shiro.web.filter.authz.PortFilter |
| rest | org.apache.shiro.web.filter.authz.HttpMethodPermissionFilter |
| roles | org.apache.shiro.web.filter.authz.RolesAuthorizationFilter |
| ssl | org.apache.shiro.web.filter.authz.SslFilter |
| user | org.apache.shiro.web.filter.authc.UserFilter |
| logout | org.apache.shiro.web.filter.authc.LogoutFilter |
| noSessionCreation | org.apache.shiro.web.filter.session.NoSessionCreationFilter |
解释:
|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| /admins/**=anon # 表示该 uri 可以匿名访问 /admins/**=auth # 表示该 uri 需要认证才能访问 /admins/**=authcBasic # 表示该 uri 需要 httpBasic 认证 /admins/**=perms[user:add:*] # 表示该 uri 需要认证用户拥有 user:add:* 权限才能访问 /admins/**=port[8081] # 表示该 uri 需要使用 8081 端口 /admins/**=rest[user] # 相当于 /admins/**=perms[user:method],其中,method 表示 get、post、delete 等 /admins/**=roles[admin] # 表示该 uri 需要认证用户拥有 admin 角色才能访问 /admins/**=ssl # 表示该 uri 需要使用 https 协议 /admins/**=user # 表示该 uri 需要认证或通过记住我认证才能访问 /logout=logout # 表示注销,可以当作固定配置 |
1.4.4 SpringBoot
SpringBoot是Pivotal团队在2013年开始研发、2014年4月发布第一个版本全新开源的轻量级框架。它基于Spring4.0设计,不仅继承了Spring框架原有优秀特性,而且还通过简化配置来进一步简化了Spring应用的整个搭建开发过程。另外SpringBoot通过集成大量的框架使得依赖包的版本冲突,引用的不稳定性等问题得到了很好的解决。
SpringBoot具备的特征有:
(1)可以创建独立的Spring应用程序,并且基于其Maven或Gradle插件,可以创建可执行的JARs和WARs;
(2)内嵌Tomcat或Jetty等Servlet容器;
(3)提供自动配置的"starter"项目对象模型(POMS)以简化Maven配置;
(4)尽可能自动配置Spring容器;
(5)提供准备好的特性,如指标、健康检查和外部化配置;
(6)绝对没有代码生成,不需要XML配置。 [1] [2]
SpringBoot框架中还有两个非常重要的策略:开箱即用和约定优于配置。开箱即用,Outofbox,是指在开发过程中,通过在MAVEN项目的pom文件中添加相关依赖包,然后使用对应注解来代替繁琐的XML配置文件以管理对象的生命周期。这个特点使得开发人员摆脱了复杂的配置工作以及依赖的管理工作,更加专注于业务逻辑。约定优于配置,Convention over configuration,是一种由SpringBoot本身来配置目标结构,由开发者在结构中添加信息的软件设计范式。这一特点虽降低了部分灵活性,增加了BUG定位的复杂性,但减少了开发人员需要做出决定的数量,同时减少了大量的XML配置,并且可以将代码编译、测试和打包等工作自动化。
SpringBoot应用系统开发模板的基本架构设计从前端到后台进行说明:前端常使用模板引擎,主要有FreeMarker和Thymeleaf,它们都是用Java语言编写的,渲染模板并输出相应文本,使得界面的设计与应用的逻辑分离,同时前端开发还会使用到Bootstrap、AngularJS、JQuery等;在浏览器的数据传输格式上采用Json,非xml,同时提供RESTfulAPI;SpringMVC框架用于数据到达服务器后处理请求;到数据访问层主要有Hibernate、MyBatis、JPA等持久层框架;数据库常用MySQL;开发工具推荐IntelliJIDEA。
1.4.5 jQuery
jQuery是一个快速、简洁JavaScript框架,是继Prototype之后又一个优秀的JavaScript代码库(或JavaScript框架)。jQuery设计的宗旨是"write Less,Do More",即倡导写更少的代码,做更多的事情。它封装JavaScript常用的功能代码,提供一种简便的JavaScript设计模式,优化HTML文档操作、事件处理、动画设计和Ajax交互。
jQuery的核心特性可以总结为:具有独特的链式语法和短小清晰的多功能接口;具有高效灵活的css选择器,并且可对CSS选择器进行扩展;拥有便捷的插件扩展机制和丰富的插件。jQuery兼容各种主流浏览器,如IE 6.0+、FF 1.5+、Safari 2.0+、Opera 9.0+等
1.4.6 Mysql
MySQL 是一款安全、跨平台、高效的,并与 PHP、Java 等主流编程语言紧密结合的数据库系统。该数据库系统是由瑞典的 MySQL AB 公司开发、发布并支持,由 MySQL 的初始开发人员 David Axmark 和 Michael Monty Widenius 于 1995 年建立的。
MySQL 的象征符号是一只名为 Sakila 的海豚,代表着 MySQL 数据库的速度、能力、精确和优秀本质。
图:MySQL 图标
目前 MySQL 被广泛地应用在 Internet 上的中小型网站中。由于其体积小、速度快、总体拥有成本低,尤其是开放源码这一特点,使得很多公司都采用 MySQL 数据库以降低成本。
MySQL 数据库可以称得上是目前运行速度最快的 SQL 语言数据库之一。除了具有许多其他数据库所不具备的功能外,MySQL 数据库还是一种完全免费的产品,用户可以直接通过网络下载 MySQL 数据库,而不必支付任何费用。
MySQL 特点
下面总结了一下 MySQL 具备的特点。
- 功能强大
MySQL 中提供了多种数据库存储引擎,各引擎各有所长,适用于不同的应用场合,用户可以选择最合适的引擎以得到最高性能,可以处理每天访问量超过数亿的高强度的搜索 Web 站点。MySQL5 支持事务、视图、存储过程、触发器等。
- 支持跨平台
MySQL 支持至少 20 种以上的开发平台,包括 Linux、Windows、FreeBSD 、IBMAIX、AIX、FreeBSD 等。这使得在任何平台下编写的程序都可以进行移植,而不需要对程序做任何的修改。
- 运行速度快
高速是 MySQL 的显著特性。在 MySQL 中,使用了极快的 B 树磁盘表(MyISAM)和索引压缩;通过使用优化的单扫描多连接,能够极快地实现连接;SQL 函数使用高度优化的类库实现,运行速度极快。
- 支持面向对象
PHP 支持混合编程方式。编程方式可分为纯粹面向对象、纯粹面向过程、面句对象与面向过程混合 3 种方式。
- 安全性高
灵活和安全的权限与密码系统,允许基本主机的验证。连接到服务器时,所有的密码传输均采用加密形式,从而保证了密码的安全。
- 成本低
MySQL 数据库是一种完全免费的产品,用户可以直接通过网络下载。
- 支持各种开发语言
MySQL 为各种流行的程序设计语言提供支持,为它们提供了很多的 API 函数,包括 PHP、ASP.NET、Java、Eiffel、Python、Ruby、Tcl、C、C++、Perl 语言等。
- 数据库存储容量大
MySQL 数据库的最大有效表尺寸通常是由操作系统对文件大小的限制决定的,而不是由 MySQL 内部限制决定的。InnoDB 存储引擎将 InnoDB 表保存在一个表空间内,该表空间可由数个文件创建,表空间的最大容量为 64TB,可以轻松处理拥有上千万条记录的大型数据库。
- 支持强大的内置函数
PHP 中提供了大量内置函数,几乎涵盖了 Web 应用开发中的所有功能。它内置了数据库连接、文件上传等功能,MySQL 支持大量的扩展库,如 MySQLi 等,可以为快速开发 Web 应用提供便利。
数据库的应用
数据库是计算机应用系统中的一种专门管理数据资源的系统。数据有多种形式,如文字、数码、符号、图形、图像及声音等,数据是所有计算机系统所要处理的对象。我们所熟知的一种处理办法是制作文件,即将处理过程编成程序文件,将所涉及的数据按程序要求组成数据文件,再用程序来调用,数据文件与程序文件保持着一定的关系。
在计算机应用迅速发展的情况下,这种文件式管理方法便显出它的不足。比如,它使得数据通用性差、不便于移植、在不同文件中存储大量重复信息、浪费存储空间、更新不便等。
而数据库系统便能解决上述问题。数据库系统不从具体的应用程序出发,而是立足于数据本身的管理,它将所有数据保存在数据库中,进行科学的组织,并借助于数据库管理系统,以它为中介,与各种应用程序或应用系统接口,使之能方便地使用数据库中的数据。
其实简单地说,数据库就是一组经过计算机整理后的数据,存储在一个或多个文件中,而管理这个数据库的软件就称为数据库管理系统。一般一个数据库系统(Database System)
可以分为数据库(Database)与数据管理系统(Database Management System,DBMS)两个部分。主流的数据库软件有 Oracle、Informix、Sybase、SQL Server、PostgreSQL、MySQL、Access、FoxPro 和 Teradata 等等。
数据库在 Web 开发中的重要地位
归根结底,动态网站都是对数据进行操作,我们平时浏览网页时,会发现网页的内容会经常变化,而页面的主体结构框架没变,新闻就是一个典型。这是因为我们将新闻存储在了数据库中,用户在浏览时,程序就会根据用户所请求的新闻编号,将对应的新闻从数据库中读取出来,然后再以特定的格式响应给用户。
Web 系统的开发基本上是离不开数据库的,因为任何东西都要存放在数据库中。所谓的动态网站就是基于数据库开发的系统,最重要的就是数据管理,或者说我们在开发时都是在围绕数据库在写程序。所以作为一个 Web 程序员,只有先掌握一门数据库,才可能去进行软件开发。
- 系统 需求分析
2.1系统功能 分析
1.用户模块管理:用户登录、用户注册、用户的查询、添加、删除操作、
2.页面模块管理:页面菜单的展示、添加操作、修改操作、删除操作、
3.角色模块管理:用户角色列表的查看、删除等操作、
4.商品管理:商品信息的查看、添加、删除、
5.订单管理:订单管理信息操作、
6.用户评论模块管理:用户评论查询、添加、删除、
7.收藏模块管理:对喜欢水果的收藏管理
8.购物车管理:对水果商品加入购物车、移除购物车
9.修改密码管理以及个人信息查看管理
9.注销退出登录管理
2.2系统运行环境
JavaJDK1.8环境配置、
Java运行在idea软件上,
数据库用mysql5版本数据库、
数据库采用Nacicat Mysql可视化工具、
基于主流的谷歌浏览器运行展示以及F12控制台调试样式、
- 系统设计
3.1系统 模板 设计
系统主要设计采用Java语言开发、采用springboot为后台框架、数据库框架采用mybatis、前端采用jquery、layui框架等
主要模块设计如下:
1.用户模块管理:用户登录、用户注册、用户的查询、添加、删除操作、
2.页面模块管理:页面菜单的展示、添加操作、修改操作、删除操作、
3.角色模块管理:用户角色列表的查看、删除等操作、
4.商品管理:商品信息的查看、添加、删除、
5.订单管理:订单管理信息操作、
6.用户评论模块管理:用户评论查询、添加、删除、
7.收藏模块管理:对喜欢水果的收藏管理
8.购物车管理:对水果商品加入购物车、移除购物车
9.修改密码管理以及个人信息查看管理
9.注销退出登录管理
3. 2 系统流程描述
- 3项目源码架构设计
- 系统实现
4.1 程序主要类
4.1.1用户管理员admin实体类
private Integer id; //管理员ID
@ValidateEntity(required=true,errorRequiredMsg="管理员对应角色不能为空!")
private Integer roleId; //管理员对应角色ID
@ValidateEntity(requiredMaxLength=true,maxLength=256,errorMaxLengthMsg="管理员头像长度不能大于256!")
private String headPic; //管理员头像
@ValidateEntity(required=true,requiredMaxLength=true,requiredMinLength=true,maxLength=16,minLength=1,errorRequiredMsg="管理员名称不能为空!",errorMaxLengthMsg="管理员名称长度不能大于16!",errorMinLengthMsg="管理员名称长度不能小于1!")
private String name; //管理员姓名
@ValidateEntity(required=true,requiredMaxLength=true,requiredMinLength=true,maxLength=16,minLength=5,errorRequiredMsg="管理员密码不能为空!",errorMaxLengthMsg="管理员密码长度不能大于16!",errorMinLengthMsg="管理员密码长度不能小于5!")
private String password; //管理员密码 默认为:123456
private Integer sex; //管理员性别:1:男;2:女;3:未知 默认为3:未知
@ValidateEntity(requiredMaxLength=true,maxLength=128,errorMaxLengthMsg="管理员地址长度不能大于128!")
private String address; //管理员地址
private Long mobile; //管理员电话
@ValidateEntity(required=true,errorRequiredMsg="管理员状态不能为空!")
private Integer state; //管理员状态:1:启用;2:冻结
4.1.4公告 Announcement 实体类
@Data
public class Announcement {
private Integer id; //公告ID
@ValidateEntity(required=true,requiredMaxLength=true,requiredMinLength=true,maxLength=256,minLength=1,errorRequiredMsg="公告内容不能为空!",errorMaxLengthMsg="公告内容长度不能大于256!",errorMinLengthMsg="公告内容长度不能小于1!")
private String content; //公告内容
@ValidateEntity(required=true,errorRequiredMsg="公告发布对应管理员角色不能为空!")
private Integer adminId; //公告发布所属管理员
private Date createTime; //公告创建时间
private Date updateTime; //公告更新时间
4.1.4菜单Menu实体类
public class Menu {
private Integer id; //菜单ID
@ValidateEntity(required=true,errorRequiredMsg="上级菜单不能为空!")
private Integer parentId; //上级菜单的ID:默认为0
@ValidateEntity(required=true,requiredMaxLength=true,requiredMinLength=true,minLength=1,maxLength=32,errorRequiredMsg="菜单名称不能为空!",errorMinLengthMsg="菜单名称长度至少为1!",errorMaxLengthMsg="菜单名称长度不能大于32!")
private String name; //菜单名称
@ValidateEntity(requiredMaxLength=true,maxLength=256,errorMaxLengthMsg="菜单路径长度不能大于256!")
private String url; //菜单路径
@ValidateEntity(requiredMaxValue=true,requiredMinValue=true,required=true,maxValue=1024,minValue=0,errorMaxValueMsg="菜单排序最大值为1024!",errorMinValueMsg="菜单排序最小值为0!",errorRequiredMsg="菜单排序不能为空!")
private Integer sort; //菜单排序:默认为0,值越大则在同级别越优先显示
@ValidateEntity(required=true,requiredMaxLength=true,maxLength=64,errorRequiredMsg="菜单图标不能为空!",errorMaxLengthMsg="菜单图标长度不能大于64!")
private String icon; //菜单图标
@ValidateEntity(required=true,errorRequiredMsg="菜单状态不能为空!")
private Integer state; //菜单状态:1:开启;2:停用
4.1.4评论Comment实体类
public class Comment {
private Long id; //评论id
@ValidateEntity(required=true,errorRequiredMsg="评论对应的商品不能为空!")
private Long productId; //评论对应的商品id
private Product product; //评论对应的商品
@ValidateEntity(required=true,errorRequiredMsg="评论对应的用户不能为空!")
private Long userId; //评论对应的用户id
private User user; //评论对应的用户
@ValidateEntity(required=true,requiredMaxLength=true,requiredMinLength=true,maxLength=100,minLength=1,errorRequiredMsg="评论内容不能为空!",errorMinLengthMsg="评论内容的长度不能小于1",errorMaxLengthMsg="评论内容的长度不能大于100!")
private String content; //评论内容
private Date createTime; //评论创建时间
4.1.4订单order实体类
private Long id; //订单id
private Long orderNo; //订单流水号
private Long userId; //订单所属用户id
private User user; //订单所属用户
private Integer state; //订单状态 0:未支付;1:已支付,待发货;2:已取消;3:已送达,待签收;4:已签收;5:已发货
private BigDecimal totalPrice; //订单总价
private Long addressId; //订单对应的配送地址id
private Address address; //订单对应的配送地址
private String remark; //订单留言
private Integer isDeleted; //用户是否删除订单 0:未删除;1:已删除
private List<OrderItem> orderItemList; //订单对应的订单详情
private Date createTime; //订单创建时间
private Date updateTime; //订单更新时间
4.1.4商品Product实体类
public class Product {
private Long id; //商品id
@ValidateEntity(required=true,requiredMaxLength=true,requiredMinLength=true,maxLength=16,minLength=1,errorRequiredMsg="商品名称不能为空!",errorMaxLengthMsg="商品名称长度不能大于16!",errorMinLengthMsg="商品名称长度不能小于1!")
private String productName; //商品的名称
@ValidateEntity(required=true,requiredMaxLength=true,requiredMinLength=true,maxLength=32,minLength=1,errorRequiredMsg="商品详情不能为空!",errorMaxLengthMsg="商品详情长度不能大于32!",errorMinLengthMsg="商品详情长度不能小于1!")
private String info; //商品的详情
@ValidateEntity(requiredMaxLength=true,maxLength=256,errorMaxLengthMsg="商品图片路径长度不能大于256!")
private String productPic; //商品的图片
@ValidateEntity(required=true,requiredMinValue=true,requiredMaxValue=true,maxValue=100000000.00,minValue=0.00,errorRequiredMsg="商品价格不能为空!",errorMaxValueMsg="商品价格不合理,请调低价格!",errorMinValueMsg="商品价格不能低于0.00元!")
private BigDecimal price; //商品的价格
@ValidateEntity(required=true,requiredMinValue=true,requiredMaxValue=true,maxValue=100000000,minValue=0,errorRequiredMsg="商品库存不能为空!",errorMaxValueMsg="商品库存不合理,请调低库存量!",errorMinValueMsg="商品库存不能低于0个!")
private Integer stock; //商品的库存
private Integer sellNum; //商品的销售数量
private Integer commentNum; //商品的评论数量
@ValidateEntity(required=true,errorRequiredMsg="该商品对应的商品种类不能为空!")
private Long categoryId; //商品所属的商品种类id
private ProductCategory productCategory; //商品所属的商品种类
private Date createTime; //商品创建时间
private Date updateTime; //商品更新时间
4.1.4用户User实体类
public class User {
private Long id; //用户id
@ValidateEntity(required=true,requiredMaxLength=true,requiredMinLength=true,maxLength=8,minLength=1,errorRequiredMsg="用户名称不能为空!",errorMaxLengthMsg="用户名称长度不能大于8!",errorMinLengthMsg="用户名称长度不能小于1!")
private String username; //用户名称
@ValidateEntity(required=true,requiredMaxLength=true,requiredMinLength=true,maxLength=16,minLength=6,errorRequiredMsg="密码不能为空!",errorMaxLengthMsg="密码长度不能大于16!",errorMinLengthMsg="密码长度不能小于6!")
private String password; //用户密码
@ValidateEntity(required=true,requiredMaxLength=true,requiredMinLength=true,maxLength=64,minLength=1,errorRequiredMsg="电子邮箱不能为空!",errorMaxLengthMsg="电子邮箱长度不能大于64!",errorMinLengthMsg="电子邮箱长度不能小于1!")
private String email; //用户电子邮箱
@ValidateEntity(required=true,requiredMaxLength=true,requiredMinLength=true,maxLength=11,minLength=11,errorRequiredMsg="手机号码不能为空!",errorMaxLengthMsg="请输入11位手机号码!",errorMinLengthMsg="请输入11位手机号码!")
private String phone; //用户手机号码
@ValidateEntity(requiredMaxLength=true,maxLength=256,errorMaxLengthMsg="头像路径长度不能大于256!")
private String headPic; //用户头像
private Date createTime; //用户信息创建时间
private Date updateTime; //用户信息更改时间
4.3系统功能主要实现模块截图
4.3.1 项目首页
前台地址:http://localhost:8080/home/system/index
4.3.1首页 :
//表单数据序列化
var data = $('#login_form').serialize();
$.ajax({
url:'/home/user/login',
data:data,
type:'post',
dataType:'json',
success:function(data){
if(data.code == 0){
setTokenToCookie(data.msg, 7);
window.location.href = "/home/system/index";
}else{
layer.alert(data.msg, {icon: 5});
}
},
error:function(){
layer.alert("网络错误,登录失败!", {icon: 5});
}
});
4.3.2 注册页面:
@RequestMapping(value = "/doRegist")
@ResponseBody
public ResultMap doRegist(User user) {
System.out.println(user);
User u = userService.getUserByPhoneAndName(user.getPhone(), null);
if (u != null){
return resultMap.success().message("该手机号已注册!");
}
try {
user.setPassword(MD5.md5(user.getPassword()));
user.setCreateTime(new Date());
userService.save(user);
String[] ids = new String[1];
ids[0] = user.getId()+"";
// 普通用户
userRoleService.addUserRole(2, ids);
return resultMap.success().message("注册成功");
}catch (Exception e){
e.printStackTrace();
return resultMap.fail().message("注册失败");
}
}
4.3.2 主页面
系统首页水果专区
4.3.2 .1 购物车 管理
添加用户:
4.3.2 .2 我的订单管理
添加页面菜单:
输入菜单名称、URL进行保存添加。
4.3.2 .3 个人 信息管理
添加宠物信息:
删除宠物信息:
4.3.2 .5 修改密码管理
4.3.2 .6 用户评论收藏
4.3.2 .4 收货地址管理
4.3.4部分 关键源码展示:
4.3.4.1 登录模块:
/**
* 登录表单验证处理
* @param admin
* @param cpacha
* @return
*/
@RequestMapping(value="/login",method=RequestMethod.POST)
@ResponseBody
public ResponseVo<Boolean> login(Admin admin, String cpacha, HttpServletRequest request){
if(admin == null) {
return ResponseVo.errorByMsg(CodeMsg.DATA_ERROR);
}
if(StringUtil.isEmpty(cpacha)) {
return ResponseVo.errorByMsg(CodeMsg.CPACHA_EMPTY);
}
String correct_cpacha = (String) request.getSession().getAttribute("admin_login");
//判断验证码是否过期
if(StringUtil.isEmpty(correct_cpacha)){
return ResponseVo.errorByMsg(CodeMsg.CPACHA_EXPIRE);
}
if(!cpacha.toLowerCase().equals(correct_cpacha.toLowerCase())) {
return ResponseVo.errorByMsg(CodeMsg.CPACHA_ERROR);
}
//去数据库查询数据验证
Admin selectByNameAndPassword = adminMapper.selectByNameAndPassword(admin.getName(), admin.getPassword());
if(selectByNameAndPassword == null) {
return ResponseVo.errorByMsg(CodeMsg.USERNAME_OR_PASSWORD_ERROR);
}
//验证该用户是否被冻结
if(selectByNameAndPassword.getState().intValue() == AdminStateEnum.STOP.getCode().intValue()) {
return ResponseVo.errorByMsg(CodeMsg.USER_STATE_ERROR);
}
//验证该用户是否无权限
List<Authority> selectByRoleId = authorityMapper.selectByRoleId(selectByNameAndPassword.getRoleId());
if(selectByRoleId == null || selectByRoleId.size() == 0) {
return ResponseVo.errorByMsg(CodeMsg.USER_AUTHORITY_ERROR);
}
//创建权限
request.getSession().setAttribute(SessionConstant.SESSION_ADMIN_LOGIN_KEY, selectByNameAndPassword);
return ResponseVo.success(true);
4.3.4.2 springboot全局配置文件:
########################################################
########################################################
server.port=8080
#1800s
server.servlet.session.timeout=1800
spring.jackson.time-zone=GMT+8
spring.jackson.date-format=yyyy-MM-dd HH:mm:ss
#定义加载的配置文件
spring.profiles.active=dev
###FREEMARKER
#设置是否允许HttpServletRequest属性重写(隐藏)控制器生成的同名模型属性。
spring.freemarker.allow-request-override=false
spring.freemarker.cache=false
spring.freemarker.check-template-location=true
spring.freemarker.charset=UTF-8
spring.freemarker.content-type=text/html
#设置是否应在与模板合并之前将所有请求属性添加到模型中。
spring.freemarker.expose-request-attributes=false
#设置是否允许HttpSession属性重写(隐藏)控制器生成的同名模型属性。
spring.freemarker.expose-session-attributes=false
#设置是否公开名为"Spring macro RequestContext"的RequestContext供Spring的宏库使用.
spring.freemarker.expose-spring-macro-helpers=false
spring.freemarker.prefix=
#spring.freemarker.request-context-attribute=
#spring.freemarker.settings.
spring.freemarker.settings.template_update_delay=0
spring.freemarker.settings.default_encoding=UTF-8
spring.freemarker.suffix=.ftl
spring.freemarker.template-loader-path=classpath:/templates/
#spring.freemarker.view-names= # whitelist of view names that can be resolved
spring.freemarker.settings.number_format=0.##
spring.servlet.multipart.max-file-size=300MB
spring.servlet.multipart.max-request-size=300MB4.3.4.3 config.properties:
#文件上传路径,文件存放的真实路径
FILEPATH=/tmp/files/
#资源映射地址为file:D://User/
file.location=file:/tmp/files/
4.3.4.3 数据库连接 配置文件:
#数据源的地址
spring.datasource.url=jdbc:mysql://127.0.0.1:3307/db_fruit_vegetable_shop?serverTimezone=GMT%2b8&useUnicode=true&characterEncoding=utf8
spring.datasource.username=root
spring.datasource.password=crit@2019
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.continue-on-error=false
spring.datasource.test-while-idle=true
#获取连接时候验证,会影响性能
spring.datasource.test-on-borrow=false
#在连接归还到连接池时是否测试该连接
spring.datasource.test-on-return=false
spring.datasource.validation-query=SELECT 1 FROM DUAL
#空闲连接回收的时间间隔,与test-while-idle一起使用,设置5分钟
spring.datasource.time-between-eviction-runs-millis=300000
#连接池空闲连接的有效时间 ,设置30分钟
spring.datasource.min-evictable-idle-time-millis=1800000
spring.datasource.initial-size=5
#指定连接池中最大的活跃连接数.
spring.datasource.max-active=50
#指定连接池等待连接返回的最大等待时间,毫秒单位.
spring.datasource.max-wait=60000
#指定必须保持连接的最小值
spring.datasource.min-idle=5
#热部署生效
spring.devtools.restart.enabled=true
#mybatis驼峰匹配开启
mybatis.configuration.map-underscore-to-camel-case=true
控制台日志配置
mybatis.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
#mapper文件扫描路径
mybatis.mapper-locations=classpath*:mappers/admin/*.xml,classpath*:mappers/home/*.xml,classpath*:mappers/common/*.xml
#mail配置
spring.mail.protocol=smtp
spring.mail.default-encoding=UTF-8
spring.mail.username=15959100218@163.com
spring.mail.password=LBWCLXTCZNGUMVMZ
spring.mail.test-connection=true
spring.mail.properties.mail.smtp.auth=true
spring.mail.properties.mail.smtp.starttls.enable=true
spring.mail.properties.mail.smtp.starttls.required=true
#redis配置
spring.redis.host=127.0.0.1
spring.redis.port=6379
spring.redis.database=0
#图片上传设置
yjq.upload.photo.sufix=.jpg,.png,.gif,.jpeg
#1024KB
yjq.upload.photo.maxsize=1024
#200MB = 204800KB
yjq.upload.attachment.maxsize=204800
yjq.upload.photo.path=D:/IDEA_project/FruitAndVegetableShop/src/main/resources/upload/photo/
yjq.upload.attachment.path=D:/IDEA_project/FruitAndVegetableShop/src/main/resources/upload/attachment/
4.3.4.4 logback-spring.xml日志文件
<?xml version="1.0" encoding="UTF-8" ?>
<configuration>
<appender name="consoleApp" class="ch.qos.logback.core.ConsoleAppender">
<layout class="ch.qos.logback.classic.PatternLayout">
<pattern>
%date{yyyy-MM-dd HH:mm:ss.SSS} %-5level[%thread]%logger{56}.%method:%L -%msg%n
</pattern>
</layout>
</appender>
<appender name="fileInfoApp" class="ch.qos.logback.core.rolling.RollingFileAppender">
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>ERROR</level>
<onMatch>DENY</onMatch>
<onMismatch>ACCEPT</onMismatch>
</filter>
<encoder>
<pattern>
%date{yyyy-MM-dd HH:mm:ss.SSS} %-5level[%thread]%logger{56}.%method:%L -%msg%n
</pattern>
</encoder>
<!-- 滚动策略 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 路径 -->
<fileNamePattern>app_log/log/app.info.%d{yyyy-MM-dd}.log</fileNamePattern>
<!--重启清理日志文件-->
<cleanHistoryOnStart>true</cleanHistoryOnStart>
<!--日志文件保留天数 10天-->
<maxHistory>10</maxHistory>
</rollingPolicy>
</appender>
<appender name="fileErrorApp" class="ch.qos.logback.core.rolling.RollingFileAppender">
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>ERROR</level>
</filter>
<encoder>
<pattern>
%date{yyyy-MM-dd HH:mm:ss.SSS} %-5level[%thread]%logger{56}.%method:%L -%msg%n
</pattern>
</encoder>
<!-- 设置滚动策略 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 路径 -->
<fileNamePattern>app_log/log/app.err.%d{yyyy-MM-dd}.log</fileNamePattern>
<!--重启清理日志文件-->
<cleanHistoryOnStart>true</cleanHistoryOnStart>
<!--日志文件保留天数 10天-->
<maxHistory>10</maxHistory>
</rollingPolicy>
</appender>
<root level="INFO">
<appender-ref ref="consoleApp"/>
<appender-ref ref="fileInfoApp"/>
<appender-ref ref="fileErrorApp"/>
</root>
</configuration>
4.3.4.5代码主启动类 :
/**
* 项目入口启动文件
*
*/
@SpringBootApplication
@MapperScan({"com.yjq.programmer.dao.admin","com.yjq.programmer.dao.home","com.yjq.programmer.dao.common"})
public class FruitAndVegetableShop
{
public static void main( String[] args )
{
SpringApplication.run(FruitAndVegetableShop.class, args);
}
}
4.3.4.7 过滤器实现类:
//后台管理员登录拦截器无需拦截的url Arrays.asList:字符串数组转化为List
public static List<String> adminLoginExcludePathPatterns = Arrays.asList(
"/admin/system/login",
"/common/cpacha/generate_cpacha",
"/admin/login/**",
"/admin/common/**",
"/admin/X-admin-2.2/**",
"/home/css/**",
"/home/common/**",
"/home/font/**",
"/home/images/**",
"/home/js/**",
"/home/system/js/slider.js",
"/ueditor/**",
"/photo/**"
);
//前台用户登录拦截器无需拦截的url Arrays.asList:字符串数组转化为List
public static List<String> userLoginExcludePathPatterns = Arrays.asList(
"/admin/system/login",
"/home/system/js/slider.js",
"/common/cpacha/generate_cpacha",
"/admin/login/**",
"/admin/common/**",
"/admin/X-admin-2.2/**",
"/home/css/**",
"/home/common/**",
"/home/font/**",
"/home/images/**",
"/home/js/**",
"/ueditor/**",
"/photo/**"
);
//前台用户访问需要拦截但无需验证的url Arrays.asList:字符串数组转化为List
public static List<String> userNotNeedConfirmUrl = Arrays.asList(
"/home/system/index",
"/home/user/login",
"/home/user/register",
"/home/product/fruit",
"/home/product/vegetable",
"/home/product/detail"
4. 4 数据库表设计
4.4.0 数据库三范式要求:
一、第一范式
1NF是对属性的原子性,要求属性具有原子性,不可再分解;
二、第二范式
2NF是对记录的唯一性,要求记录有唯一标识,即实体的唯一性,即不存在部分依赖;
三、第三范式
3NF是对字段的冗余性,要求任何字段不能由其他字段派生出来,它要求字段没有冗余,即不存在传递依赖;
四、反范式化
一般说来,数据库只需满足第三范式(3NF)就行了。
没有冗余的数据库设计可以做到。但是,没有冗余的数据库未必是最好的数据库,有时为了提高运行效率,就必须降低范式标准,适当保留冗余数据。具体做法是:在概念数据模型设计时遵守第三范式,降低范式标准的工作放到物理数据模型设计时考虑。降低范式就是增加字段,允许冗余,达到以空间换时间的目的。
〖例〗:有一张存放商品的基本表,"金额"这个字段的存在,表明该表的设计不满足第三范式,因为"金额"可以由"单价"乘以"数量"得到,说明"金额"是冗余字段。但是,增加"金额"这个冗余字段,可以提高查询统计的速度,这就是以空间换时间的作法。
在Rose 2002中,规定列有两种类型:数据列和计算列。"金额"这样的列被称为"计算列",而"单价"和"数量"这样的列被称为"数据列"。
五、范式化设计和反范式化设计的优缺点
5.1 范式化
优点:
缺点:
5.2 反范式化
优点:
缺点:
数据库采用mysql5版本、满足数据库设计三范式。
编码采用utf8 -- UTF-8 Unicode
排序规则采用utf8_general_ci
4.4.1数据库表ER图
4.4.2用户表设计
主要字段有:用户名、密码、邮箱、地址、个人信息、创建时间、手机号等信息
4.4.3角色表设计
主要字段有:角色id、用户、备注信息、创建时间
4.4.4菜单表设计
主要字段有:菜单id、pid、菜单名称、菜单路径、类型、图标、状态标识等字段
4.4.5商品表设计
主要字段有:id、商品名称、详情、图片、库存数量、销量、评论、种类、等
4.4.6订单表设计
主要字段有:id、用户id、订单流水号、订单状、总价、配送地址等
4.4.7评论表设计
主要字段有:id、用户id、商品id、评论时间等
4.4.6数据库sql文件
/*
Navicat MySQL Data Transfer
Source Server : 本地连接
Source Server Version : 50505
Source Host : localhost:3306
Source Database : db_fruit_vegetable_shop
Target Server Type : MYSQL
Target Server Version : 50505
File Encoding : 65001
Date: 2021-3-1 15:06:22
*/
SET FOREIGN_KEY_CHECKS=0;
-- Table structure for `bms_admin`
DROP TABLE IF EXISTS `bms_admin`;
CREATE TABLE `bms_admin` (
`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '管理员ID',
`role_id` int(11) NOT NULL DEFAULT '0' COMMENT '管理员对应角色ID;默认0:无',
`head_pic` varchar(256) DEFAULT 'common/default_img.jpg' COMMENT '管理员头像',
`password` varchar(16) NOT NULL DEFAULT '123456' COMMENT '管理员密码',
`name` varchar(16) NOT NULL COMMENT '管理员姓名',
`sex` int(11) DEFAULT '3' COMMENT '管理员性别:1:男;2:女;3:未知',
`address` varchar(128) DEFAULT NULL COMMENT '管理员地址',
`mobile` bigint(20) NOT NULL COMMENT '管理员电话',
`state` int(11) NOT NULL DEFAULT '1' COMMENT '管理员状态:1:启用;2:冻结',
`create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '管理员创建时间',
`update_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '管理员更新时间',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=22 DEFAULT CHARSET=utf8;
-- Records of bms_admin
INSERT INTO `bms_admin` VALUES ('1', '1', '20200807/1596731167923.jpg', '1234567', '杨杨吖', '1', '福建省厦门市湖里区水晶公寓1座402', '13774559485', '1', '2020-08-02 16:27:44', '2020-08-07 00:27:42');
INSERT INTO `bms_admin` VALUES ('9', '5', '20200803/1596444752079.jpg', '123456', '测试人员', '1', '福建省福州市鼓楼区金山佳园4座101', '13983776256', '1', '2020-08-03 15:46:46', '2020-08-07 00:01:31');
INSERT INTO `bms_admin` VALUES ('21', '5', '20200806/1596709959740.jpg', '123456', '开发人员', '2', '福建省莆田市秀屿区碧水公寓5座202', '14328448375', '1', '2020-08-06 18:33:22', '2020-08-06 18:33:53');
-- Table structure for `bms_announcement`
DROP TABLE IF EXISTS `bms_announcement`;
CREATE TABLE `bms_announcement` (
`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '公告ID',
`content` varchar(256) NOT NULL COMMENT '公告内容',
`admin_id` int(11) NOT NULL COMMENT '公告发布所属管理员',
`create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '公告创建时间',
`update_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '公告更新时间',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=9 DEFAULT CHARSET=utf8;
-- Records of bms_announcement
INSERT INTO `bms_announcement` VALUES ('7', '测试人员快把任务给我做了', '1', '2020-08-07 18:23:30', '2020-08-07 18:23:30');
INSERT INTO `bms_announcement` VALUES ('8', '开发人员也速度点', '1', '2020-08-07 18:23:47', '2020-08-07 18:23:47');
-- Table structure for `bms_attachment`
DROP TABLE IF EXISTS `bms_attachment`;
CREATE TABLE `bms_attachment` (
`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '附件ID',
`sender_id` int(11) NOT NULL COMMENT '发件人ID',
`url` varchar(256) NOT NULL COMMENT '附件保存路径',
`name` varchar(256) NOT NULL COMMENT '附件名称',
`size` decimal(10,2) NOT NULL DEFAULT '0.00' COMMENT '附件大小:单位为KB;默认为0.00',
`create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '附件创建时间',
`update_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '附件更新时间',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;
-- Records of bms_attachment
INSERT INTO `bms_attachment` VALUES ('1', '1', '20200807/1596812677479.docx', '感谢文档.docx', '10.89', '2020-08-07 23:04:37', '2020-08-07 23:04:37');
INSERT INTO `bms_attachment` VALUES ('3', '1', '20200808/1596822984571.docx', '感谢文档.docx', '10.89', '2020-08-08 01:56:24', '2020-08-08 01:56:24');
-- Table structure for `bms_authority`
DROP TABLE IF EXISTS `bms_authority`;
CREATE TABLE `bms_authority` (
`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '权限ID',
`menu_id` int(11) NOT NULL COMMENT '权限对应的菜单ID',
`role_id` int(11) NOT NULL COMMENT '权限对应的角色ID',
`create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '权限创建时间',
`update_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '权限更改时间',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=489 DEFAULT CHARSET=utf8;
-- Records of bms_authority
INSERT INTO `bms_authority` VALUES ('99', '11', '5', '2020-08-06 18:40:25', '2020-08-06 18:40:25');
INSERT INTO `bms_authority` VALUES ('100', '15', '5', '2020-08-06 18:40:25', '2020-08-06 18:40:25');
INSERT INTO `bms_authority` VALUES ('101', '16', '5', '2020-08-06 18:40:25', '2020-08-06 18:40:25');
INSERT INTO `bms_authority` VALUES ('102', '17', '5', '2020-08-06 18:40:25', '2020-08-06 18:40:25');
INSERT INTO `bms_authority` VALUES ('103', '18', '5', '2020-08-06 18:40:25', '2020-08-06 18:40:25');
INSERT INTO `bms_authority` VALUES ('104', '88', '5', '2020-08-06 18:40:25', '2020-08-06 18:40:25');
INSERT INTO `bms_authority` VALUES ('105', '89', '5', '2020-08-06 18:40:25', '2020-08-06 18:40:25');
INSERT INTO `bms_authority` VALUES ('106', '90', '5', '2020-08-06 18:40:25', '2020-08-06 18:40:25');
INSERT INTO `bms_authority` VALUES ('107', '95', '5', '2020-08-06 18:40:25', '2020-08-06 18:40:25');
INSERT INTO `bms_authority` VALUES ('108', '96', '5', '2020-08-06 18:40:25', '2020-08-06 18:40:25');
INSERT INTO `bms_authority` VALUES ('109', '91', '5', '2020-08-06 18:40:25', '2020-08-06 18:40:25');
INSERT INTO `bms_authority` VALUES ('110', '97', '5', '2020-08-06 18:40:25', '2020-08-06 18:40:25');
INSERT INTO `bms_authority` VALUES ('111', '98', '5', '2020-08-06 18:40:25', '2020-08-06 18:40:25');
INSERT INTO `bms_authority` VALUES ('441', '1', '1', '2020-11-19 10:33:11', '2020-11-19 10:33:11');
INSERT INTO `bms_authority` VALUES ('442', '2', '1', '2020-11-19 10:33:11', '2020-11-19 10:33:11');
INSERT INTO `bms_authority` VALUES ('443', '3', '1', '2020-11-19 10:33:11', '2020-11-19 10:33:11');
INSERT INTO `bms_authority` VALUES ('444', '4', '1', '2020-11-19 10:33:11', '2020-11-19 10:33:11');
INSERT INTO `bms_authority` VALUES ('445', '10', '1', '2020-11-19 10:33:11', '2020-11-19 10:33:11');
INSERT INTO `bms_authority` VALUES ('446', '14', '1', '2020-11-19 10:33:11', '2020-11-19 10:33:11');
INSERT INTO `bms_authority` VALUES ('447', '11', '1', '2020-11-19 10:33:11', '2020-11-19 10:33:11');
INSERT INTO `bms_authority` VALUES ('448', '15', '1', '2020-11-19 10:33:11', '2020-11-19 10:33:11');
INSERT INTO `bms_authority` VALUES ('449', '16', '1', '2020-11-19 10:33:11', '2020-11-19 10:33:11');
INSERT INTO `bms_authority` VALUES ('450', '17', '1', '2020-11-19 10:33:11', '2020-11-19 10:33:11');
INSERT INTO `bms_authority` VALUES ('451', '18', '1', '2020-11-19 10:33:11', '2020-11-19 10:33:11');
INSERT INTO `bms_authority` VALUES ('452', '25', '1', '2020-11-19 10:33:11', '2020-11-19 10:33:11');
INSERT INTO `bms_authority` VALUES ('453', '26', '1', '2020-11-19 10:33:11', '2020-11-19 10:33:11');
INSERT INTO `bms_authority` VALUES ('454', '81', '1', '2020-11-19 10:33:11', '2020-11-19 10:33:11');
INSERT INTO `bms_authority` VALUES ('455', '82', '1', '2020-11-19 10:33:11', '2020-11-19 10:33:11');
INSERT INTO `bms_authority` VALUES ('456', '83', '1', '2020-11-19 10:33:11', '2020-11-19 10:33:11');
INSERT INTO `bms_authority` VALUES ('457', '88', '1', '2020-11-19 10:33:11', '2020-11-19 10:33:11');
INSERT INTO `bms_authority` VALUES ('458', '89', '1', '2020-11-19 10:33:11', '2020-11-19 10:33:11');
INSERT INTO `bms_authority` VALUES ('459', '90', '1', '2020-11-19 10:33:11', '2020-11-19 10:33:11');
INSERT INTO `bms_authority` VALUES ('460', '95', '1', '2020-11-19 10:33:11', '2020-11-19 10:33:11');
INSERT INTO `bms_authority` VALUES ('461', '96', '1', '2020-11-19 10:33:11', '2020-11-19 10:33:11');
INSERT INTO `bms_authority` VALUES ('462', '91', '1', '2020-11-19 10:33:11', '2020-11-19 10:33:11');
INSERT INTO `bms_authority` VALUES ('463', '97', '1', '2020-11-19 10:33:11', '2020-11-19 10:33:11');
INSERT INTO `bms_authority` VALUES ('464', '98', '1', '2020-11-19 10:33:11', '2020-11-19 10:33:11');
INSERT INTO `bms_authority` VALUES ('465', '108', '1', '2020-11-19 10:33:11', '2020-11-19 10:33:11');
INSERT INTO `bms_authority` VALUES ('466', '109', '1', '2020-11-19 10:33:11', '2020-11-19 10:33:11');
INSERT INTO `bms_authority` VALUES ('467', '110', '1', '2020-11-19 10:33:11', '2020-11-19 10:33:11');
INSERT INTO `bms_authority` VALUES ('468', '111', '1', '2020-11-19 10:33:11', '2020-11-19 10:33:11');
INSERT INTO `bms_authority` VALUES ('469', '112', '1', '2020-11-19 10:33:11', '2020-11-19 10:33:11');
INSERT INTO `bms_authority` VALUES ('470', '113', '1', '2020-11-19 10:33:11', '2020-11-19 10:33:11');
INSERT INTO `bms_authority` VALUES ('471', '115', '1', '2020-11-19 10:33:11', '2020-11-19 10:33:11');
INSERT INTO `bms_authority` VALUES ('472', '116', '1', '2020-11-19 10:33:11', '2020-11-19 10:33:11');
INSERT INTO `bms_authority` VALUES ('473', '117', '1', '2020-11-19 10:33:11', '2020-11-19 10:33:11');
INSERT INTO `bms_authority` VALUES ('474', '114', '1', '2020-11-19 10:33:11', '2020-11-19 10:33:11');
INSERT INTO `bms_authority` VALUES ('475', '118', '1', '2020-11-19 10:33:11', '2020-11-19 10:33:11');
INSERT INTO `bms_authority` VALUES ('476', '119', '1', '2020-11-19 10:33:11', '2020-11-19 10:33:11');
INSERT INTO `bms_authority` VALUES ('477', '120', '1', '2020-11-19 10:33:11', '2020-11-19 10:33:11');
INSERT INTO `bms_authority` VALUES ('478', '121', '1', '2020-11-19 10:33:11', '2020-11-19 10:33:11');
INSERT INTO `bms_authority` VALUES ('479', '122', '1', '2020-11-19 10:33:11', '2020-11-19 10:33:11');
INSERT INTO `bms_authority` VALUES ('480', '125', '1', '2020-11-19 10:33:11', '2020-11-19 10:33:11');
INSERT INTO `bms_authority` VALUES ('481', '126', '1', '2020-11-19 10:33:11', '2020-11-19 10:33:11');
INSERT INTO `bms_authority` VALUES ('482', '123', '1', '2020-11-19 10:33:11', '2020-11-19 10:33:11');
INSERT INTO `bms_authority` VALUES ('483', '124', '1', '2020-11-19 10:33:11', '2020-11-19 10:33:11');
INSERT INTO `bms_authority` VALUES ('484', '127', '1', '2020-11-19 10:33:11', '2020-11-19 10:33:11');
INSERT INTO `bms_authority` VALUES ('485', '128', '1', '2020-11-19 10:33:11', '2020-11-19 10:33:11');
INSERT INTO `bms_authority` VALUES ('486', '129', '1', '2020-11-19 10:33:11', '2020-11-19 10:33:11');
INSERT INTO `bms_authority` VALUES ('487', '130', '1', '2020-11-19 10:33:11', '2020-11-19 10:33:11');
INSERT INTO `bms_authority` VALUES ('488', '131', '1', '2020-11-19 10:33:11', '2020-11-19 10:33:11');
-- Table structure for `bms_mail`
DROP TABLE IF EXISTS `bms_mail`;
CREATE TABLE `bms_mail` (
`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '邮件ID',
`sender_id` int(11) NOT NULL COMMENT '邮件发件人ID',
`receiver_id` int(11) NOT NULL COMMENT '邮件收件人ID',
`title` varchar(64) NOT NULL COMMENT '邮件主题',
`content` longtext COMMENT '邮件正文',
`attachment_one` int(11) DEFAULT NULL COMMENT '邮件的附件1',
`attachment_two` int(11) DEFAULT NULL COMMENT '邮件的附件2',
`attachment_three` int(11) DEFAULT NULL COMMENT '邮件的附件3',
`delete_state` int(11) NOT NULL DEFAULT '1' COMMENT '邮件删除状态:1:双方均未删除 2:发送者删除;3:接收者删除',
`create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '邮件创建时间',
`update_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '邮件更新时间',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;
-- Records of bms_mail
INSERT INTO `bms_mail` VALUES ('1', '1', '1', '测试邮件', '<p>测试正文<img src=\"http://img.baidu.com/hi/bobo/B_0026.gif\\"/></p><p><img src=\"http://localhost:8080/ueditor/images/20200807/1596812716910.jpg\\" title=\"1596812716910.jpg\" alt=\"1596812716910.jpg\"/></p>', '1', null, null, '1', '2020-08-07 23:05:25', '2020-08-07 23:05:25');
INSERT INTO `bms_mail` VALUES ('2', '1', '9', '测试邮件', '<p>测试正文<img src=\"http://img.baidu.com/hi/bobo/B_0026.gif\\"/></p><p><img src=\"http://localhost:8080/ueditor/images/20200807/1596812716910.jpg\\" title=\"1596812716910.jpg\" alt=\"1596812716910.jpg\"/></p>', '1', null, null, '1', '2020-08-07 23:05:25', '2020-08-07 23:05:25');
INSERT INTO `bms_mail` VALUES ('3', '1', '21', '测试邮件', '<p>测试正文<img src=\"http://img.baidu.com/hi/bobo/B_0026.gif\\"/></p><p><img src=\"http://localhost:8080/ueditor/images/20200807/1596812716910.jpg\\" title=\"1596812716910.jpg\" alt=\"1596812716910.jpg\"/></p>', '1', null, null, '1', '2020-08-07 23:05:25', '2020-08-07 23:05:25');
-- Table structure for `bms_menu`
DROP TABLE IF EXISTS `bms_menu`;
CREATE TABLE `bms_menu` (
`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '菜单ID',
`parent_id` int(11) NOT NULL DEFAULT '0' COMMENT '上级菜单的ID:默认为0',
`name` varchar(32) NOT NULL COMMENT '菜单名称',
`url` varchar(256) DEFAULT NULL COMMENT '菜单路径',
`sort` int(11) NOT NULL DEFAULT '0' COMMENT '菜单排序:默认为0,值越大则在同级别越优先显示',
`icon` varchar(64) NOT NULL COMMENT '菜单图标',
`state` int(11) NOT NULL DEFAULT '1' COMMENT '菜单状态:1:开启;2:停用',
`create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '菜单创建时间',
`update_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '菜单更新时间',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=132 DEFAULT CHARSET=utf8;