基于SSM框架的《超市订单管理系统》Web项目开发(第二天)完成登录模块和用户退出模块

《超市订单管理系统》(第二天) 基于SSM框架的Web项目开发

​ 昨天我们实现了登录功能,但是用的是模拟数据。今天我们要链接数据库整合Spirng+Mybatis,读取数据库中的真实数据,用来跟我们输入的userCode和userPassword进行对比,来判断用户名和密码是否正确。还需要进行一些其他的微调


今日目标:链接数据库完成以下模块设计

  • 完成登录模块(登录页面设计+登录功能)
  • 完成用户退出模块

项目的开发流程(一般来说)

项目的开发流程可以根据具体需求和项目规模有所不同,但通常包括以下主要步骤:

  1. 需求分析和规划
    • 理解项目的需求和目标。
    • 制定项目计划和时间表。
    • 确定项目的范围和功能。
  2. 数据库设计
    • 根据项目需求设计数据库结构,包括表和关系。
    • 创建数据库模式和表结构。
    • 确保数据库的正常运行和性能。
  3. 后端开发
    • 开发后端应用程序,包括业务逻辑和数据访问层。
    • 集成数据库,实现数据的增删改查操作。
    • 编写 API 和服务端逻辑。
  4. 前端开发
    • 开发前端界面和用户体验。
    • 使用 HTML、CSS、JavaScript 等前端技术。
    • 与后端进行通信,调用后端提供的 API。
  5. 集成和测试
    • 集成前后端组件,确保它们协同工作。
    • 进行单元测试和集成测试,检查功能和性能。
    • 解决和修复问题。
  6. 部署和上线
    • 部署应用程序到生产环境。
    • 配置服务器和数据库。
    • 监控应用程序性能,并处理生产问题。
  7. 维护和优化
    • 定期监控和维护应用程序,确保其稳定性。
    • 进行性能优化,提高应用程序效率。
    • 根据用户反馈和需求进行功能扩展和更新。
  8. 文档和培训
    • 编写项目文档,包括用户手册和开发文档。
    • 培训用户和开发团队,确保他们了解项目和工具。

​ 关于数据库的创建,通常在数据库设计阶段会创建数据库模式和表结构但在实际开发中,有时也可以在后期根据需求进行数据库的调整和扩展

这是因为,项目开发是一个迭代和持续改进的过程,需要我们不断地与团队成员者进行沟通和协作。

一般来说都是要提前设计好数据库表结构等,然后再去进行一个前后端的开发。在自己进行一个全新项目开发的时候呢,基本上是得按照上面的流程来。


一、开发前准备

①数据库准备:

运行Navicat for Mysql等数据库管理工具,导入我们项目资源中的数据库文件supermarket.sql

​ ps:Navicat 是一款强大的数据库管理工具,用于管理和维护多种数据库系统,包括 MySQL、MariaDB、SQLite、SQL Server、Oracle 和 PostgreSQL 等。它为数据库开发人员和管理员提供了丰富的功能和工具,使他们能够更轻松地管理和操作数据库。

创建出supermarket数据库。

②查看用户表中的所有字段,我们要确保我们的类中的属性和表中的字段名一致,一 一对应映射,这样涉及到前后端传值的时候就比较清晰,不会太迷糊,降低出错的风险。

在这里插入图片描述

二、开始完善登录功能

自动生成pojo类这个部分,我也是前面的文章有发布过的,可以访问查看一下

如何使用IDEA链接数据库并自动生成POJO类?_Stevedash的博客-CSDN博客如何实现

①确保正确的项目结构和资源文件的齐全

在这里插入图片描述

②使用idea自带链接数据库生成数据库表的pojo类与pojo包下,然后进行检查。

在这里插入图片描述

在这里插入图片描述

③dao层(dao包)下创建Mybatis的映射文件和接口,我们这里是对user表进行的操作,那么就是UserMapper接口和UserMapper.xml(也就是Mybatis映射文件)

看到这里可能会有疑惑

为什么dao层中的UserMapper接口要和UserMapper.xml的命名一样呢?

​ 其实我们前面的文章也有讲到的,在MyBatis这样的持久化框架中,UserMapper接口和UserMapper.xml的命名之间通常需要保持一致,这是为了确保MyBatis能够正确地将接口与XML配置文件关联起来并执行相应的SQL操作

UserMapper接口代码如下:

