软件设计模式与体系结构课程设计是计算机科学与技术专业的一门专业核心课程。本课程设计旨在使学生深入理解软件设计模式与体系结构的概念、原理和应用,掌握面向对象设计模式和软件体系结构风格的分类、结构模式、特点及应用场景,培养学生综合运用所学知识、方法和技术进行软件系统分析、设计和实现的能力。通过分组完成某一领域或行业软件系统的分析、设计和开发,培养学生从软件系统进行系统分析设计的能力,以及良好的学习态度和团队合作精神。
本次课程设计以奶茶销售系统为案例,要求学生运用面向对象设计模式和软件体系结构风格,采用 Spring、SpringMVC、MyBatis、BootStrap 等技术,实现一个具有登录注册、数据存储、菜单查看、加购、下单、付款等功能的奶茶销售系统。通过本次课程设计,学生将锻炼发现问题、解决问题、综合编程、团队合作等方面的能力,掌握面向对象设计模式和软件体系结构风格的基础技术,提高软件系统结构设计能力和项目开发能力,注重学生团队意识培养。
本次课程设计的内容是基于 Spring、SpringMVC、MyBatis、BootStrap 等技术,实现一个具有登录注册、数据存储、菜单查看、加购、下单、付款等功能的奶茶销售系统。
- 系统功能:
登录注册:用户可以通过注册账号并登录系统,进行奶茶的购买和管理。
数据存储:系统需要将用户信息、奶茶信息、订单信息等数据存储到数据库中,以便进行管理和查询。
菜单查看:用户可以查看奶茶的菜单信息,包括奶茶的名称、价格、图片等。
加购:用户可以将奶茶加入购物车,方便进行购买。
下单:用户可以在购物车中选择需要购买的奶茶,并进行下单操作。
付款:用户可以选择在线支付或货到付款等方式进行付款。
- 非功能要求:
安全性:系统需要保证用户信息和交易数据的安全性,防止数据泄露和篡改。
易用性:系统需要具有良好的用户界面和操作流程,方便用户进行使用。
可扩展性:系统需要具有良好的可扩展性,方便进行功能的扩展和维护。
本次课程设计需要使用以下环境和工具:
开发工具:Eclipse/MyEclipse
开发语言:Java
数据库:MySQL
框架:Spring、SpringMVC、MyBatis、BootStrap
内容进度 |
|
|
10编码实现与测试阶段:系统编码 11、编码实现与测试阶段:界面优化、系统测试 12、编码实现与测试阶段:工程打包 13、验收和关闭阶段:文档整理 |
15、项目汇报准备:文档完善、PPT制作、录制系统介绍视频 16、项目总结与汇报 17、资料提交 |
用户可以注册新账号或登录系统。
用户可以浏览奶茶菜单,查看各种口味、规格和价格信息。
用户可以下单购买奶茶,选择支付方式。
用户可以查看订单状态和历史订单信息。
用户注册新账号或登录系统。
用户浏览奶茶菜单,选择喜欢的奶茶。
用户确认购物车中的商品,选择配送方式和支付方式,下单购买。
系统生成订单,用户可以查看订单状态和历史订单信息。
界面友好:系统界面设计简洁直观,操作流畅,用户易于上手。
扩展性:系统具有良好的扩展性,方便新增奶茶种类、调整价格等。
操作便捷性:系统操作简单直观,用户能够快速完成浏览、选择商品和下单的过程。
- 功能结构设计
Web 应用程序架构通常由客户端、服务器和数据库三个主要部分组成。客户端通过 HTTP 请求与服务器进行通信,服务器接收请求并调用相应的业务逻辑进行处理,然后将处理结果返回给客户端。数据库用于存储应用程序的数据。 在这个图片中,展示了 Web 层、应用层和数据库之间的关系。
- 数据结构关系图
product 表中的 classid 字段与 classification 表中的 classid 字段关联,shoppingcart 表中的 uid 字段与 user 表中的 uid 字段关联,order 表中的 uid 字段与 user 表中的 uid 字段关联,orderdetail 表中的 orderid 字段与 order 表中的 orderid 字段关联。
- 业务流程设计
- 用户发起请求:用户通过浏览器或其他客户端向应用程序发送请求。
- 控制器接收请求:控制器接收用户的请求,并根据请求的类型和参数决定要执行的操作。
- 控制器调用模型:控制器根据请求调用相应的模型方法,以获取或更新数据。
- 模型处理数据:模型执行相应的业务逻辑,对数据进行处理,并返回处理结果。
- 控制器调用视图:控制器根据模型返回的结果调用相应的视图,以将数据呈现给用户。
- 视图渲染页面:视图使用模板引擎或其他技术将数据渲染成 HTML 页面,并将其返回给控制器。
- 控制器返回响应:控制器将视图渲染的 HTML 页面返回给用户的浏览器或其他客户端,作为对用户请求的响应。
通过这种方式,MVC 架构将应用程序的不同部分分离,使得它们可以独立开发、测试和维护。这种分离提高了应用程序的可扩展性、可维护性和可重用性。
- 数据结构设计
- orderdetail数据表
包含订单详情的信息,如订单详情 ID、订单 ID、产品 ID、产品图片、产品名称、价格和购买数量。
odetailId | orderid | pid | pimg | pname | price | odetailnum |
47 | 40 | 100019 | 1572799782508_Product.jpg | 茶2 | 20 | 1 |
50 | 43 | 100020 | 1572803288864_Product.jpg | 奶茶2 | 20 | 1 |
51 | 44 | 100019 | 1572799782508_Product.jpg | 茶2 | 20 | 5 |
52 | 45 | 100003 | 1572801314894_Product.jpg | 奶茶4 | 20 | 2 |
58 | 50 | 100019 | 1572799782508_Product.jpg | 茶2 | 20 | 1 |
59 | 51 | 100020 | 1572803288864_Product.jpg | 奶茶2 | 20 | 1 |
60 | 52 | 100004 | 1572801470567_Product.jpg | 咖啡2 | 20 | 3 |
61 | 53 | 100018 | 1572798038864_Product.jpg | 茶1 | 20 | 1 |
62 | 54 | 100022 | 1572802975010_Product.jpg | 奶茶3 | 20 | 1 |
63 | 55 | 100020 | 1572803288864_Product.jpg | 奶茶2 | 20 | 1 |
orderdetail数据表
- user数据表
存储用户的信息,包括用户 ID、头像、用户名、密码、真实姓名、性别和生日。
uid | headimg | uname | password | myname | sex | birthday |
10010 | 1574151751020_Person.jpg | 漾泶 | 1234 | 孟东 | male | 1999年6月23日 |
10011 | 1572801861503_Person.jpg | Instinc | 2345 | 测试用户2 | female | 1997年5月10日 |
10013 | 1572799183823_Person.jpg | 欧冉 | 1234 | female | ||
10014 | 1572796657112_Person.jpg | 必上岸 | 1234 | |||
10015 | 1572801171277_Person.jpg | 正在狙击月亮 | 1234 | |||
10033 | 1572800869753_Person.jpg | NO.1 | 1234 | |||
10034 | 1572804782153_Person.jpg | 钢铁侠 | 1234 | |||
10035 | 1571405904746_Person.jpg | 北极星 | 1234 | 张三 | male | |
10037 | 1574135742960_Person.jpg | 长颈鹿 | 1234 |
user数据表
- shoppingcart 数据表:
记录购物车的相关信息,如购物车 ID、用户 ID、产品 ID、购买数量、总价和添加时间。
carid | uid | pid | numbers | priceall | cartbytime |
45 | 10010 | 100024 | 2 | 466 | 27/10/2019 18:00:15 |
47 | 10011 | 100024 | 2 | 466 | 31/10/2019 23:58:23 |
48 | 10010 | 100020 | 1 | 233 | 10/11/2019 14:20:23 |
49 | 10010 | 100003 | 3 | 11997 | 19/11/2019 18:54:34 |
- product 数据表:
包含产品的详细信息,如产品 ID、名称、图片、价格、库存、添加时间和分类 ID。
pid | pname | pimg | price | stock | bytime | classid |
100001 | 咖啡1 | 1572802837137_Product.jpg | 666 | 223 | 27/5/2024 17:38:04 | 1006 |
100002 | 果茶1 | 1572803212160_Product.jpg | 666 | 21 | 27/5/2024 17:38:04 | 1005 |
100003 | 奶茶4 | 1572801314894_Product.jpg | 666 | 394 | 27/5/2024 17:38:04 | 1001 |
100004 | 咖啡2 | 1572801470567_Product.jpg | 666 | 435 | 27/5/2024 17:38:04 | 1006 |
100005 | 冰淇淋1 | 1572806079781_Product.jpg | 666 | 546 | 27/5/2024 17:38:04 | 1004 |
100006 | 冰淇淋2 | 1572804070664_Product.jpg | 666 | 234 | 27/5/2024 17:38:04 | 1004 |
100011 | 冰淇淋3 | 1572803585667_Product.jpg | 666 | 4656 | 27/5/2024 17:38:04 | 1004 |
100013 | 果茶2 | 1572806191420_Product.jpg | 666 | 4656 | 27/5/2024 17:38:04 | 1005 |
100014 | 咖啡3 | 1572801007136_Product.jpg | 666 | 4656 | 27/5/2024 17:38:04 | 1006 |
100017 | 冰淇淋4 | 1572796713852_Product.jpg | 666 | 4656 | 27/5/2024 17:38:04 | 1004 |
100018 | 茶1 | 1572798038864_Product.jpg | 666 | 4656 | 27/5/2024 17:38:04 | 1002 |
product数据表
通过这些数据表的关联,可以实现奶茶销售系统的各种功能,如用户管理、订单管理、购物车管理和产品管理等。
- 首页
顶部导航栏: 包括系统的Logo、首页、产品导航、产品推荐、登录/注册等功能的链接,方便用户进行导航。
轮播图模块: 在首页展示多张奶茶产品的图片,通过自动轮播或手动切换的方式展示不同口味和品种的奶茶,吸引用户的眼球。
- 产品导航
有一个菜单,当用户在下拉菜单中选择某个选项时,通过特定的事件处理函数,页面会自动跳转到相应的位置
- 产品推荐
有一个菜单,当用户在下拉菜单中选择某个选项时,通过特定的事件处理函数,页面会自动跳转到相应的位置
- 服务与支持
在我们的奶茶销售系统中,设置了售后服务政策,给予用户及时的帮助和支持。
在这次课程设计中,我深刻体会到了将理论知识应用到实际项目中的重要性。通过参与奶茶销售系统的开发,我更加深入地理解了面向对象设计模式和软件体系结构风格,如如何合理地构建类和对象,以及不同架构风格在系统中的优势体现。掌握了 Spring、SpringMVC、MyBatis 和 BootStrap 等技术的实际运用,极大地提升了我的编程能力。同时,在解决各种问题的过程中,我的问题解决能力和逻辑思维也得到了锻炼。还学会了如何在团队中有效地沟通和协作,这对我的个人成长和职业发展都有着重要的意义。
作为团队的一员,我感受到了团队合作的力量。在分工协作的过程中,我们各自发挥优势,共同攻克难题。通过不断地交流和讨论,我们能够碰撞出更多的创意和想法,使得系统的功能更加完善和优化。团队成员之间的相互支持和鼓励,让我们能够保持积极的态度面对挑战。也学会了如何倾听他人的意见和建议,提高了团队协作的效率和质量。这种团队合作的经验对于我们今后在任何工作环境中都将是非常宝贵的财富。
部分关键代码
public class UserUtil {
/* 获取登录用户ID */
public static int getLoginUserId() {
User user = getLoginUser();
return user.getUid();
}
/* 获取登录用户名 */
public static String getLoginUserName() {
User user = getLoginUser();
return user.getUname();
}
/* 获取登录密码 */
public static String getLoginUserPswd() {
User user = getLoginUser();
return user.getPassword();
}
/* 获取登录用户对象 */
private static User getLoginUser() {
return (User) CoreUtil.getSession().getAttribute(Constants.LOGIN_USER);
}
}
@Controller
@RequestMapping("/login")
public class LoginController
@Resource
private ILoginSvc loginSvc;
/**
* produces="application/json;charset=UTF-8":防止ajax获取中文时出现乱码
* @return 将数据回传给ajax
*/
@ResponseBody
@RequestMapping(value = "/usertologin", method = RequestMethod.POST, produces = "application/json;charset=UTF-8")
public Object usertologin(
Integer uid,
String upswd,
HttpServletResponse response,
HttpSession session)
//创建 JSONObject 对象,它会把放入的数据以 json 的数据格式存储,对于集合类型的数据还要用到 JSONArray 数组
JSONObject object = new JSONObject();
int i = loginSvc.checkUid(uid);
if (i > 0) // 证明账号存在,进行密码验证
object.put("num_i", i);
object.put("SUCCESS_MESSAGE", "账号验证成功!");
int j = loginSvc.checkLogin(new User(uid, upswd));
if (j > 0) // 密码正确,进行相同账号的登录验证
object.put("num_j", j);
object.put("SUCCESS_MESSAGE2", "密码验证成功!");
User user_session = (User) CoreUtil.getSession().getAttribute(Constants.LOGIN_USER);
if (user_session!=null) { //证明用户已登录,不允许相同账号的登录
object.put("ERROR_MESSAGE", "该账号已登录!");
return object.toString();
} else //尚未有该用户登录,需要获取个人信息,保存用户名等,用以显示
/*String ipAddr = ToolsUtil.getIpAddr(request);
System.out.println("当前用户IP为:" + ipAddr);*/
User user = loginSvc.showUserInfo(uid);
/*保存信息,用于验证登录拦截器*/
session.setAttribute(Constants.LOGIN_USER, user);
session.setAttribute("myinfo", user);
String lasttime = ToolsUtil.getTime("yyyy-MM-dd HH:mm:ss", 0);
User user2 = loginSvc.showUserInfo(uid);
user2.setLasttime(lasttime);
int k = loginSvc.upUser(user2); // 此处可以对k进行判断,提示等
String logintime = ToolsUtil.getTime("yyyy年MM月dd日 HH:mm:ss", 0);
// 登录日志记录,此处为日志插入单独写了一个方法,调用即可
String descb = "您在【" + logintime + "】登录了本系统";
Log log = ToolsUtil.insertLog(uid, descb);
int m = loginSvc.insertUserLog(log);
else {
object.put("ERROR_MESSAGE", "密码错误,请重新输入!");
}
else {
object.put("ERROR_MESSAGE", "账号不存在!");
}
return object.toString(); //由于前端ajax在接收服务器数据时一般是字符串,因此要用“.toString()”方法转化
/**
* 用户注册
* */
@ResponseBody
@RequestMapping(value = "/register", produces = "application/json;charset=UTF-8")
public Map<String,Object> register(User user) {
Map<String, Object> map=new HashMap<String, Object>();
User ex_user = loginSvc.selUserByUname(user.getUname());
if(ex_user==null){
user.setBytime(ToolsUtil.getTime("yyyy-MM-dd HH:mm:ss", 0));
int i = loginSvc.addUser(user);
User new_user = loginSvc.selUserByUname(user.getUname());
map.put("add_res", i);
map.put("add_userres", new_user);
}else {
map.put("add_res", 0);
}
return map;
}
/**
* 退出
*/
@ResponseBody
@RequestMapping(value = "/invali", produces = "application/json;charset=UTF-8")
public String invali(HttpSession session)
session.invalidate();
JSONObject object=new JSONObject();
object.put("test_date", " ");
return object.toString();
/*String str = ToolsUtil.getContextPath() + "/goindex.jsp";
response.sendRedirect(str);*/
@Service
public class LoginSvcIMPL implements ILoginSvc
@Resource
private IUserDao userDao;
@Override
public int checkUid(Integer uid) {
return userDao.checkUid(uid);
}
@Override
public int checkLogin(User user) {
return userDao.checkLogin(user);
}
@Override
public User showUserInfo(Integer uid) {
return userDao.showUserInfo(uid);
}
@Override
public int upUser(User user) {
return userDao.upUser(user);
}
@Override
public int insertUserLog(Log log) {
return userDao.insertUserLog(log);
}
@Override
public List<User> selAllUser() {
return userDao.selAllUser();
}
@Override
public int addUser(User user) {
return userDao.addUser(user);
}
@Override
public User selUserByUname(String uname)
return userDao.selUserByUname(uname);
@Override
public int delUserById(Integer uid) {
return userDao.delUserById(uid);
}