尚硅谷书城项目总结

2023-10-13 13:40
文章标签 总结 项目 硅谷 书城

本文主要是介绍尚硅谷书城项目总结,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

尚硅谷书城项目

跟着课程讲的思路来做项目,一步一步梳理的都很清晰,小黄记性不太好,决定边做边总结,本片文章持续更新

先附上尚硅谷的JavaWeb视频链接,对我帮助极大,有兴趣的小伙伴也可以跟着一起学习,一起进步

https://www.bilibili.com/video/BV1Y7411K7zz

第一阶段:表单验证

大部分网站都会有登录注册功能,而在这些用户可以进行操作的板块中,我们需要通过JS将用户填写的内容进行一个判断,在前端先检查,避免将无用的数据传到服务器对服务器造成负担

操作流程(我们拿注册来举例说明)

  1. 给注册按钮绑定单击事件
  2. 获取用户输入在输入框中的内容
  3. 按照规则进行判断(可能用到正则表达式)
  4. 输入不合法返回提示信息

先来看一下表单(为了全篇文章的可读性,我只会贴一小部分实例代码)

<%--span.errorMsg用于显示返回的错误信息--%>
<span class="errorMsg"></span>
<form><input type="hidden" name="function" value="regist"><label>用户名称:</label><input class="itxt" type="text" placeholder="请输入用户名"autocomplete="off" tabindex="1" name="username" id="username"/><br /><input type="submit" value="注册" id="sub_btn" />
</form>

我们的要求是用户名必须由字母、数字、下划线组成,并且长度在5-12之间,这个需求我们需要使用正则表达式

$(function () {// 给注册绑定单击事件$("#sub_btn").click(function () {// 验证用户名:必须由字母,数字下划线组成,并且长度为5到12位//1 获取用户名输入框里的内容var usernameText = $("#username").val();//2 创建正则表达式对象var usernamePatt = /^\w{5,12}$/;//3 使用test方法验证if (!usernamePatt.test(usernameText)) {//4 提示用户结果$("span.errorMsg").text("用户名不合法!");//返回false代表验证不通过时,不会跳转页面return false;}});
});

第二阶段:搭建书城项目环境

第二阶段我们开始着手搭建书城项目的环境,并且实现用户登录、注册的功能

先来看一下JavaEE的三层架构

在这里插入图片描述

一般我们的项目都会有以下几个包,先来介绍一下这些包的用处

  • dao:dao层是专门用来与数据库打交道的,这里存放到dao接口包
  • daoImpl:dao接口的实现类
  • pojo:Javabean对象
  • service:service接口包
  • serviceImpl:service接口实现类
  • servlet:servlet类
  • test:测试类
  • utils:工具类

在这里插入图片描述