package com.steveDash.dao;import com.steveDash.pojo.User;public interface UserMapper {public User getUserByUserCode(String userCode);
}

UserMapper.xml代码如下:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd"><mapper namespace="com.steveDash.dao.UserMapper"><!--根据账户名userCode查询user表,返回一个User类型对象记录--><select id="getUserByUserCode" parameterType="String" resultType="User">select * from user where userCode=#{userCode}</select>
</mapper>

这里的返回类型本来是要写全类限名,但是我们在Mybatis-config配置文件中编写了别名,因此这里我们可以直接写User

在这里插入图片描述

在这里插入图片描述

按照我们前面讲的,这里应该还需要去mybatis-config里面注册好我们的mapper映射文件的地址吧?

但是呢,这里我们选择在spring-config中去写入配置Dao层,这样的话我们就不用一个一个的映射文件都要注册到配置文件中,这段代码它会自动扫描该包下的所有映射文件并且注册好

在这里插入图片描述


④根据分层思想,在Service层下,编写UserService接口。

UserService接口中添加查询用户的方法getUserByUserCode()

package com.steveDash.service;import com.steveDash.pojo.User;public interface UserService {public User getUserByUserCode(String userCode);
}

(使用给接口生成实现类的快捷键ALT+ENTER)编写业务实现类UserServiceImpl

package com.steveDash.service;import com.steveDash.dao.UserMapper;
import com.steveDash.pojo.User;
import org.springframework.stereotype.Service;import javax.annotation.Resource;@Service("userServiceImpl")
public class UserServiceImpl implements UserService {@Resourceprivate UserMapper userMapper;public UserMapper getUserMapper() {return userMapper;}public void setUserMapper(UserMapper userMapper) {this.userMapper = userMapper;}@Overridepublic User getUserByUserCode(String userCode) {try{return userMapper.getUserByUserCode(userCode);}catch (RuntimeException e){e.printStackTrace();throw e;}}
}

代码说明:在这里我们将dao中的接口UserMapper的实例注入到UserServiceImpl,并调用它的getUserByUserCode方法查询数据

所以这里一定要添加getter,setter方法!!! 因为依赖注入Spring框架通过setter方法来注入userMapper的实例

因为我们是使用注解的方式,所以我们需要去Spring-config.xml中查看一下,是否开启了注解的代码

在这里插入图片描述


⑤打开controller包下的,UserController,进行登录方法doLogin()的修改

在这里插入图片描述

这种方式就是我们前几天学到的,依赖注入和IOC控制反转,由IOC容器创建对象,通过getBean的方式来获取实例对象。


这里请思考一下:下面这俩种写法效果都是一样的,那么为什么我们要选择第一种呢?

UserService userService=(UserServiceImpl)context.getBean("userServiceImpl");

UserServiceImpl userService=(UserServiceImpl)context.getBean("userServiceImpl");

答案如下:

两种方式的效果是一样的,但第一种方式更符合依赖注入和面向接口编程的原则,因为它将userService声明为接口类型,而不是具体的实现类型。这样做有助于降低耦合度,使代码更具灵活性。如果以后更改了UserService的实现类,第一种方式无需修改,而第二种方式则需要修改。因此,第一种方式通常更好一些。


⑥运行一下tomcat服务

测试1首先进行正确的账号密码输入测试:

在这里插入图片描述

可以看到正常运行,并且没有错误。

还需要进行其他情况的测试2,比如用户名不存在的情况admin1,预期输出结果:用户名错误

在这里插入图片描述

与预期结果一致。

那么在进行登录测试3:账号正确,密码错误的情况。预期结果:用户名或者密码错误

在这里插入图片描述

与预期结果一致。


⑦代码反思优化,采用依赖注入的方式

上面的代码还有优化的空间,因为

在这里插入图片描述

蓝色标注的这一段,我们只是为了获取userServiceImpl的Bean,所以我们可以使用依赖注入的方式,代码如下:

