家居网购项目(一)

文章目录

    • 1.前置知识
        • 1.项目开发阶段
        • 2.Java经典三层架构
        • 3.项目具体分层(包方案)
        • 4.MVC
    • 2.开发环境搭建
        • 1.新建普通javaweb项目,导入jar包
        • 2.创建项目结构
        • 3.搭建前端页面
    • 3.会员注册前端js校验
        • 1.需求分析
        • 2.代码
          • login.html
        • 3.结果
        • 4.调试阶段
          • 1.验证信息一闪而过
            • 原因:
    • 4.会员注册后端
        • 1.需求分析
        • 2.程序框架图
        • 3.数据库表设计
          • 会员表设计
        • 4.建立javabean与表的映射
          • Member.java
        • 5.引入德鲁伊连接池工具类
          • JDBCUtilsByDruid.java
        • 6.引入BasicDao
          • BasicDao.java
        • 7.编写druid配置文件
          • druid.properties
          • 编写测试类,测试连接
            • JDBCUtilsByDruidTest.java
        • 8.编写MemberDao
          • 1.MemberDao.java
          • 2.MemberDaoImpl.java
          • 3.进行单元测试
            • MemberDaoTest.java
            • 测试结果:
        • 9.编写MemberService
          • 1.MemberService.java
          • 2.MemberServiceImpl.java
          • 3.进行单元测试
            • MemberServiceTest.java
            • 测试结果
        • 10.login.html优化
          • 1.设置base路径
          • 2.修改所有../../为空
          • 3.运行login.html
          • 4.修改前端js验证通过逻辑
        • 11.编写RegisterServlet
          • 1.修改login.html
          • 2.引入两个前端页面
          • 3.修改两个页面的base路径
          • 4.RegisterServlet.java
        • 12.注册功能展示
          • 注册界面
          • 注册成功
          • 注册失败返回首页

1.前置知识

1.项目开发阶段

image-20240204174457829

2.Java经典三层架构

image-20240204181049612

3.项目具体分层(包方案)

image-20240204181314291

4.MVC

image-20240204183543670

image-20240204182252025

2.开发环境搭建

1.新建普通javaweb项目,导入jar包

image-20240204185053583

2.创建项目结构

image-20240204185122184

3.搭建前端页面

image-20240204191613545

3.会员注册前端js校验

1.需求分析

image-20240204193615650