实际开发中,我们应该从数据库一层一层的往外写

  • 编写JdbcUtils类,用于连接数据库(采用德鲁伊数据库连接池)

    public class JdbcUtils {private static DataSource dataSource = null;static{try {Properties prop = new Properties();InputStream is = JdbcUtils.class.getClassLoader().getResourceAsStream("jdbc.properties");prop.load(is);dataSource = DruidDataSourceFactory.createDataSource(prop);} catch (Exception e) {e.printStackTrace();}}/*** 从数据库连接池中拿出一条链接* @return*/public static Connection getConnection(){Connection conn = null;try {conn = dataSource.getConnection();} catch (SQLException throwables) {throwables.printStackTrace();}return conn;}/*** 关闭一条连接* @param conn*/public static void close(Connection conn){if(conn != null){try {conn.close();} catch (SQLException throwables) {throwables.printStackTrace();}}}
    }
    

    每一个小demo编写完成,都需要进行测试,测试代码放在test目录下,我就不贴出来了

  • 编写BaseDao类,用于与数据库的交互,执行CRUD操作

    public class BaseDAO {private QueryRunner queryRunner = new QueryRunner();/*** update():用于执行insert、update、delete语句* @param conn* @param sql 执行的sql语句* @param args 填充sql的占位符* @return 返回值为影响的行数,返回-1代表失败*/public int update(Connection conn,String sql,Object... args){int rows = -1;try {rows = queryRunner.update(conn, sql, args);} catch (SQLException throwables) {throwables.printStackTrace();}return rows;}/*** queryByOne():用于查询一行数据* @param type 返回值类型* @param conn* @param sql 执行的sql* @param args 填充占位符* @param <T> 返回值类型的泛型* @return*/public <T> T queryByOne(Class<T> type,Connection conn,String sql,Object... args){T t = null;try {t = queryRunner.query(conn, sql, new BeanHandler<>(type), args);} catch (SQLException throwables) {throwables.printStackTrace();}return t;}/*** queryByList():用于返回多条数据* @param type 返回值类型* @param conn* @param sql 执行的sql* @param args 填充占位符* @param <T> 返回值类型的泛型* @return*/public <T>List<T> queryByList(Class<T> type,Connection conn,String sql,Object... args){List<T> list = null;try {list = queryRunner.query(conn, sql, new BeanListHandler<>(type), args);} catch (SQLException throwables) {throwables.printStackTrace();}return list;}/*** queryForSingleValue():用于查询函数语句* @param conn* @param sql* @param args* @return*/public Object queryForSingleValue(Connection conn,String sql,Object... args){Object result = null;try {result = queryRunner.query(conn, sql, new ScalarHandler(), args);} catch (SQLException throwables) {throwables.printStackTrace();}return result;}
    }
    
  • 编写UserDao接口

    这里我们要结合业务来看,登录注册需要的操作有:

    • 判断用户名是否重复(注册):根据用户名查询数据库中的数据
    • 判断用户名密码是否存在(登录):根据用户名密码查询数据库中的数据
    • 保存用户信息(注册):将用户输入的数据保存到数据库
    public interface UserDAO {//根据用户名查询数据库中的数据User queryUserByUsername(String username);//根据用户名密码查询数据库中的数据User queryUserByUsernameAndPassword(String username,String password);//将用户输入的数据保存到数据库void saveUser(User user);
    }
    
  • 编写UserDaoImpl类实现UserDao接口

    public class UserDAOImpl extends BaseDAO implements UserDAO {@Overridepublic User queryUserByUsername(String username) {Connection conn = JdbcUtils.getConnection();String sql = "select id,username,password,email from t_user where username = ?";User user = queryByOne(User.class, conn, sql, username);JdbcUtils.close(conn);return user;}@Overridepublic User queryUserByUsernameAndPassword(String username, String password) {Connection conn = JdbcUtils.getConnection();String sql = "select id,username,password,email from t_user where username = ? and password = ?";User user = queryByOne(User.class, conn, sql, username,password);JdbcUtils.close(conn);return user;}@Overridepublic void saveUser(User user) {Connection conn = JdbcUtils.getConnection();String sql = "insert into t_user(username,password,email) values (?,?,?)";update(conn, sql, user.getUsername(), user.getPassword(), user.getEmail());}
    }
    

    以上dao层的操作我们算是做完了,需要做一个小测试,接下来我们看一下service如何处理

  • 编写UserService接口

    service接口我们就需要更具体的去调用dao中的方法

    public interface UserService {User login(String username,String password);void regist(User user);/*** 判断用户名是否存在* @param username* @return 返回true代表用户名存在,不可用,反之亦然*/boolean existUsername(String username);
    }
  • 编写UserServiceImpl类实现UserService接口

    public class UserServiceImpl implements UserService {UserDAO userDAO = new UserDAOImpl();@Overridepublic User login(String username, String password) {User user = userDAO.queryUserByUsernameAndPassword(username, password);return user;}@Overridepublic void regist(User user) {userDAO.saveUser(user);}@Overridepublic boolean existUsername(String username) {User user = userDAO.queryUserByUsername(username);if(user == null){return false;}return true;}
    }
    

    以上完成之后,我们开始编写servlet程序,来实现需求

  • 编写登录的servlet程序

    public class UserLoginServlet extends HttpServlet {@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {String username = req.getParameter("username");String password = req.getParameter("password");UserService userService = new UserServiceImpl();if(userService.login(username, password) != null){//使用请求重定向,成功之后跳转页面req.getRequestDispatcher("pages/user/login_success.jsp").forward(req,resp);}else {//登录失败req.setAttribute("msg","用户名或密码错误");req.setAttribute("username",username);req.getRequestDispatcher("pages/user/login.jsp").forward(req,resp);}}
    }
    
  • 编写注册的servlet程序

    public class UserRegistServlet extends HttpServlet {@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {String username = req.getParameter("username");String password = req.getParameter("password");String email = req.getParameter("email");String code = req.getParameter("code");//判断用户名是否存在UserService userService = new UserServiceImpl();if(!userService.existUsername(username)){//用户名可用if("abcde".equals(code)){//验证码正确userService.regist(new User(null,username,password,email));req.getRequestDispatcher("pages/user/regist_success.jsp").forward(req,resp);}else {//回到注册页面req.setAttribute("msg","验证码错误");req.setAttribute("username",username);req.setAttribute("email",email);req.getRequestDispatcher("pages/user/regist.jsp").forward(req,resp);}}else {//回到注册页面req.setAttribute("msg","用户名已存在");req.setAttribute("username",username);req.setAttribute("email",email);req.getRequestDispatcher("pages/user/regist.jsp").forward(req,resp);}}
    }
    

第三阶段:对以上代码进行优化

一般来说,我们一个功能只会有一个servlet程序,比如书城项目,操作用户的是一个userServlet,操作书的是一个BookServlet,我们需要对以上的servlet进行优化,将他整合到一个servlet程序中

思路:运用input:hidden 隐藏表单,将客户端功能传输给服务器,在服务器判断应该执行哪条程序

  • 编写UserServlet

    public class UserServlet extends HttpServlet {@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {if("login".equals(req.getParameter("function"))){login(req,resp);}else if ("regist".equals(req.getParameter("function"){regist(req,resp);}}private void login(HttpServletRequest req,HttpServletResponse resp) throws Exception{String username = req.getParameter("username");String password = req.getParameter("password");UserService userService = new UserServiceImpl();if(userService.login(username, password) != null){req.getRequestDispatcher("pages/user/login_success.jsp").forward(req,resp);}else {//登录失败req.setAttribute("msg","用户名或密码错误");req.setAttribute("username",username);req.getRequestDispatcher("pages/user/login.jsp").forward(req,resp);}}private void regist(HttpServletRequest req,HttpServletResponse resp) throws Exception{String code = req.getParameter("code");User user = ServletUtils.getParamToBean(req.getParameterMap(),new User());//判断用户名是否存在UserService userService = new UserServiceImpl();if(!userService.existUsername(user.getUsername())){//用户名可用if("abcde".equals(code)){//验证码正确userService.regist(user);req.getRequestDispatcher("pages/user/regist_success.jsp").forward(req,resp);}else {//回到注册页面req.setAttribute("msg","验证码错误");req.setAttribute("username",user.getUsername());req.setAttribute("email",user.getEmail());req.getRequestDispatcher("pages/user/regist.jsp").forward(req,resp);}}else {//回到注册页面req.setAttribute("msg","用户名已存在");req.setAttribute("username",user.getUsername());req.setAttribute("email",user.getEmail());req.getRequestDispatcher("pages/user/regist.jsp").forward(req,resp);}}
    }
    
  • 利用反射,去除繁琐的if else

    在实际开发过程中,我们可能不只是登录、注册,可能还有修改信息等等功能,如果我们使用if else,会让代码看上去非常的冗余。我们发现从前端得到的字符串,与我们的方法名相同,这时候我们可以使用反射技术,动态的调用相对于的方法

    public class UserServlet extends HttpServlet {@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {String function = req.getParameter("function");//利用反射,动态调用操作用户的方法,避免大量的if elsetry {Method method =  this.getClass().getDeclaredMethod(function,HttpServletRequest.class,HttpServletResponse.class);method.setAccessible(true);method.invoke(this,req,resp);} catch (Exception e) {e.printStackTrace();}}//重复的login和regist方法就
    }
    
  • 编写BaseServlet

    除了操作用户,操作书籍等功能都需要使用到反射技术,所以我们这些代码提取出来,UserServlet只需继承BaseServlet即可

    public abstract class BaseServlet extends HttpServlet {@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {String function = req.getParameter("function");//利用反射,动态调用操作用户的方法,避免大量的if elsetry {Method method =  this.getClass().getDeclaredMethod(function,HttpServletRequest.class,HttpServletResponse.class);method.setAccessible(true);method.invoke(this,req,resp);} catch (Exception e) {e.printStackTrace();}}
    }
    

这篇关于尚硅谷书城项目总结的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



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

相关文章

关于C++中的虚拟继承的一些总结(虚拟继承,覆盖,派生,隐藏)

1.为什么要引入虚拟继承 虚拟继承是多重继承中特有的概念。虚拟基类是为解决多重继承而出现的。如:类D继承自类B1、B2,而类B1、B2都继承自类A,因此在类D中两次出现类A中的变量和函数。为了节省内存空间,可以将B1、B2对A的继承定义为虚拟继承,而A就成了虚拟基类。实现的代码如下: class A class B1:public virtual A; class B2:pu

用Microsoft.Extensions.Hosting 管理WPF项目.

首先引入必要的包: <ItemGroup><PackageReference Include="CommunityToolkit.Mvvm" Version="8.2.2" /><PackageReference Include="Microsoft.Extensions.Hosting" Version="8.0.0" /><PackageReference Include="Serilog

eclipse运行springboot项目,找不到主类

解决办法尝试了很多种,下载sts压缩包行不通。最后解决办法如图: help--->Eclipse Marketplace--->Popular--->找到Spring Tools 3---->Installed。

十五.各设计模式总结与对比

1.各设计模式总结与对比 1.1.课程目标 1、 简要分析GoF 23种设计模式和设计原则,做整体认知。 2、 剖析Spirng的编程思想,启发思维,为之后深入学习Spring做铺垫。 3、 了解各设计模式之间的关联,解决设计模式混淆的问题。 1.2.内容定位 1、 掌握设计模式的"道" ,而不只是"术" 2、 道可道非常道,滴水石穿非一日之功,做好长期修炼的准备。 3、 不要为了

vue项目集成CanvasEditor实现Word在线编辑器

CanvasEditor实现Word在线编辑器 官网文档:https://hufe.club/canvas-editor-docs/guide/schema.html 源码地址:https://github.com/Hufe921/canvas-editor 前提声明: 由于CanvasEditor目前不支持vue、react 等框架开箱即用版,所以需要我们去Git下载源码,拿到其中两个主

React+TS前台项目实战(十七)-- 全局常用组件Dropdown封装

文章目录 前言Dropdown组件1. 功能分析2. 代码+详细注释3. 使用方式4. 效果展示 总结 前言 今天这篇主要讲全局Dropdown组件封装,可根据UI设计师要求自定义修改。 Dropdown组件 1. 功能分析 (1)通过position属性,可以控制下拉选项的位置 (2)通过传入width属性, 可以自定义下拉选项的宽度 (3)通过传入classN

人工智能机器学习算法总结神经网络算法(前向及反向传播)

1.定义,意义和优缺点 定义: 神经网络算法是一种模仿人类大脑神经元之间连接方式的机器学习算法。通过多层神经元的组合和激活函数的非线性转换,神经网络能够学习数据的特征和模式,实现对复杂数据的建模和预测。(我们可以借助人类的神经元模型来更好的帮助我们理解该算法的本质,不过这里需要说明的是,虽然名字是神经网络,并且结构等等也是借鉴了神经网络,但其原型以及算法本质上还和生物层面的神经网络运行原理存在

Java注解详细总结

什么是注解?         Java注解是代码中的特殊标记,比如@Override、@Test等,作用是:让其他程序根据注解信息决定怎么执行该程序。         注解不光可以用在方法上,还可以用在类上、变量上、构造器上等位置。 自定义注解  现在我们自定义一个MyTest注解 public @interface MyTest{String aaa();boolean bbb()

tensorboard-----summary用法总结

Tensorflow学习笔记——Summary用法         最近在研究tensorflow自带的例程speech_command,顺便学习tensorflow的一些基本用法。 其中tensorboard 作为一款可视化神器,可以说是学习tensorflow时模型训练以及参数可视化的法宝。 而在训练过程中,主要用到了tf.summary()的各类方法,能够保存训练过程以及参数分布图并在

vue3项目将所有访问后端springboot的接口统一管理带跨域

vue3项目将所有访问后端springboot的接口统一管理带跨域 一、前言1.安装Axios2.创建Axios实例3.创建API服务文件4.在组件中使用API服务 二、跨域三、总结 一、前言 在Vue 3项目中,统一管理所有访问后端Spring Boot接口的最佳实践是创建一个专门的API服务层。这可以让你的代码更加模块化、可维护和集中管理。你可以使用Axios库作为HTT