Javaweb-书城项目

第一阶段 表单验证

  1. 新建一个模块

  1. 把书城的静态资源拷贝到工程下

验证用户名里输入的内容
  1. 获取输入框内容

  1. 创建正则表达式对象

  1. 使用test验证

  1. 提示用户结果

第二阶段——用户注册和登录

JavaEE项目的三层架构

web层 com.tjq(我的名字缩写qwq).web/servlet/controller

service层 com.tjq.serivce service接口包类

com.tjq.service.impl service接口实现类

dao持久层 dao Dao接口包

dao.impl Dao接口实现类

实体Bean对象 com.tjq.pojo/entity/domain/bean JavaBean类

测试包 com.tjq.test.junit

工具类 com.tjq.utils

  1. 创建数据库和t_user表

CREATE TABLE t_user(

`id` int PRIMARY KEY auto_increment,

`username` VARCHAR(10) NOT NULL UNIQUE,

`password` VARCHAR(32) NOT NULL,

`email` VARCHAR(200)

);

INSERT INTO t_user (`username`,`password`,`email`) VALUES ('admin','admin','admin@tjq.com');

SELECT * FROM t_user

  1. 创建数据库对应的user类

  1. 编写Dao持久层

  1. 编写BaseDao

  1. 编写UserDao

  1. 编写UserService和测试

需求1:用户注册

需求如下:

  1. 访问注册页面

  1. 填写注册信息,提交给服务器

  1. 服务器应该保存用户

  1. 当用户已经存在-提示用户注册失败,用户已存在

  1. 当用户不存在时,注册成功

web阶段使用:base+相对

框架之后:绝对路径

需求2:用户登录

第三阶段

a)页面JSP动态化

b)抽取页面中相同内容

动态base值

在Servlet中setAttribute,然后在jsp中<%=%>

BaseServlet的抽取

在实际的项目开发中,一个模块,一般只使用一个Servlet程序

代码优化:

优化一:合并LoginServlet和RegistServlet

优化二:使用反射优化大量else if

String action = request.getParameter("action");

System.out.println(action);

try {

Method method = this.getClass().getDeclaredMethod(action, HttpServletRequest.class, HttpServletResponse.class);

method.invoke(this, request, response);

} catch (Exception e) {

e.printStackTrace();

}

优化三:抽取BaseServlet程序

数据的抽取和BeanUtils的使用

BeanUtils工具类,可以一次性的把所有请求的参数注入到JavaBean中

BeanUtils不是官方类,第三方,需要导包

1、导入需要的包

commons-beanutils-1.8.0.jar

commons-logging-1.1.1.jar

2、使用BeanUtils类方法注入

底层:注入的核心是User类的写方法set,通过反射赋值,所以名称必须相同

把Map中的值注入到对应的JavaBean属性中,适用性更强使用更加灵活

第四阶段

EL表达式错误回显

第五阶段

MVC概念

MVC全称:Model 模型、View 视图、Controller 控制器

MVC最早出现在JavaEE三层中的Web层,他可以有效知道Web层的代码如何进行有效分离,单独工作

View视图:只负责数据和界面的显示

Controller控制器:只负责接受请求

Model模型

MVC是一种思想
1.图书模块
  1. 编写图书模块的数据库表

  1. 编写图书模块的JavaBean

  1. 编写图书模块的Dao和测试Dao

  1. 编写图书模块的Service和测试Service

  1. 编写图书模块的Web层和页面联调测试

图书列表功能实现

点击——访问BookServlet(地址/manager/bookServlet?action=list)

设置Attribute把queryBooks传过去,重定向页面

protected void list(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

List<Book> books = bookDao.queryBooks();

request.setAttribute("books", books);

request.getRequestDispatcher("/pages/manager/book_manager.jsp").forward(request, response);

}

<c:forEach items="${requestScope.books}" var="book">

<tr>

<td>${book.name}</td>

<td>${book.price}</td>

<td>${book.author}</td>

<td>${book.sales}</td>

<td>${book.stock}</td>

<td><a href="pages/manager/book_edit.jsp">修改</a></td>

<td><a href="#">删除</a></td>

</tr>

</c:forEach>

前后台的简单介绍
添加图书功能实现

重点:request.getParameter()名字要和html里面的name一样,因为原理

bug:表单重复提交

所以不能用请求转发:getRequestDispatcher

用重定向:response.sendRedirect

删除图书功能实现
修改图书

图书分页

Page类:

pageNo 当前页码

pageTotal 总页码

pageTotalCount 总记录数

pageSize 每页显示数量

items 当前页数据

pageNo 当前页码是由客户端进行传递

pageSize 每页显示数量由两种因素决定

一、客户端进行传递

二、由页面布局决定

pageTotalCount 总记录数可以由sql语句求得

pageTotal 总页码可以由总记录数/每页数量得到

注:总记录数%每页数量>0,则 总页码+1

items 是当前页数据,也是可以由sql语句求得

sql语句是:select * form 表名 limit begin, pageSize

begin 可以由公式求得:(pageNo-1)*pageSize

结构图

显示五个连续的页码,当前页码在中间

情况一:总页码小于等于5

情况二:总页码大于5

小情况1:当前页码为前三个:1,2,3的情况,页码范围是 :1-5

小情况2:当前页码为最后三个,页码范围:总页码减4-总页码

小情况3:4,5,6,7,页码范围减2-当前页码加2