2.代码
login.html
<!--    引入jquery--><script type="text/javascript" src="../../script/jquery-3.6.0.min.js"></script><script>$(function () { //页面加载//绑定注册按钮点击事件$("#sub-btn").click(function () {//获取usernamevar usernameVal = $("#username").val();// alert(usernameVal);//1.编写正则表达式验证用户名var usernamePattern = /^\w{6,10}$/;//验证if (!usernamePattern.test(usernameVal)) {//使用前端给的span展示错误信息$("span[class='errorMsg']").text("用户名格式不对,需要6到10个字符");return false; //不提交}//2.编写正则表达式验证密码//获取密码var passwordVal =  $("#password").val();//正则var passwordPattern = /^\w{6,10}$/;//验证if (!passwordPattern.test(passwordVal)) {//使用前端给的span展示错误信息(普通选择器)$("span.errorMsg").text("密码格式不对,需要6到10个字符");return false;}//3.两次密码需要相同//获取第二次输入的密码var repwdVal = $("#repwd").val();//与第一次的密码进行比较if (repwdVal != passwordVal) {$("span.errorMsg").text("两次密码不相同!");return false;}//4.验证邮箱//得到邮箱var emailVal = $("#email").val();//正则var emailPattern = /^[\w-]+@([a-zA-Z]+\.)+[a-zA-Z]+$/; //java中是两个斜杠,js是一个//验证if(!emailPattern.test(emailVal)) {$("span.errorMsg").text("电子邮件格式不对!");return false;}//暂时先算过关,先不提交$("span.errorMsg").text("验证通过!");return false;})})</script>
3.结果

image-20240204201041909

4.调试阶段
1.验证信息一闪而过
原因:

没有在js中return false,阻止表单提交

4.会员注册后端

1.需求分析

image-20240204201601053

2.程序框架图

image-20240204202530923

3.数据库表设计
会员表设计
-- 创建家具网购数据库表
CREATE DATABASE home_furnishing;USE home_furnishing;-- 创建会员表
CREATE TABLE `member` (
`id` INT PRIMARY KEY auto_increment,
`username` VARCHAR(32) NOT NULL UNIQUE,
`password` VARCHAR(32) NOT NULL,
`email` VARCHAR(64)
)
-- 测试数据
INSERT INTO member VALUES(NULL, 'admin', MD5('admin'), '1721469477@qq.com')
4.建立javabean与表的映射
Member.java
package com.sxs.furns.entity;/*** @author 孙显圣* @version 1.0*/
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;}public Integer getId() {return id;}public void setId(Integer id) {this.id = id;}public String getUsername() {return username;}public void setUsername(String username) {this.username = username;}public String getPassword() {return password;}public void setPassword(String password) {this.password = password;}public String getEmail() {return email;}public void setEmail(String email) {this.email = email;}
}
5.引入德鲁伊连接池工具类
JDBCUtilsByDruid.java
package com.sxs.furns.utils;import com.alibaba.druid.pool.DruidDataSourceFactory;import javax.sql.DataSource;
import java.io.IOException;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;/*** @author 孙显圣* @version 1.0*/
public class JDBCUtilsByDruid {//静态数据源引用(jdbc的接口)private static DataSource dataSource;//静态代码块,在类加载时为数据源引用赋值static {//1.读取配置文件Properties properties = new Properties();try {//使用类加载器读取配置文件,配置文件放在resources文件夹//这句话的意思是,使用JDBCUtilsByDruid类读取在resources文件夹下的配置文件,druid.propertiesproperties.load(JDBCUtilsByDruid.class.getClassLoader().getResourceAsStream("druid.properties"));} catch (IOException e) {throw new RuntimeException(e);}//2.使用配置文件,创建德鲁伊数据源对象try {dataSource = DruidDataSourceFactory.createDataSource(properties);} catch (Exception e) {throw new RuntimeException(e);}}//编写getConnection方法public static Connection getConnection() {try {return dataSource.getConnection();} catch (SQLException e) {throw new RuntimeException(e);}}//把Connection对象放回连接池public static void close(ResultSet resultSet, Statement statement, Connection connection) {try {if (resultSet != null) {resultSet.close();}if (statement != null) {statement.close();}if (connection != null) {connection.close();}} catch (SQLException e) {throw new RuntimeException(e);}}}
6.引入BasicDao
BasicDao.java
package com.sxs.furns.dao;import com.sxs.furns.utils.JDBCUtilsByDruid;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanHandler;
import org.apache.commons.dbutils.handlers.BeanListHandler;
import org.apache.commons.dbutils.handlers.ScalarHandler;import java.sql.Connection;
import java.sql.SQLException;
import java.util.List;/*** @author 孙显圣* @version 1.0* 开发BasicDAO , 是其他DAO的父类*/
public class BasicDao<T> { //泛型指定具体类型private QueryRunner qr =  new QueryRunner();//开发通用的dml方法, 针对任意的表public int update(String sql, Object... parameters) {Connection connection = null;try {connection = JDBCUtilsByDruid.getConnection();int update = qr.update(connection, sql, parameters);return  update;} catch (SQLException e) {throw  new RuntimeException(e); //将编译异常->运行异常 ,抛出} finally {JDBCUtilsByDruid.close(null, null, connection);}}//返回多个对象(即查询的结果是多行), 针对任意表/**** @param sql sql 语句,可以有 ?* @param clazz 传入一个类的Class对象 比如 Actor.class* @param parameters 传入 ? 的具体的值,可以是多个* @return 根据Actor.class 返回对应的 ArrayList 集合*/public List<T> queryMulti(String sql, Class<T> clazz, Object... parameters) {Connection connection = null;try {connection = JDBCUtilsByDruid.getConnection();return qr.query(connection, sql, new BeanListHandler<T>(clazz), parameters);} catch (SQLException e) {throw  new RuntimeException(e); //将编译异常->运行异常 ,抛出} finally {JDBCUtilsByDruid.close(null, null, connection);}}//查询单行结果 的通用方法public T querySingle(String sql, Class<T> clazz, Object... parameters) {Connection connection = null;try {connection = JDBCUtilsByDruid.getConnection();return  qr.query(connection, sql, new BeanHandler<T>(clazz), parameters);} catch (SQLException e) {throw  new RuntimeException(e); //将编译异常->运行异常 ,抛出} finally {JDBCUtilsByDruid.close(null, null, connection);}}//查询单行单列的方法,即返回单值的方法public Object queryScalar(String sql, Object... parameters) {Connection connection = null;try {connection = JDBCUtilsByDruid.getConnection();return  qr.query(connection, sql, new ScalarHandler(), parameters);} catch (SQLException e) {throw  new RuntimeException(e); //将编译异常->运行异常 ,抛出} finally {JDBCUtilsByDruid.close(null, null, connection);}}}
7.编写druid配置文件
druid.properties
#key=value
driverClassName=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://localhost:3306/home_furnishing?rewriteBatchedStatements=true
#url=jdbc:mysql://localhost:3306/girls
username=root
password=root
#initial connection Size
initialSize=10
#min idle connecton size
minIdle=5
#max active connection size
maxActive=50
#max wait time (5000 mil seconds)
maxWait=5000
编写测试类,测试连接
JDBCUtilsByDruidTest.java
package com.sxs.furns.test;import com.sxs.furns.utils.JDBCUtilsByDruid;
import org.junit.Test;import java.sql.Connection;/*** @author 孙显圣* @version 1.0*/
public class JDBCUtilsByDruidTest {@Testpublic void getConnection() {//测试连接Connection connection = JDBCUtilsByDruid.getConnection();System.out.println(connection);JDBCUtilsByDruid.close(null, null, connection);}
}

image-20240204210743090

8.编写MemberDao
1.MemberDao.java
package com.sxs.furns.dao;import com.sxs.furns.entity.Member;/*** @author 孙显圣* @version 1.0*/
public interface MemberDao {//1.通过用户名返回Memberpublic Member queryMemberByUsername(String username);//2.保存Member对象到数据库的member表public int saveMember(Member member);
}
2.MemberDaoImpl.java
package com.sxs.furns.dao.impl;import com.sxs.furns.dao.BasicDao;
import com.sxs.furns.dao.MemberDao;
import com.sxs.furns.entity.Member;/*** @author 孙显圣* @version 1.0*/
public class MemberDaoImpl extends BasicDao<Member> implements MemberDao {/*** 通过用户名,返回对应的Member* @param username 用户名* @return 对应的Member对象,如果没有则返回null*/@Overridepublic Member queryMemberByUsername(String username) {//查询单行数据Member member = querySingle("select * from member where username = ?", Member.class, username);return member;}/*** 保存一个会员* @param member 传入Member对象* @return 返回-1就是失败,返回其他的数字就是受影响的行数*/@Overridepublic int saveMember(Member member) {//获取member对象信息String username = member.getUsername();String password = member.getPassword();String email = member.getEmail();//插入到member表中return update("insert into member values(?,?,md5(?),?)", null, username, password, email);}
}
3.进行单元测试
MemberDaoTest.java
package com.sxs.furns.test;import com.sxs.furns.dao.MemberDao;
import com.sxs.furns.dao.impl.MemberDaoImpl;
import com.sxs.furns.entity.Member;
import org.junit.Test;/*** @author 孙显圣* @version 1.0*/
public class MemberDaoTest {private MemberDao memberDao = new MemberDaoImpl();@Testpublic void queryMemberByUsername() {if (memberDao.queryMemberByUsername("admin") == null) {System.out.println("该用户不存在");} else {System.out.println("该用户存在");}}@Testpublic void saveMember() {Member member = new Member(null, "jack", "123", "123@qq.com");if (memberDao.saveMember(member) == 1) {System.out.println("添加成功");} else {System.out.println("添加失败");}}
}
测试结果:

image-20240205095931244

image-20240205095853310

9.编写MemberService
1.MemberService.java
package com.sxs.furns.service;import com.sxs.furns.entity.Member;/*** @author 孙显圣* @version 1.0*/
public interface MemberService {//注册用户public boolean registerMember(Member member);//判断用户名是否存在public boolean isExistsUsername(String username);
}
2.MemberServiceImpl.java
package com.sxs.furns.service.impl;import com.sxs.furns.dao.MemberDao;
import com.sxs.furns.dao.impl.MemberDaoImpl;
import com.sxs.furns.entity.Member;
import com.sxs.furns.service.MemberService;/*** @author 孙显圣* @version 1.0*/
public class MemberServiceImpl implements MemberService {//定义一个MemberDao的属性MemberDao memberDao = new MemberDaoImpl();/*** 将注册用户信息插入到数据库中* @param member 注册用户信息* @return 成功返回true,失败返回false*/@Overridepublic boolean registerMember(Member member) {return memberDao.saveMember(member) == 1 ? true : false;}/*** 判断用户是否存在* @param username 用户名* @return 如果存在,返回true,否则返回false*/@Overridepublic boolean isExistsUsername(String username) {return memberDao.queryMemberByUsername(username) == null ? false : true;}
}
3.进行单元测试
MemberServiceTest.java
package com.sxs.furns.test;import com.sxs.furns.entity.Member;
import com.sxs.furns.service.MemberService;
import com.sxs.furns.service.impl.MemberServiceImpl;
import org.junit.Test;/*** @author 孙显圣* @version 1.0*/
public class MemberServiceTest {private MemberService memberService = new MemberServiceImpl();@Testpublic void registerMember() {Member member = new Member(null, "jack", "123", "123@qq.com");if (!memberService.registerMember(member)) {System.out.println("注册失败");} else {System.out.println("注册成功");}}@Testpublic void isExistsUsername() {if (!memberService.isExistsUsername("jack")) {System.out.println("用户不存在");} else {System.out.println("用户存在");}}
}
测试结果

image-20240205102436637

image-20240205102443364

10.login.html优化
1.设置base路径
<!--    base路径设置    --><base href="http://localhost:8080/jiaju_mail/">

image-20240205104237811

2.修改所有…/…/为空

image-20240205104843033

3.运行login.html

image-20240205104903148

4.修改前端js验证通过逻辑

image-20240205105045231

11.编写RegisterServlet
1.修改login.html

image-20240205105359729

2.引入两个前端页面

image-20240205140855281

3.修改两个页面的base路径

image-20240205140931909

4.RegisterServlet.java
package com.sxs.furns.web;import com.sxs.furns.entity.Member;
import com.sxs.furns.service.MemberService;
import com.sxs.furns.service.impl.MemberServiceImpl;import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;/*** @author 孙显圣* @version 1.0*/
@WebServlet(urlPatterns = "/registerServlet")
public class RegisterServlet extends HttpServlet {//定义属性private MemberService memberService = new MemberServiceImpl();@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//接受用户注册信息String username = req.getParameter("username");String password = req.getParameter("password");String email = req.getParameter("email");//判断用户名是否在数据库中if (!memberService.isExistsUsername(username)) { //不在数据库中,可以注册Member member = new Member(null, username, password, email);//注册if (memberService.registerMember(member)) {//请求转发req.getRequestDispatcher("/views/member/register_ok.html").forward(req, resp);} else {//请求转发req.getRequestDispatcher("/views/member/register_fail.html").forward(req, resp);}} else {//返回注册页面req.getRequestDispatcher("/views/member/login.html").forward(req, resp);}}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {doGet(req, resp);}
}
12.注册功能展示
注册界面

image-20240205141051819

注册成功

image-20240205141105048

注册失败返回首页

image-20240205141249455

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

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

相关文章

如何在群晖本地搭建在线PS工具Potopea并实现无公网IP远程编辑图片

文章目录 1. 部署Photopea2. 运行Photopea3. 群晖安装Cpolar4. 配置公网地址5. 公网访问测试6. 固定公网地址 本文主要介绍如何在群晖NAS使用Docker部署Potopea在线图片编辑工具&#xff0c;并结合cpolar内网穿透实现公网环境可以远程访问本地部署的Potopea. Photopea是一款强大…

如何实现无感刷新(附前后端实现)?

无感刷新的核心思路&#xff1a; 无感刷新机制的目的是在用户不知情的情况下&#xff0c;自动更新其认证令牌&#xff08;通常是Access Token&#xff09;&#xff0c;以保证用户的会话不会中断。这通常涉及到两种类型的令牌&#xff1a; Access Token&#xff1a;它是用户进行…

Python(3):条件语句+循环语句+逻辑运算符+符号优先级

文章目录 一、if语句1.if语句2.if 和 elif区别3.三元表达式 二、循环语句1.range函数和循环结束关键字2.while循环3.for循环 三、逻辑运算符1.and语句2.or语句3.not语句4.逻辑运算法的优先级 四、python运算符优先级和结合性一览表 一、if语句 1.if语句 1.if单分支语句 格式…

分布式锁-redission可重入锁原理

5.3 分布式锁-redission可重入锁原理 在Lock锁中&#xff0c;他是借助于底层的一个voaltile的一个state变量来记录重入的状态的&#xff0c;比如当前没有人持有这把锁&#xff0c;那么state0&#xff0c;假如有人持有这把锁&#xff0c;那么state1&#xff0c;如果持有这把锁的…

常用Python爬虫库汇总

很多人学Python&#xff0c;都是从爬虫开始的&#xff0c;毕竟网上类似的资源很丰富&#xff0c;开源项目也非常多。 Python学习网络爬虫主要分3个大的版块&#xff1a; 抓取 &#xff0c; 分析 &#xff0c; 存储 当我们在浏览器中输入一个url后回车&#xff0c;后台会发生什…

跟着Carl大佬学leetcode之27 移除元素

来点强调&#xff0c;刷题是按照代码随想录的顺序进行的&#xff0c;链接如下https://www.programmercarl.com/本系列是记录一些刷题心得和学习过程&#xff0c;就看到题目自己先上手试试&#xff0c;然后看程序员Carl大佬的解释&#xff0c;自己再敲一遍修修补补&#xff0c;练…

Linux网络名称空间和虚拟机有何区别

在Linux系统中&#xff0c;网络名称空间和虚拟机都是实现资源隔离和虚拟化的技术&#xff0c;但它们在设计理念、实现机制、资源消耗、使用场景等方面存在着显著的区别。本文旨在全方位、系统性地分析这两种技术的区别。&#x1f50d; 1. 设计理念与实现机制 1.1. 网络名称空…

中国软件商业模式

很多IT技术人、风险投资人这些年进入SaaS产业&#xff0c;写了大量的文章来诊断中国软件产业。 我只是看过去十年的中国软件百强&#xff0c;这是事实上在中国这片土地上长出来并且跑出来的厂商。实践是检验一切真理的唯一标准。说美国怎么样怎么样&#xff0c;中国甲方企业和中…

MMYOLO调试RTMDet--小数据集split_ss_dota_200

背景 用MMYOLO调试旋转目标检测时需要用到dota数据集&#xff0c;根据MMYOLO的官方教程&#xff0c;dota数据集经过处理后变为split_ss_dota&#xff0c;但是该数据集还是很大&#xff0c;对于一些配置比较低的机器要调试比较麻烦&#xff0c;所以这里针对该数据集&#xff0c…

从0到1实现RPC | 09 故障隔离与恢复

一、应用场景 故障隔离解决的是&#xff1a;当服务提供者provider出现异常时&#xff0c;消费者consumer就不再调用异常实例&#xff0c;而是选择好的实例&#xff0c;避免频繁出错。 故障恢复解决的是&#xff1a;一段时间过后&#xff0c;服务提供者provider可以正常提供服…

Python+Selenium+Unittest 之Unittest5(常用装饰器-跳过用例执行)

目录 1、unittest.skip()&#xff08;跳过该装饰器下的用例&#xff09; 2、unittest.skipIf()&#xff08;跳过该装饰器下判断条件为True的用例&#xff09; 3、unittest.skipUnless()&#xff08;跳过该装饰器下判断条件为False的用例&#xff09; 4、unittest.expectedF…

Thingsboard PE智慧运维仪表板实例(二)【智慧排口截污实例】

ThingsBoard 的仪表板是一个用于可视化和监控物联网数据的重要组件。 它具有以下特点: 1. 可定制性:用户可以根据自己的需求创建各种类型的图表、表格和指标。 2. 数据可视化:以直观的方式展示设备数据,帮助用户快速了解系统状态。 3. 实时更新:实时反映设备的最新数据…