ibooking项目设计介绍(一个基于SSH的外卖点餐系统)

一、源码路径

https://github.com/weiganyi/ibooking

 

二、界面

通过浏览器访问web网站,可以看到界面如下:

 

 

 

三、背景

这两年来O2O的概念越来越火热,O2O因为能够把线下的资源通过线上的信息沟通渠道进行连接,影响着很多实体行业未来的发展。

这个项目就是为餐饮店提供线上外卖订餐服务的web网站,具有O2O网站的特点。网站有顾客和管理员两类角色,分别对于与餐饮店的顾客和餐饮店自身。用户在网站上注册后会留下用户的地址和联系电话,这些信息会作为送外卖时的用户信息,然后用户能够在网站上看到餐饮店的所有菜品图片,选中后到购物车下单,就会生成一个订单,餐饮店后台可以看到这些订单,然后完成后续的餐品制作和送达服务。

系统后台采用的是成熟的SSH框架来搭建服务,前端仍然是用jsp来拼接页面,所以页面还是在后台生成的。由于本人是后台开发,所以为了美化界面采用bootstrapcss框架,在js框架方面只是使用了jquery,并没有使用其他js框架。数据库方面使用的mysql,对于用户访问量大的几个表采用了redis做为缓存,提高响应速度。

 

四、功能实现

1、用户功能

1)菜品预定:菜品展示(主页)、购物车、订单列表、订单详情

2)注册登录:注册、登录、用户信息

2、管理员功能

1)用户管理

2)订单管理

3)图片管理

4)菜品管理

5)菜品类型管理

6)配置管理

 

五、总体设计思路

1、数据库设计

1)其中ib_menu_type表存储菜品类型信息,ib_menu表存储菜品信息,ib_option表存储配置信息,ib_user表存储用户信息,ib_shopping表存储用户购物车信息,ib_order表存储订单信息,ib_order_detail表存储订单详情信息,这7个表为关系型表,使用mysql数据库存储。它们的具体字段如下:

create table ib_menu_type(

    menu_type_id int(4) not null primary key auto_increment,

    menu_type_name char(255) not null);

create table ib_menu(

    menu_id int(4) not null primary key auto_increment,

    menu_name char(255) not null,

    menu_price int(16) not null,

    menu_pic_addr char(255) not null,

    menu_type_id int(4) not null);

create table ib_option(

    option_id int(4) not null primary key auto_increment,

    option_name char(255) not null,

    option_value char(255) not null);

create table ib_user(

    user_id int(16) not null primary key auto_increment,

    user_name char(255) not null,

    user_passwd char(255) not null,

    user_auth enum('admin', 'customer') not null,

    user_tel char(255) not null,

    user_addr char(255) not null);

create table ib_shopping(

    shopping_id int(16) not null primary key auto_increment,

    shopping_user_name char(255) not null,

    shopping_menu_name char(255) not null,

    shopping_menu_price int(16) not null,

    shopping_amount int(16) not null,

    shopping_remark char(255) not null);

create table ib_order(

    order_id int(16) not null primary key auto_increment,

    order_user_name char(255) not null,

    order_time datetime not null,

    order_admin_name char(255) not null,

    order_accept int(1) not null);

create table ib_order_detail(

    detail_id int(16) not null primary key auto_increment,

    detail_order_id int(16) not null,

    detail_menu_name char(255) not null,

    detail_menu_price int(16) not null,

    detail_amount int(16) not null,

    detail_remark char(255) not null);

2)用户访问量大的menumenutypeoption三个表使用redis缓存,因为这几个表不会频繁更新,不会造成缓存频繁失效,同时对于不同的用户,都会访问这几个表里相同的字段,所以它们使用缓存是比较有意义的。

3)由于使用了缓存,redismysql之间的数据同步设计是要点。最开始,我采用的读流程为在redis启动时先从mysql读入表的所有记录,后续直接从redis查询记录,写流程为先写入redis,并将其放入一个队列,队列消费者读取队列后再写入mysql,当mysql写失败时,要把redis写入的内容回滚。但经过分析这种设计是有问题的,redismysql数据同步肯定会涉及一个主次问题,之前的设计相当于redis为主,mysql为次,这样当mysql写失败时再回滚redis,这时redis可能已经有新数据写入了,再回滚会造成用户后写入的数据被刷掉了。正确的写流程应该以mysql为主,先写入mysql然后设置redis对应的键失效,这样成功写入mysql后,即便设置redis键失效操作失败,由于缓存可以设置有效期,也只是会在缓存有效期内暂时影响读到的数据,而数据由于已经写入了mysql是能够正确的保存的。

4)在写操作时redis生成自增id,然后插入mysql,必须保证redis生成的自增id大于mysql表的auto_increment当前值才能成功。所以redis启动时需要先读取mysql对应表的auto_increment值并保存,以后每次新增记录时,把auto_increment值加一并作为id值,这样就能够保证总是大于mysql表的auto_increment当前值。

