项目实战系列: 家居购项目 第一部分

2024-09-06 14:12

本文主要是介绍项目实战系列: 家居购项目 第一部分,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

家居购项目

  • 🐀Java后端经典三层架构
  • 🐇MVC模型
  • 🐇开发环境搭建
  • 🐇会员注册
    • 🍉前端JS校验
    • 🍉后端实现
  • 🐇会员登陆

在这里插入图片描述

🐀Java后端经典三层架构

在这里插入图片描述

在这里插入图片描述

分层对应包说明
web层com.zzw.furns.web/servlet/controller/handler接受浏览器发送数据; 调用相关的service;根据执行结果,返回页面数据
service层com.zzw.furns.serviceService接口包
com.zzw.furns.service.implService接口实现类
dao持久层com.zzw.furns.daoDao接口包
com.zzw.furns.dao.implDao接口实现类
实体bean对象com.zzw.furns.pojo/entity/domain/beanJavaBean类
工具类com.zzw.furns.utils工具类
测试包com.zzw.furns.test完成对dao/service测试

🐇MVC模型

MVC全称: Model模型, View试图, Controller控制器
MVC最早出现在JavaEE三层中的Web层, 它可以有效地指导WEB层代码如何有效地分离, 单独工作

  • View试图: 只负责数据和界面的显示, 不接受任何与显示数据无关的代码, 便于程序员和美工的分工与合作(Vue/Jsp/Thymeleaf/Html)
  • Controller控制器: 只负责接收请求, 调用业务层的代码处理请求, 然后派发给页面, 是一个"调度者"的角色
  • Model模型: 将与业务逻辑相关的数据封装为具体的JavaBean类, 其中不掺杂任何与数据处理相关的代码(JavaBean/Domain/Pojo)

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

解读

  1. model 最早期就是javabean, 就是早期的jsp+servlet+javabean
  2. 后面业务复杂度越来越高, model逐渐分层化/组件化(service+dao)
  3. 后面又出现了持久化技术(service+dao+持久化技术(hibernate / mybatis / mybatis-plus))
  4. MVC依然是原来的mvc, 只是变得更加强大

🐇开发环境搭建

参考 IDEA 2022.3开发JavaWeb工程

1.新建Java项目 jiaju_mall

2.导入jar包

3.项目的结构
在这里插入图片描述
在这里插入图片描述

4.下载资源, 拷贝到web路径下
在这里插入图片描述

html转成jsp, 并把页面调整也以下目录
views/member/login.jsp
views/member/register_ok.jsp
views/member/register_fail.jsp
views/member/login_ok.jsp
web/index.jsp

1)html页面转为jsp页面要做的处理

在这里插入图片描述

将页面内应用的.html页面改成.jsp

将页面内的相对路径重新修改

在这里插入图片描述
如果有需要, 在页面顶部引入c标签
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

如果是html页面, base标签不能使用el表达式, 要这样写:
在这里插入图片描述

5.Rebuild project, 让项目识别到这些资源, 然后再启动Tomcat

在这里插入图片描述

6.对于复杂的前端页面, 要学会打开当前页面的结构, 提高工作效率

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

🐇会员注册

🍉前端JS校验

1.验证用户名:必须字母,数字下划线组成,并且长度为 6 到 10 位 => 正则表达式
2.验证密码:必须由字母,数字下划线组成,并且长度为 6 到 10 位
3.邮箱格式验证:常规验证即可
4.验证码:后面实现

代码实现
1.修改web/views/member/login.html, 增加(script在src属性引文件)