package com.steveDash.controller;import com.steveDash.pojo.User;
import com.steveDash.service.UserService;
import com.steveDash.service.UserServiceImpl;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;import javax.annotation.Resource;
import javax.servlet.http.HttpSession;@Controller
public class UserController {@Resourceprivate UserService userService;@RequestMapping(value="/login")public String showLoginPage(){System.out.println("进入登录页面");return "login";}@RequestMapping(value="/dologin")public String doLogin(@RequestParam("userCode") String userCode, @RequestParam("userPassword") String userPassword, Model model, HttpSession session){//读取用户和密码System.out.println("帐号和密码是"+userCode+"-"+userPassword);User user=userService.getUserByUserCode(userCode);if(user!=null){if(userPassword.equals(user.getUserPassword())){session.setAttribute("userCode",userCode);//添加session值return "welcome"; //密码正确就去welcome.jsp}else{//登录失败就回到login.jspmodel.addAttribute("error", "用户名或密码不正确");return "login";}}else{//登录失败就返回login.jspmodel.addAttribute("error", "用户名不正确");return "login";}}}

⑧重新运行服务,看看需求是否满足,登录功能是否正常?

在这里插入图片描述

在这里插入图片描述


三、完成退出模块

​ 退出登录模块的设计,其实就是清除httpSession中的Session,然后进行判断若是Session中没有用户,那就判断回到登录页面,若有就跳转到主功能页面,这样子就可以完成一个退出的功能。

所以在完成退出模块设计前,要对我们刚刚实现的登录功能进行一个优化

①我们Session中只存了用户的账号名:userCode,可是我们其他页面或许需要user用户的其他参数,因此我们修改Session中存储的值,修改为存储user用户

在UserController.java找到doLogin并且进行修改

@RequestMapping(value="/dologin")
public String doLogin(@RequestParam("userCode") String userCode, @RequestParam("userPassword") String userPassword, Model model, HttpSession session){//读取用户和密码System.out.println("帐号和密码是"+userCode+"-"+userPassword);User user=userService.getUserByUserCode(userCode);if(user!=null){if(userPassword.equals(user.getUserPassword())){session.setAttribute("user",user);//添加session值,修改成存入user对象return "redirect:/main"; //密码正确就去welcome.jsp(main是welcome页面的映射)}else{//登录失败就回到login.jspmodel.addAttribute("error", "用户名或密码不正确");return "login";}
}else{//登录失败就返回login.jspmodel.addAttribute("error", "用户名不正确");return "login";}
}

所以我们还需要添加一个去到welcome页面的映射,因此还是在UserController中进行如下操作

新增/main映射到welcome.jsp页面

@RequestMapping(value="/main")
public String welcome(HttpSession session)  {if(session.getAttribute("user") == null){ //如果用户没有登录就直接来到main.html就回到loginreturn "redirect:/syserror";}elsereturn "welcome";
}@RequestMapping("/syserror")//出错页面public String sysError(){return "syserror";}

​ 这里为什么不是直接使用welcome作为页面的映射呢?这是基于一个网络安全的考虑,因为直接让映射名和文件名一致的话,很容易就被黑客找到关键资源文件,进行渗透攻击修改后台数据,因此我们都是用关键词代表这个映射的操作。

​ 我们这里还加入了一个判断,若是没有登陆就想直接访问main界面,就会自动重定向到syserror.jsp报错页面

<%--Created by IntelliJ IDEA.User: AdministratorDate: 2023/9/17Time: 11:39To change this template use File | Settings | File Templates.
--%>
<%@ page language="java" contentType="text/html; charset=UTF-8"pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><title>Insert title here</title>
</head>
<body>
<h1>请登录后再访问该页面!</h1>
<a href="${pageContext.request.contextPath }/login">返回</a>
</body>
</html>

在这里插入图片描述

**在这里插入图片描述
**

上面这样子就完善了登录页面的操作,并且设置了主页welcome的main映射,然后还编写了未登录就访问主页的错误提示。


②编写退出操作

代码如下:

@RequestMapping(value = "/logout")
public String logout(HttpSession session){session.removeAttribute("user");//清除掉Session 中的user值return "redirect:/login";//返回login.jsp
}

使用removeAttribute()方法清除掉session中存储的user对象,然后重定向到登录界面即可完成退出操作。

重新运行服务看看效果

在这里插入图片描述

在这里插入图片描述

可以看到了退回了登录界面,退出功能也完成了。


总结

​ 今天是综合项目超市订单管理系统开发的第二天,我们完善了登录的功能模块和退出的功能模块。项目现在已经整合了SpringMVC和Spring、以及Mybatis,算是SSM的综合项目了,接下里的就是把之前学习过的知识,应用在这个项目中还讲解了一下项目的开发流程,希望通过今天的学习,希望各位读者可以对整体的项目开发流程有个大致的了解,为框架开发打下坚实基础。

​ 想要跟着学习的可以去我的资源里面找对应的文件下载,我的md文件也会发上去,项目文件会上传可以自己跟着学习一下。(ps:前俩天有事,所以今天补上)

作者:Stevedash

发表于:2023年9月17日 13点23分

注:本文内容基于个人学习理解,如有错误或疏漏,欢迎指正。感谢阅读!如果觉得有帮助,请点赞和分享。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/134540.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

制作立体图像实用软件:3DMasterKit 10.7 Crack

3DMasterKit 软件专为创建具有逼真 3D 和运动效果的光栅图片而设计&#xff1a;翻转、动画、变形和缩放。 打印机、广告工作室、摄影工作室和摄影师将发现 3DMasterKit 是一种有用且经济高效的解决方案&#xff0c;可将其业务扩展到新的维度&#xff0c;提高生成的 3D 图像和光…

Git - Git Merge VS Git Rebase

文章目录 概述Flow View小结 概述 Git merge和Git rebase是两种不同的版本控制工作流程&#xff0c;它们用于将一个分支的更改合并到另一个分支。它们有不同的工作原理和应用场景&#xff0c;下面是它们的主要区别&#xff1a; 合并的方式&#xff1a; Git Merge&#xff1a;合…

用c++实现五子棋小游戏

五子棋是一款经典小游戏&#xff0c;今天我们就用c实现简单的五子棋小游戏 目录 用到的算法&#xff1a; 思路分析 定义变量 开始写代码 完整代码 结果图&#xff1a; 用到的算法&#xff1a; 合法移动的判断&#xff1a;isValidMove 函数通过检查指定位置是否在棋盘范…

基于matlab实现的 BPSK调制AWGN通道未编码数据误码率程序

完整程序&#xff1a; clear; close all; clc; c0; rate1; %Code rate N10000000; %Number of bits for EbNoc0:1:10 %Ratio of bit energy to no…

Stream流处理快速上手最佳实践 | 京东物流技术团队

一 引言 JAVA1.8得益于Lambda所带来的函数式编程&#xff0c;引入了一个全新的Stream流概念Stream流式思想类似于工厂车间的“生产流水线”&#xff0c;Stream流不是一种数据结构&#xff0c;不保存数据&#xff0c;而是对数据进行加工处理。Stream可以看作是流水线上的一个工…

【基础篇】ClickHouse 表引擎详解

文章目录 0. 引言1. 什么是表引擎2. 不同表引擎使用场景1. MergeTree:2. Log:3. Memory:4. Distributed:5. Kafka:6. MaterializedView:7. File和URL: 3. MergeTree 家族3.1. MergeTree:3.2. ReplacingMergeTree:3.3. SummingMergeTree:3.4. AggregatingMergeTree:3.5. Collaps…

【AI】机器学习——感知机

文章目录 4.1 感知机基本概念4.2 策略4.2.1 数据集的线性可分性4.2.2 学习策略目标损失函数的构造关于距离的解释 4.3 算法4.3.1 原始形式损失函数的梯度下降法 4.3.2 PLA例题4.3.3 算法收敛性 4.4 PLA对偶形式4.4.1 原始PLA分析4.4.2 PLA对偶形式4.4.3 优点 4.1 感知机基本概念…

office mac苹果办公软件安装包安装教程详解

软件下载 软件&#xff1a;mac office版本&#xff1a;2021语言&#xff1a;简体中文大小&#xff1a;4.27G安装环境&#xff1a;mac硬件要求&#xff1a;CPU2.0GHz 内存4G(或更高&#xff09;下载通道 百度网盘 https://pan.baidu.com/s/1WGSB-icELUxweFkI8iIbzA 首先&#…

什么是JavaScript的事件驱动编程(event-driven programming)?

聚沙成塔每天进步一点点 ⭐ 专栏简介⭐ 事件&#xff08;Event&#xff09;⭐ 事件监听器&#xff08;Event Listener&#xff09;⭐ 回调函数&#xff08;Callback Function&#xff09;⭐ 非阻塞和异步⭐ 事件循环&#xff08;Event Loop&#xff09;⭐ 触发事件&#xff08;…

知识竞赛活动舞台搭建需要多少钱

知识竞赛活动舞台搭建的费用会根据不同的竞赛活动规模和要求而有所不同。对于小型的知识竞赛活动&#xff0c;如学校内部组织的知识竞赛或社区的知识竞赛活动&#xff0c;舞台搭建的费用往往相对较低。在这种情况下&#xff0c;可能只需要一些简单的装饰和道具&#xff0c;例如…

【C++进阶】:哈希(一)

哈希 一.unordered_map二.底层结构1.哈希概念2.解决哈希冲突1.闭散列2.开散列 在C98中&#xff0c;STL提供了底层为红黑树结构的一系列关联式容器&#xff0c;在查询时效率可达到 l o g 2 N log_2N log2​N&#xff0c;即最差情况下需要比较红黑树的高度次&#xff0c;当树中的…

Linux:基础开发工具之yum,vim,gcc的使用

文章目录 yumvimgcc 本篇主要总结的是Linux下开发工具 yumvimgcc/g yum 什么是yum&#xff1f; 不管是在手机移动端还是pc端&#xff0c;不管是什么操作系统&#xff0c;当用户想要下载一些内容或者工具的时候&#xff0c;都需要到一个特定的位置进行下载&#xff0c;例如在…

初识Java 9-2 内部类

目录 为什么需要内部类 闭包和回调 内部类和控制框架 继承内部类 内部类的重写&#xff08;并不能&#xff09; 局部内部类 内部类标识符 本笔记参考自&#xff1a; 《On Java 中文版》 为什么需要内部类 在一些情况下&#xff0c;我们无法享受接口带来的便利&#xff0…

c刷题(四)

目录 获得月份天数 判断字母 字母大小写转换 网购 下列程序段的输出结果 字符逆序 自幂数 a的前n项之和 最小公倍数 倒置字符串 获得月份天数 获得月份天数_牛客题霸_牛客网 这道题可以用switch case语句解&#xff0c;不过这道题更简单的方法是数组&#xff0c;关…

AE-如何制作湖面水波纹波动的效果

目录 1.新建水面合成 2.新建纯色层命名为“分形杂色”&#xff0c;并添加“分形杂色”效果&#xff0c;设置相关参数 3.添加3D效果&#xff0c;并添加摄像机和空对象 4.新建中秋节合成&#xff0c;导入背景图&#xff0c;新建调整图层&#xff0c;并在调整图层上增加“焦散…

【C++】动态内存管理(79分钟写的文章哪里看不懂了,快来学)

动态内存管理目录&#xff1a; 一、C/C内存分布 在学习了C/C内存区域的划分后&#xff0c;我们来做几道题巩固一下&#xff1a; 1. 选择题&#xff1a;选项 : A.栈 B.堆 C.数据段(静态区) D.代码段(常量区)globalVar在哪里&#xff1f;____ staticGlobalVar在哪里&#x…

一个Binder的前生今世 (一):Service的创建

一个Binder的前生今世 (一):Service的创建 一个Binder的前生今世Binder的历史 (字面意义的前生今世)Binder的生命周期(抽象意义的前生今世)Binder 应用及系统层关系图Binder应用层的架构设计Binder应用层实现Binder的创建服务端Binder的创建服务端Binder的传递Binder在客…

实现按钮悬停动画

知识点与技巧 伪元素 使用伪元素来作为按钮悬停效果动画展示的元素 z-index 的使用技巧 使用z-index属性来控制按钮和伪元素的层次关系 transform、transition 复习 使用transform、transition两个属性来实现动画的展示 按钮边框动画 切换效果 核心代码 .btn.btn-border-…

2023面试知识点一

1、新生代和老年代的比例 默认的&#xff0c;新生代 ( Young ) 与老年代 ( Old ) 的比例的值为 1:2 ( 该值可以通过参数 –XX:NewRatio 来指定 )&#xff0c;即&#xff1a;新生代 ( Young ) 1/3 的堆空间大小。老年代 ( Old ) 2/3 的堆空间大小。其中&#xff0c;新生代 ( …

Unity减少发布打包文件的体积——获取精灵图片的信息限制它的大小

一、起因 一个工程&#xff0c;打包成webGL且压缩成zip文件后&#xff0c;接近400M&#xff0c;后来把大的精灵图片设置最大尺寸&#xff0c;降低大小后&#xff0c;再次发布&#xff0c;zip文件缩减到250M 二、如何一键获得工程里面的精灵图片信息 三、获取精灵图片信息 1、…