5)在事务可靠性方面,当需要同时修改两个表的记录时,redismysql需要各自使用事务。redis自身有事务机制可以使用,而mysql可以使用SSH框架的aop声明式事务机制。

6redis的数据格式为了对应mysql表,需要有一条记录表示mysql表的索引,如set/get "ib_menu:test:id" "6",这里test是菜品名称,也是ib_menu表的索引是菜品名,这样就可以通过这条记录取得test菜品的id值,然后对应这个id值有系列记录表示mysql表的各个字段,如set/get "ib_menu:6:menu_price" "13",这里就表示id6的记录的menu_price字段值为13

2Web前端设计

1)在html页面的构造上,采用jsp脚本来完成。根据后台servlet逻辑处理完后生成的java bean对象,在jsp文件内,通过java脚本或者jstljsp技术,获取java bean对象拼装成所需要的html页面。

2)采用bootstrap来美化界面,采用bootstrap封装的一些组件。

3)界面按钮触发ajax请求,页面刷新方式有两种,一种响应只更新页面具体元素值,另一种是响应更新除了页头外的其余部分。

3Java后台服务设计

1)后台整体模块采用MVC经典分成架构,分为如下5层:

表现层:jsp页面。

MVC Action层:每个页面对应一个Action

业务逻辑层:负责后台业务逻辑实现。

DAO层:负责数据库和缓存的读写逻辑实现。

数据对象层:对数据库或缓存做对象映射。

2)对struts包含组件和特性的使用情况:

action:实现主要控制器逻辑。

国际化:使用全局国际化资源文件。

标签:主要使用s:text, s:property, s:fielderror和控制标签,structss:form比较弱,所以使用原生的并用bootstrap来增强。

类型转换:请求参数解析和响应参数构造由类型转换来实现,可能需要自定义转换器。

输入校验:文本输入需要增加校验,使用全局校验文件。

文件上传:使用封装的文件上传框架,包括拦截器文件过滤功能。

拦截器:实现一个自定义的管理员访问权限控制拦截器。

3)对hibernate数据库的封装的使用情况:

单表映射:ib_option使用单表映射。

关联映射:ib_menuib_menu_type使用无连接表的单向N-1关联。

hql查询:使用hibernate特有的hql查询语法,便于与HibernateDaoSupport框架集成。

开启二级缓存:由于使用了redis做缓存,所以不使用hibernate内置的二级缓存功能。

4)对spring特性的使用情况:

ioc依赖注入:如果采用spring来注入struts action会造成xml冗余,所以不使用这种方式,

使用spring启动hibernatesessionFactory,并用ioc注入的dao对象方式来进行数据库表访问。

aop切面注入:对多表操作使用xml方式声明式事务机制。

5)线程安全方面的考虑,因为HibernateTemplate是线程安全的,所以mysql访问不需要加锁,而redis访问需要加锁。

6)在服务部署上,使用nginx做反向代理,把请求转发到后端的tomcat服务器上进行处理。这也是常用的部署方式,因为目前系统文件比较少,所以没有把图片等静态资源放到nginx下这种动静分离的做法。

 

六、文件目录介绍

bin:系统脚本,如重启脚本

res\pic:图片资源文件

res\tmp:删除图片时的临时存放目录

WEB-INF\jsp:jsp文件

WEB-INF\jsp\manager:后台管理模块的jsp文件

WEB-INF\lib:依赖的jar

WEB-INF\src\ibooking\action:action的实现

WEB-INF\src\ibooking\action\authority:拦截器实现

WEB-INF\src\ibooking\action\base:action的父类

WEB-INF\src\ibooking\action\manager:后台管理模块的action实现

WEB-INF\src\ibooking\dao:dao层的父类

WEB-INF\src\ibooking\dao\impl:dao的实现

WEB-INF\src\ibooking\po:数据对象映射类

WEB-INF\src\ibooking\service:业务逻辑层父类

WEB-INF\src\ibooking\service\impl:业务逻辑层实现

WEB-INF\src\ibooking\util:辅助类实现

WEB-INF\src\ibooking\vo:视图层对象

WEB-INF\src\ibooking\vo\manager:后台管理模块的视图层对象

 

七、部署方法

1、源码下载后,用eclipse编译服务端源码。

2、在服务器上安装部署nginxtomcat,配置nginx把所有请求转发到tmcat,同时安装部署好mysqlredis

3、在tomcat/webapps下建立项目目录ibooking,然后把编译生成的目录和文件拷贝到ibooking下。

4、把根目录下的数据库备份文件ibooking_mysql_db.sql导入mysql

5、通过浏览器也可以访问系统的Web部分,使用顾客和管理员角色相关功能。

(完)

展开阅读全文

没有更多推荐了,返回首页