<script type="text/javascript" src="../../script/jquery-3.6.0.min.js"></script>
<script type="text/javascript">$(function () {//页面加载完毕后执行 function$("#sub-btn").click(function () {//采用过关斩将法//正则表达式验证用户名var usernameValue = $("#username").val();var usernamePattern = /^\w{6,10}$/;if (!usernamePattern.test(usernameValue)) {$("span[class='errorMsg']").text("用户名格式不对, 需要6-10个字符(大小写字母,数字,下划线)");return false;}//验证密码var passwordValue = $("#password").val();var passwordPattern = /^\w{6,10}$/;if (!passwordPattern.test(passwordValue)) {$("span.errorMsg").text("密码格式不对, 需要6-10个字符(大小写字母,数字,下划线)");return false;}//两次密码要相同var rePwdValue = $("#repwd").val();if (passwordValue != rePwdValue) {$("span.errorMsg").text("两次密码不相同");return false;}//这里仍然采用过关斩将法//验证邮件var emailVal = $("#email").val();//在java中, 正则表达式的转义是\\; 在js中, 正则表达式转义是\var emailPattern = /^[\w-]+@([a-zA-Z]+\.)+[a-zA-Z]+$/;if (!emailPattern.test(emailVal)) {$("span.errorMsg").text("电子邮件的格式不正确, 请重新输入");return false;}//这里暂时不提交=>显示验证通过$("span.errorMsg").text("验证通过");return false;});})
</script>

2.测试

在这里插入图片描述

🍉后端实现

思路分析

  1. 会员注册信息, 验证通过后
  2. 提交给服务器, 如果用户名在数据库中已经存在, 后端给出提示信息, 并返回重新注册
  3. 如果用户名没有在数据库中, 完成注册, 并返回注册成功的页面

程序框架图
在这里插入图片描述

代码实现
1.创建数据库和表

-- 创建家居网购需要的数据库和表
-- 删除数据库
DROP DATABASE IF EXISTS home_furnishing;-- 删除表
DROP TABLE member;-- 创建数据库
CREATE DATABASE home_furnishing;-- 切换
USE home_furnishing;-- 创建会员表
CREATE TABLE member (id INT PRIMARY KEY AUTO_INCREMENT,username VARCHAR(32) NOT NULL DEFAULT '' UNIQUE,`password` VARCHAR(32) NOT NULL,email VARCHAR(64)
)CHARSET utf8 ENGINE INNODB;-- 插入数据
INSERT INTO member VALUES(NULL, 'admin', MD5('admin'), '978964140@qq.com');
INSERT INTO member VALUES(NULL, 'zhaozhiwei', MD5('zhaozhiwei'), '978964140@qq.com');
INSERT INTO member(id, username, `password`, email) VALUES(NULL, 'tom', MD5('tom'), 'tom@sohu.com');-- 查询
SELECT * FROM member;
SELECT id, username, `password`, email FROM member WHERE username = 'admine'
SELECT id, username, `password`, email FROM member WHERE username = 'admin123' AND `password` = MD5('123456');UPDATE member SET `password`=MD5('admin') WHERE username='admin';

2.创建实体类src/com/zzw/furns/entity/Member.java 满汉楼项目参考
无参构造器和set方法. get方法

public class Member {private Integer id;private String username;private String password;private String email;//无参构造器, 底层反射用public Member() {}//提供了有参构造器,必须提供无参构造器public Member(Integer id, String username, String password, String email) {this.id = id;this.username = username;this.password = password;this.email = email;}
}

3.从满汉楼项目引入BasicDAO.java, JdbcUtilsByDruid.java, Druid.properties

4.修改Druid配置文件要连接的数据库名, 确保用户名密码正确. url后面是做批处理用的
在这里插入图片描述

5.修改JdbcUtilsByDruid的路径

在这里插入图片描述

6.配置快捷键

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

7.测试, 新建src/com/zzw/furns/test/JdbcUtilsByDruidTest.java

@SuppressWarnings({"all"})
public class JdbcUtilsByDruidTest {@Testpublic void getConnection() {Connection connection = JdbcUtilsByDruid.getConnection();System.out.println(connection);JdbcUtilsByDruid.close(null, null, connection);}
}

8.新建src/com/zzw/furns/dao/MemberDao.java

public interface MemberDAO {//小伙伴需要自己分析, 需要哪些方法//提供一个通过用户名返回对应的Memberpublic Member queryMemberByUsername(String username);//提供一个 保存Member对象到数据库Member表 的方法public int saveMember(Member member);
}

9.新建src/com/zzw/furns/dao/impl/MemberDaoImpl.java

public class MemberDAOImpl extends BasicDAO<Member> implements MemberDAO {/*** 通过用户名返回对应的Member* @param username 用户名* @return 对应的Member, 如果没有该Member返回null*/@Overridepublic Member queryMemberByUsername(String username) {//现在sqlyog测试, 然后再拿到程序中, 这样可以提高我们的开发效率, 减少不必要的bugString sql = "SELECT id, username, `password`, email FROM member WHERE username = ?";Member member = querySingle(sql, Member.class, username);return member;}/*** 保存一个会员* @param member 传入一个Member对象* @return 如果返回-1, 就是失败; 返回其它的数字, 就是受影响的行数*/@Overridepublic int saveMember(Member member) {//连同单引号一并换成 ? , 它会自动加上单引号String sql = "INSERT INTO member(id, username, `password`, email) " +"VALUES(NULL, ?, MD5(?), ?)";int updateRows = update(sql, member.getUsername(), member.getPassword(), member.getEmail());return updateRows;}
}

10.测试, 新建src/com/zzw/furns/test/MemberDAOTest.java

public class MemberDAOTest {private MemberDAO memberDAO = new MemberDAOImpl();@Testpublic void queryMemberByUsernameTest() {if (memberDAO.queryMemberByUsername("tome") == null) {System.out.println("该用户名不存在");} else {System.out.println("该用户名存在");}}@Testpublic void saveMember() {Member member =new Member(null, "king", "king", "king@sohu.com");if (memberDAO.saveMember(member) == 1) {System.out.println("添加成功");} else {System.out.println("添加失败");}}
}

11.新建src/com/zzw/furns/service/MemberService.java

public interface MemberService {//注册用户public boolean registerMember(Member member);//判断用户名是否存在public boolean isExistsByUsername(String username);
}

12.新建src/com/zzw/furns/service/MemberServiceImpl.java

public class MemberServiceImpl implements MemberService {//定义MemberDAO属性private MemberDAO memberDAO = new MemberDAOImpl();/*** 判断用户名是否存在** @param username 用户名* @return 如果存在返回true, 否则返回false*/@Overridepublic boolean isExistsByUsername(String username) {//小技巧: 如果看某个方法:// (1)ctrl+b 定位到memberDAO的编译类型中的方法// (2)如果使用ctrl+alt+b 会定位到实现类的方法//如果有多个类实现了该方法, 会让你选择return memberDAO.queryMemberByUsername(username) == null ? false : true;}@Overridepublic boolean registerMember(Member member) {return memberDAO.saveMember(member) == 1 ? true : false;}
}

13.测试, 新建src/com/zzw/furns/test/MemberServiceTest.java

public class MemberServiceTest {private MemberService memberService = new MemberServiceImpl();@Testpublic void isExistsByUsernameTest() {if (memberService.isExistsByUsername("king")) {System.out.println("用户名存在");} else {System.out.println("用户名不存在");}}@Testpublic void registerMember() {//构建一个用来测试的Member对象Member member = new Member(null, "tom", "tom", "tom@sohu.com");if (memberService.registerMember(member)) {System.out.println("注册用户成功");} else {System.out.println("注册用户失败");}}
}

14.接通web层, 新建src/com/zzw/furns/web/RegisterServlet.java

public class RegisterServlet extends HttpServlet {private MemberService memberService = new MemberServiceImpl();@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {doPost(request, response);}@Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {String username = request.getParameter("username");String password = request.getParameter("password");String email = request.getParameter("email");Member member = new Member(null, username, password, email);if (!memberService.isExistsByUsername(member)) {//用户名可用if (memberService.registerMember(member)) {System.out.println("注册成功");request.getRequestDispatcher("/views/member/register_ok.jsp").forward(request, response);} else {System.out.println("注册失败");request.getRequestDispatcher("/views/member/register_fail.jsp").forward(request, response);}} else {//用户名不可用request.setAttribute("msg", "用户名" + username + "不可用");request.setAttribute("username", username);//回显用户名request.setAttribute("active", "register_tab");request.getRequestDispatcher("/views/member/login.jsp").forward(request, response);}}
}
<servlet><servlet-name>RegisterServlet</servlet-name><servlet-class>com.zzw.furns.web.RegisterServlet</servlet-class>
</servlet>
<servlet-mapping><servlet-name>RegisterServlet</servlet-name><url-pattern>/register</url-pattern>
</servlet-mapping>

15.前端(错误信息回显), 修改web/views/member/login.jsp

2)cart.jsp, checkout.jsp, order.jsp,order_detail.jsp均可跳转

<!-- Header Logo Start -->
<div class="col-auto align-self-center"><div class="header-logo"><a href="index.jsp"><img src="assets/images/logo/logo.png" alt="Site Logo"/></a></div>
</div>
<!-- Header Logo End --><!-- Header Action Start -->
<div class="col align-self-center"><div class="header-actions"><!-- Single Wedge Start -->欢迎: ${sessionScope.member.username}&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<div class="header-bottom-set dropdown"><a href="orderServlet?action=listOrderByMemberId">订单管理</a></div><div class="header-bottom-set dropdown"><a href="memberServlet?action=logout">安全退出</a></div><!-- Single Wedge End --></div>
</div>
<!-- Header Action End -->

3)修改web/views/member/login.jsp注册表单

<!--会员注册-->
<span class="errorMsg"style="float: right; font-weight: bold; color: lightgray; font-size: 20pt; margin-left: 10px;">${msg}</span>
<form action="registerServlet" method="post">
</form>
<a id="register_tab" data-bs-toggle="tab" href="#lg2"><h4>会员注册</h4>
</a>

4)修改loign.jsp - 注册失败回显信息时, 停留在注册的tab内

$(function () {//模拟一个点击事件, 选中注册//决定是显示登陆还是显示注册tab//如果注册失败, 显示注册tab, 而不能是默认的登录tabif (${requestScope.active == "register_tab"}) {$("#register_tab")[0].click();} else {$("#login_tab")[0].click();}
}
<a id="login_tab" data-bs-toggle="tab" href="#lg1"><h4>会员登录</h4>
</a>
<a id="register_tab" data-bs-toggle="tab" href="#lg2"><h4>会员注册</h4>
</a>

5)加入register_ok.jsp, register_fail.jsp页面

<a class="active"  href="index.jsp"><h4>注册成功, 返回首页</h4>
</a>
<a class="active"  href="views/member/login.jsp"><h4>注册失败, 重新注册</h4>
</a>

16.删除点击注册后的拦截代码web/views/member/login.jsp

//这里暂时不提交=>显示验证通过
$("span.errorMsg").text("验证通过");
return false;

17.测试

在这里插入图片描述

在这里插入图片描述

🐇会员登陆

思路分析
1.输入用户名和密码后提交
2.如果输入有误,则给出提示
3.判断会员是否存在
4.会员存在于数据库, 显示登录成功页面
5.否则, 返回登陆页面, 重新登陆
6.要求改进登陆密码为md5加密

程序框架图
在这里插入图片描述

代码实现
1.修改src/com/zzw/furns/dao/MemberDao.java

在这里插入图片描述

2.修改src/com/zzw/furns/dao/MemberDaoImpl.java

/*** 根据用户名和密码查询对应的Member对象* @param username 用户名* @param password 密码* @return 对应的Member对象, 如果没有 则返回null*/
@Override
public Member queryMemberByUsernameAndPassword(String username, String password) {String sql = "SELECT id, username, `password`, email FROM member WHERE username = ? AND `password` = MD5(?);";Member member = querySingle(sql, Member.class, username, password);return member;
}

3.测试(不要忘了测试)

@Test
public void queryMemberByUsernameAndPassword() {String username = "admin";String password = "123456";Member member = memberDao.queryMemberByUsernameAndPassword(username, password);if (member == null) {System.out.println("用户名或密码错误");} else {System.out.println("登录成功");}
}

快捷键
在这里插入图片描述
在这里插入图片描述

4.修改src/com/zzw/furns/service/MemberService.java

public interface MemberService {/*** 根据传入的member信息, 返回对应在DB中的member对象* @param member 是根据用户登录构建一个member* @return 返回的是对应的DB中的member对象, 如果不存在返回null*/public Member login(Member member);
}

5.修改src/com/zzw/furns/service/impl/MemberServiceImpl.java

public class MemberServiceImpl implements MemberService {//定义MemberDAO属性private MemberDAO memberDAO = new MemberDAOImpl();/*** 判断用户名和密码是否存在* @param username 用户名* @param password 密码* @return*/@Overridepublic Member login(Member member) {//返回一个对象return memberDAO.queryMemberByUsernameAndPassword(member.getUsername(), member.getPassword());}
}

6.测试(不要忘了测试)

@Test
public void login() {Member member = new Member(null, "adminx", "admin", null);Member login = memberService.login(member);System.out.println("login= " + login);
}

7.修改src/com/zzw/furns/web/LoginServlet.java

public class LoginServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {doPost(request, response);}private MemberService memberService = new MemberServiceImpl();@Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {//如果在登陆界面用户没有输入内容, 后台接收到的是""String username = request.getParameter("username");String password = request.getParameter("password");Member member = new Member(null, username, password, null);if (memberService.login(member) != null) {//用户存在DBSystem.out.println("用户存在, 登陆成功...");request.getRequestDispatcher("/views/member/login_ok.html").forward(request, response);} else {//用户不存在System.out.println("登陆失败, 返回登陆页面");request.setAttribute("username", username);request.setAttribute("msg", "登陆失败");request.getRequestDispatcher("/views/member/login.jsp").forward(request, response);}}
}

配置LoginServlet

<servlet><servlet-name>LoginServlet</servlet-name><servlet-class>com.zzw.furns.web.LoginServlet</servlet-class>
</servlet>
<servlet-mapping><servlet-name>LoginServlet</servlet-name><url-pattern>/login</url-pattern>
</servlet-mapping>

8.修改web/views/member/login.jsp

$("button:first")[0].onclick = function () {//采用过关斩将法//正则表达式验证用户名var usernameValue = $("form:first")[0].childNodes[3].value;var usernamePattern = /^\w{6,10}$/;if (!usernamePattern.test(usernameValue)) {$("span[class='errorMsg2']").text("用户名格式不对, 需要6-10个字符(大小写字母,数字,下划线)");return false;}//验证密码var passwordValue = $("form:first")[0].childNodes[5].value;var passwordPattern = /^\w{6,10}$/;if (!passwordPattern.test(passwordValue)) {$("span.errorMsg2").text("密码格式不对, 需要6-10个字符(大小写字母,数字,下划线)");return false;}
}
<!--会员登录-->
<span class="errorMsg2"style="float: right; font-weight: bold; color: lightgray; font-size: 20pt; margin-left: 10px;">${msg}</span>
<form action="loginServlet" method="post"><input type="text" name="username" value="${username}" placeholder="Username"/><input type="password" name="password" placeholder="Password"/><div class="button-box"><div class="login-toggle-btn"><input type="checkbox"/><a class="flote-none" href="javascript:void(0)">Remember me</a><a href="#">Forgot Password?</a></div><button type="submit"><span>Login</span></button></div>
</form>

9.添加login_ok.jsp, 参考

10.快捷键学习

在这里插入图片描述

11.测试
在这里插入图片描述
在这里插入图片描述

这篇关于项目实战系列: 家居购项目 第一部分的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1142229

相关文章

网页解析 lxml 库--实战

lxml库使用流程 lxml 是 Python 的第三方解析库,完全使用 Python 语言编写,它对 XPath表达式提供了良好的支 持,因此能够了高效地解析 HTML/XML 文档。本节讲解如何通过 lxml 库解析 HTML 文档。 pip install lxml lxm| 库提供了一个 etree 模块,该模块专门用来解析 HTML/XML 文档,下面来介绍一下 lxml 库

Spring Security 从入门到进阶系列教程

Spring Security 入门系列 《保护 Web 应用的安全》 《Spring-Security-入门(一):登录与退出》 《Spring-Security-入门(二):基于数据库验证》 《Spring-Security-入门(三):密码加密》 《Spring-Security-入门(四):自定义-Filter》 《Spring-Security-入门(五):在 Sprin

这15个Vue指令,让你的项目开发爽到爆

1. V-Hotkey 仓库地址: github.com/Dafrok/v-ho… Demo: 戳这里 https://dafrok.github.io/v-hotkey 安装: npm install --save v-hotkey 这个指令可以给组件绑定一个或多个快捷键。你想要通过按下 Escape 键后隐藏某个组件,按住 Control 和回车键再显示它吗?小菜一碟: <template

如何用Docker运行Django项目

本章教程,介绍如何用Docker创建一个Django,并运行能够访问。 一、拉取镜像 这里我们使用python3.11版本的docker镜像 docker pull python:3.11 二、运行容器 这里我们将容器内部的8080端口,映射到宿主机的80端口上。 docker run -itd --name python311 -p

性能分析之MySQL索引实战案例

文章目录 一、前言二、准备三、MySQL索引优化四、MySQL 索引知识回顾五、总结 一、前言 在上一讲性能工具之 JProfiler 简单登录案例分析实战中已经发现SQL没有建立索引问题,本文将一起从代码层去分析为什么没有建立索引? 开源ERP项目地址:https://gitee.com/jishenghua/JSH_ERP 二、准备 打开IDEA找到登录请求资源路径位置

C#实战|大乐透选号器[6]:实现实时显示已选择的红蓝球数量

哈喽,你好啊,我是雷工。 关于大乐透选号器在前面已经记录了5篇笔记,这是第6篇; 接下来实现实时显示当前选中红球数量,蓝球数量; 以下为练习笔记。 01 效果演示 当选择和取消选择红球或蓝球时,在对应的位置显示实时已选择的红球、蓝球的数量; 02 标签名称 分别设置Label标签名称为:lblRedCount、lblBlueCount

科研绘图系列:R语言扩展物种堆积图(Extended Stacked Barplot)

介绍 R语言的扩展物种堆积图是一种数据可视化工具,它不仅展示了物种的堆积结果,还整合了不同样本分组之间的差异性分析结果。这种图形表示方法能够直观地比较不同物种在各个分组中的显著性差异,为研究者提供了一种有效的数据解读方式。 加载R包 knitr::opts_chunk$set(warning = F, message = F)library(tidyverse)library(phyl

在cscode中通过maven创建java项目

在cscode中创建java项目 可以通过博客完成maven的导入 建立maven项目 使用快捷键 Ctrl + Shift + P 建立一个 Maven 项目 1 Ctrl + Shift + P 打开输入框2 输入 "> java create"3 选择 maven4 选择 No Archetype5 输入 域名6 输入项目名称7 建立一个文件目录存放项目,文件名一般为项目名8 确定

【生成模型系列(初级)】嵌入(Embedding)方程——自然语言处理的数学灵魂【通俗理解】

【通俗理解】嵌入(Embedding)方程——自然语言处理的数学灵魂 关键词提炼 #嵌入方程 #自然语言处理 #词向量 #机器学习 #神经网络 #向量空间模型 #Siri #Google翻译 #AlexNet 第一节:嵌入方程的类比与核心概念【尽可能通俗】 嵌入方程可以被看作是自然语言处理中的“翻译机”,它将文本中的单词或短语转换成计算机能够理解的数学形式,即向量。 正如翻译机将一种语言

滚雪球学Java(87):Java事务处理:JDBC的ACID属性与实战技巧!真有两下子!

咦咦咦,各位小可爱,我是你们的好伙伴——bug菌,今天又来给大家普及Java SE啦,别躲起来啊,听我讲干货还不快点赞,赞多了我就有动力讲得更嗨啦!所以呀,养成先点赞后阅读的好习惯,别被干货淹没了哦~ 🏆本文收录于「滚雪球学Java」专栏,专业攻坚指数级提升,助你一臂之力,带你早日登顶🚀,欢迎大家关注&&收藏!持续更新中,up!up!up!! 环境说明:Windows 10