注意事项
  1. 数据有效边境检查

  1. 修改,添加图书后能直接跳到所操作的图书的当前页,这里直接用的是pageNo,并在add和update里面改跳转地址

前台分页的初步实现

准备一个pages下的client目录,复制index.jsp到client目录下

web下的index只干请求转发

分页条的抽取(优化重点)

跟common里的一样

价格区间搜索并分页
查询价格回显

判断req.getParameter min是不是null,StringBuffer添加参数,避免回显默认值

第六阶段

1.显示登录的用户信息

<c:if test="${empty sessionScope.user}">

<a href="pages/user/login.jsp">登录</a> |

<a href="pages/user/regist.jsp">注册</a>

</c:if>

<c:if test="${not empty sessionScope.user}">

<span>欢迎<span class="um_span">${sessionScope.user}</span>光临尚硅谷书城</span>

<a href="pages/order/order.jsp">我的订单</a>

<a href="index.jsp">注销</a>

</c:if>

2.登出——注销用户
  1. 销毁Session中用户登录的信息(或者销毁Session)

  1. 重定向到首页

3.表单重复提交之——验证码

表单重复提交有三种常见的情况:

一、提交完表单,服务器使用请求转发来进行页面跳转。这个时候,用户按下f5,就会发起最后一次请求,造成表单重复提交问题。解决方法:使用重定向来进行跳转

二、用户正常提交服务器,但是由于网络延迟等原因,迟迟未收到服务器的响应,这个时候,用户以为提交失败,就会着急,然后多点了几次提交操作,也会造成表单重复提交

三、用户正常提交服务器,服务器也没有延迟,但是提交完成后,用户回退浏览器,重新提交。也会造成表单重复提交。

验证码底层原理
4.谷歌kaptcha图片验证码的使用
  1. 导入谷歌验证码的jar包

  1. 在web.xml中去配置用于验证码的Servlet程序

  1. 在表单中使用img标签显示验证码并使用它

用户名:<input type="text" name="username"><br>

密码:<input type="password" name="password"><br>

<img src="http://localhost:8080/temp/kaptcha.jpg" alt="" style="width: 100px;height: 28px"><br>

<input type="submit" value="登录">

  1. 在服务器获取谷歌生成的验证码和客户端发送来的验证码比较

5.验证码的切换

给img标签绑定一个单机事件,this.src后面加上一个时间戳来保证每次点击发送的请求不一样。(原理,浏览器缓存)

6.购物车
6.1 购物车模块的分析
6.2 添加商品到购物车

如何解决在第二页添加购物车返回的却是第一页的问题:

使用请求头中的Referer,可以把地址栏中的地址发送到服务器,进而实现跳转到原来的页面

6.3 购物车的展示

使用的jsp中的循环语句

<c:forEach items="${sessionScope.cart.items}" var="entry">

<tr>

<td>${entry.value.name}</td>

<td>${entry.value.count}</td>

<td>${entry.value.price}</td>

<td>${entry.value.totalPrice}</td>

<td><a href="#">删除</a></td>

</tr>

</c:forEach>

6.4修改购物车商品数量

使用js

$(".updateCount").change(function () {

//给输入框绑定失去焦点事件

var name = $(this).parent().parent().find("td:first").text();

var count = this.value;

var id = $(this).attr("bookId");

if (confirm("你确定要将【" + name + "】的数量修改为:" + count + "吗?")) {

location.href = "http://localhost:8080/book/cartServlet?action=updateCount&count=" + count + "&id=" + id;

} else {

this.value = this.defaultValue;

}

});

7.订单

7.1 订单模块的分析

订单功能:

  1. 生成订单

  1. 查询所有订单(管理员)

  1. 发货(管理员)

  1. 查看订单详情(管理员/用户)

  1. 查看我的订单(用户)

  1. 签收订单(用户)

7.2 订单模块

第八阶段

1.使用Filter过滤器拦截/pages/manager所有内容,实现权限检查

<filter>

<filter-name>ManagerFilter</filter-name>

<filter-class>com.tjq.filter.ManagerFilter</filter-class>

</filter>

<filter-mapping>

<filter-name>ManagerFilter</filter-name>

<url-pattern>/pages/manager/*</url-pattern>

<url-pattern>/manager/bookServlet</url-pattern>

</filter-mapping>

2.ThreadLocald的使用

ThreadLocal的作用,可以解决多线程的数据安全问题

ThreadLocal它可以给当前线程关联一个数据(可以是普通变量,可以是对象,也可以是数组,集合)

ThreadLocal的特点:

  1. ThreadLocal可以为当前线程关联一个数据(它可以像Map一样存取数据,key为当前线程)

  1. 每一个ThreadLocal对象,只能为当前线程关联一个数据,如果要为当前线程关联多个数据,就需要使用多个ThreadLocal对象实例

  1. 每个ThreadLoca对象实例定义的时候,一般都是static类型

  1. ThreadLocal中保存数据,在线程销毁后。会由JVM虚拟机自动释放。

2.使用Filter和ThreadLocal组合管理事务
3.使用Filter过滤器统一给所有的Service方法都加上try-catch。来实现统一的事务管理

第九模块

通过ajax验证用户名可用不可用

http://localhost:8080/book/userServlet?action=ajaxExistsUsername&username=tjq

http://localhost:8080/book/userSerlvet?action=ajaxExistsUsername&username=tjq

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一只桃子z

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值