书城项目第六阶段
项目第六阶段
1、登陆---显示用户名
UserServlet 程序中保存用户登录的信息

修改 login_succuess_menu.jsp

还要修改首页 index.jsp 页面的菜单 :

2、登出---注销用户
1、销毁 Session 中用户登录的信息(或者销毁 Session)
2、重定向到首页(或登录页面)。
UserServlet 程序中添加 logout 方法
public class UserServlet extends BaseServlet {
private UserService userService = new UserServiceImpl();
protected void logout(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//1、销毁 Session 中用户登录的信息(或者销毁 Session)
req.getSession().invalidate();
//2、重定向到首页(或登录页面)。
resp.sendRedirect(req.getContextPath());
}
/**
* 处理登录的功能
* @param req
* @param resp
* @throws ServletException
* @throws IOException
*/
protected void login(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 1、获取请求的参数
String username = req.getParameter("username");
String password = req.getParameter("password");
// 调用 userService.login()登录处理业务
User loginUser = userService.login(new User(null,username,password,null));
// 如果等于 null,说明登录 失败!
if (loginUser==null){
//把错误信息,和回显的表单项信息,保存到Request域中
req.setAttribute("msg","用户名或密码错误");
req.setAttribute("username",username);
// 跳回登录页面
req.getRequestDispatcher("/pages/user/login.jsp").forward(req,resp);
}else{
// 登录 成功
//保存用户的信息到session域中
req.getSession().setAttribute("user",loginUser);
// 跳到成功页面 login_success.jsp
req.getRequestDispatcher("/pages/user/login_success.jsp").forward(req,resp);
}
}
/**
* 处理注册的功能
* @param req
* @param resp
* @throws ServletException
* @throws IOException
*/
protected void regist(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 1、获取请求的参数
String username = req.getParameter("username");
String password = req.getParameter("password");
String email = req.getParameter("email");
String code = req.getParameter("code");
User user = WebUtils.copyParamToBean(req.getParameterMap(),new User());
// 2、检查 验证码是否正确 === 写死,要求验证码为:abcde
if ("abcde".equalsIgnoreCase(code)) {
// 3、检查 用户名是否可用
if (userService.existsUsername(username)) {
//把错误信息,和回显的表单项信息,保存到Request域中
req.setAttribute("msg","用户名已存在!");
req.setAttribute("username",username);
req.setAttribute("email",email);
System.out.println("用户名[" + username + "]已存在!");
// 跳回注册页面
req.getRequestDispatcher("/pages/user/regist.jsp").forward(req, resp);
} else {
// 可用
// 调用 Sservice 保存到数据库
userService.registUser(new User(null, username, password, email));
// 跳到注册成功页面regist_success.html
req.getRequestDispatcher("/pages/user/regist_success.jsp").forward(req, resp);
}
} else {
//把错误信息,和回显的表单项信息,保存到Request域中
req.setAttribute("msg","验证码错误!");
req.setAttribute("username",username);
req.setAttribute("email",email);
System.out.println("验证码[" + code + "]错误");
req.getRequestDispatcher("/pages/user/regist.jsp").forward(req, resp);
}
}
}
修改【注销】的菜单地址


3、表单重复提交之-----验证码
表单重复提交有三种常见的情况:
一:提交完表单。服务器使用请求转来进行页面跳转。这个时候,用户按下功能键 F5,就会发起最后一次的请求。 造成表单重复提交问题。解决方法:使用重定向来进行跳转
二:用户正常提交服务器,但是由于网络延迟等原因,迟迟未收到服务器的响应,这个时候,用户以为提交失败,
就会着急,然后多点了几次提交操作,也会造成表单重复提交。
三:用户正常提交服务器。服务器也没有延迟,但是提交完成后,用户回退浏览器。重新提交。也会造成表单重复
提交。

4、谷歌 kaptcha 图片验证码的使用
谷歌验证码 kaptcha 使用步骤如下:
1、导入谷歌验证码的 jar 包
- kaptcha-2.3.2.jar
2、在 web.xml 中去配置用于生成验证码的 Servlet 程序(此Servlet为jar包中携带,配置即可)
<servlet>
<servlet-name>KaptchaServlet</servlet-name>
<servlet-class>com.google.code.kaptcha.servlet.KaptchaServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>KaptchaServlet</servlet-name>
<url-pattern>/kaptcha.jpg</url-pattern>
</servlet-mapping>
3、在表单中使用 img 标签去显示验证码图片并使用它,设置一下边框大小

4、在服务器获取谷歌生成的验证码和客户端发送过来的验证码比较使用。
修改UserServlet中的regist方法

public class UserServlet extends BaseServlet {
private UserService userService = new UserServiceImpl();
protected void logout(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//1、销毁 Session 中用户登录的信息(或者销毁 Session)
req.getSession().invalidate();
//2、重定向到首页(或登录页面)。
resp.sendRedirect(req.getContextPath());
}
/**
* 处理登录的功能
* @param req
* @param resp
* @throws ServletException
* @throws IOException
*/
protected void login(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 1、获取请求的参数
String username = req.getParameter("username");
String password = req.getParameter("password");
// 调用 userService.login()登录处理业务
User loginUser = userService.login(new User(null,username,password,null));
// 如果等于 null,说明登录 失败!
if (loginUser==null){
//把错误信息,和回显的表单项信息,保存到Request域中
req.setAttribute("msg","用户名或密码错误");
req.setAttribute("username",username);
// 跳回登录页面
req.getRequestDispatcher("/pages/user/login.jsp").forward(req,resp);
}else{
// 登录 成功
//保存用户的信息到session域中
req.getSession().setAttribute("user",loginUser);
// 跳到成功页面 login_success.jsp
req.getRequestDispatcher("/pages/user/login_success.jsp").forward(req,resp);
}
}
/**
* 处理注册的功能
* @param req
* @param resp
* @throws ServletException
* @throws IOException
*/
protected void regist(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 获取 Session 中的验证码
String token = (String) req.getSession().getAttribute(KAPTCHA_SESSION_KEY);
// 删除 Session 中的验证码
req.getSession().removeAttribute(KAPTCHA_SESSION_KEY);
// 1、获取请求的参数
String username = req.getParameter("username");
String password = req.getParameter("password");
String email = req.getParameter("email");
String code = req.getParameter("code");
User user = WebUtils.copyParamToBean(req.getParameterMap(),new User());
if (token!=null && token.equalsIgnoreCase(code)) {
// 3、检查 用户名是否可用
if (userService.existsUsername(username)) {
//把错误信息,和回显的表单项信息,保存到Request域中
req.setAttribute("msg","用户名已存在!");
req.setAttribute("username",username);
req.setAttribute("email",email);
System.out.println("用户名[" + username + "]已存在!");
// 跳回注册页面
req.getRequestDispatcher("/pages/user/regist.jsp").forward(req, resp);
} else {
// 可用
// 调用 Sservice 保存到数据库
userService.registUser(new User(null, username, password, email));
// 跳到注册成功页面regist_success.html
req.getRequestDispatcher("/pages/user/regist_success.jsp").forward(req, resp);
}
} else {
//把错误信息,和回显的表单项信息,保存到Request域中
req.setAttribute("msg","验证码错误!");
req.setAttribute("username",username);
req.setAttribute("email",email);
System.out.println("验证码[" + code + "]错误");
req.getRequestDispatcher("/pages/user/regist.jsp").forward(req, resp);
}
}
}
5、切换验证码:


// 给验证码的图片,绑定单击事件
$("#code_img").click(function () {
// 在事件响应的 function 函数中有一个 this 对象。这个 this 对象,是当前正在响应事件的 dom 对象
// src 属性表示验证码 img 标签的 图片路径。它可读,可写
this.src = "${basePath}kaptcha.jpg?d="+new Date();
});
5、购物车模块分析

6、购物车模型编写
/**
* 购物车商品项
*/
public class CartItem {
private Integer id;
private String name;
private Integer count;
private BigDecimal price;
private BigDecimal totalPrice;
/**
* 购物车对象
*/
public class Cart {
//private Integer totalCount;
// private BigDecimal totalPrice;
private Map<Integer,CartItem> items = new LinkedHashMap<Integer,CartItem>();
/**
* 添加商品项
* @param cartItem
*/
public void addItem(CartItem cartItem){
// 先查看购物车中是否已经添加过此商品,如果已添加,则数量累加,总金额更新,如果没有添加过,直接放到 集合中即可
CartItem item = items.get(cartItem.getId());
if (item==null){
// 之前没添加过此商品
items.put(cartItem.getId(),cartItem);
}else{
// 已经 添加过的情况
item.setCount(item.getCount()+1);// 数量 累加
item.setTotalPrice(item.getPrice().multiply(new BigDecimal(item.getCount())));//更新总金额
}
}
/**
* 删除商品项
* @param id
*/
public void deleteItem(Integer id){
items.remove(id);
}
/**
* 清空购物车
*/
public void clear(){
items.clear();
}
/**
* 修改商品数量
* @param id
* @param count
*/
public void updateCount(Integer id,Integer count){
// 先查看购物车中是否有此商品。如果有,修改商品数量,更新总金额
CartItem cartItem = items.get(id);
if (cartItem!=null){
cartItem.setCount(count);// 修改商品数量
cartItem.setTotalPrice(cartItem.getPrice().multiply(new BigDecimal(cartItem.getCount())));// 更新总金额
}
}
public Cart() {
}
public Integer getTotalCount() {
Integer totalCount = 0;
for (Map.Entry<Integer,CartItem>entry : items.entrySet()) {
totalCount += entry.getValue().getCount();
}
return totalCount;
}
public BigDecimal getTotalPrice() {
BigDecimal totalPrice = new BigDecimal(0);
for (Map.Entry<Integer,CartItem>entry : items.entrySet()) {
totalPrice = totalPrice.add(entry.getValue().getTotalPrice());
}
return totalPrice;
}
public Map<Integer, CartItem> getItems() {
return items;
}
public void setItems(Map<Integer, CartItem> items) {
this.items = items;
}
@Override
public String toString() {
return "Cart{" +
"totalCount=" + getTotalCount() +
", totalPrice=" + getTotalPrice() +
", items=" + items +
'}';
}
}
7、加入购物车功能的实现
CartServlet 程序中的代码:
public class CartServlet extends BaseServlet{
private BookService bookService = new BookServiceImpl();
protected void addItem(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 获取请求的参数 商品编号
int id = WebUtils.parseInt(req.getParameter("id"), 0);
// 调用 bookService.queryBookById(id):Book 得到图书的信息
Book book = bookService.queryBookById(id);
// 把图书信息,转换成为 CartItem 商品项
CartItem cartItem = new CartItem(book.getId(),book.getName(),1,book.getPrice(),book.getPrice());
// 调用 Cart.addItem(CartItem);添加商品项
Cart cart = (Cart) req.getSession().getAttribute("cart");
if (cart == null) {
cart = new Cart();
req.getSession().setAttribute("cart",cart);
}
cart.addItem(cartItem);
System.out.println(cart);
System.out.println("请求头 Referer 的值:" + req.getHeader("Referer"));
// 重定向回原来商品所在的地址页面
resp.sendRedirect(req.getHeader("Referer"));
}
}
index.jsp 页面 js 的代码:

<script type="text/javascript">
$(function () {
// 给加入购物车按钮绑定单击事件
$("button.addToCart").click(function () {
/**
* 在事件响应的 function 函数 中,有一个 this 对象,这个 this 对象,是当前正在响应事件的 dom 对象
* @type {jQuery}
*/
var bookId = $(this).attr("bookId");
location.href = "cartServlet?action=addItem&id=" + bookId;
});
});
</script>
图解说明,如何跳回添加商品的页面:

8、购物车的展示


9、删除购物车商品项
CartServlet 程序:
public class CartServlet extends BaseServlet{
private BookService bookService = new BookServiceImpl();
protected void deleteItem(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 获取商品编号
int id = WebUtils.parseInt(req.getParameter("id"), 0);
// 获取购物车对象
Cart cart = (Cart) req.getSession().getAttribute("cart");
if (cart!=null){
// 删除 了购物车商品项
cart.deleteItem(id);
// 重定向回原来购物车展示页面
resp.sendRedirect(req.getHeader("Referer"));
}
}
protected void addItem(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 获取请求的参数 商品编号
int id = WebUtils.parseInt(req.getParameter("id"), 0);
// 调用 bookService.queryBookById(id):Book 得到图书的信息
Book book = bookService.queryBookById(id);
// 把图书信息,转换成为 CartItem 商品项
CartItem cartItem = new CartItem(book.getId(),book.getName(),1,book.getPrice(),book.getPrice());
// 调用 Cart.addItem(CartItem);添加商品项
Cart cart = (Cart) req.getSession().getAttribute("cart");
if (cart == null) {
cart = new Cart();
req.getSession().setAttribute("cart",cart);
}
cart.addItem(cartItem);
System.out.println(cart);
System.out.println("请求头 Referer 的值:" + req.getHeader("Referer"));
// 重定向回原来商品所在的地址页面
resp.sendRedirect(req.getHeader("Referer"));
}
}
购物车/pages/cart/cart.jsp 页面的代码:

删除的确认提示操作:
<script type="text/javascript">
$(function () {
// 给 【删除】绑定单击事件
$("a.deleteItem").click(function () {
return confirm("你确定要删除【"+$(this).parent().parent().find("td:first").text()+"】吗?")
});
});
</script>
10、清空购物车
CartServlet 程序
public class CartServlet extends BaseServlet{
private BookService bookService = new BookServiceImpl();
protected void clear(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 获取购物车对象
Cart cart = (Cart) req.getSession().getAttribute("cart");
if (cart!=null){
// 清空购物车
cart.clear();
// 重定向回原来购物车展示页面
resp.sendRedirect(req.getHeader("Referer"));
}
}
protected void deleteItem(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 获取商品编号
int id = WebUtils.parseInt(req.getParameter("id"), 0);
// 获取购物车对象
Cart cart = (Cart) req.getSession().getAttribute("cart");
if (cart!=null){
// 删除 了购物车商品项
cart.deleteItem(id);
// 重定向回原来购物车展示页面
resp.sendRedirect(req.getHeader("Referer"));
}
}
protected void addItem(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 获取请求的参数 商品编号
int id = WebUtils.parseInt(req.getParameter("id"), 0);
// 调用 bookService.queryBookById(id):Book 得到图书的信息
Book book = bookService.queryBookById(id);
// 把图书信息,转换成为 CartItem 商品项
CartItem cartItem = new CartItem(book.getId(),book.getName(),1,book.getPrice(),book.getPrice());
// 调用 Cart.addItem(CartItem);添加商品项
Cart cart = (Cart) req.getSession().getAttribute("cart");
if (cart == null) {
cart = new Cart();
req.getSession().setAttribute("cart",cart);
}
cart.addItem(cartItem);
System.out.println(cart);
System.out.println("请求头 Referer 的值:" + req.getHeader("Referer"));
// 重定向回原来商品所在的地址页面
resp.sendRedirect(req.getHeader("Referer"));
}
}
cart.jsp 页面的内容

清空的确认提示操作:
$("#clearCart").click(function () {
return confirm("你确定要清空购物车吗?");
});
11、修改购物车商品数量
CartServlet 程序
public class CartServlet extends BaseServlet{
private BookService bookService = new BookServiceImpl();
protected void updateCount(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 获取请求的参数 商品编号 、商品数量
int id = WebUtils.parseInt(req.getParameter("id"), 0);
int count = WebUtils.parseInt(req.getParameter("count"), 1);
// 获取购物车对象
Cart cart = (Cart) req.getSession().getAttribute("cart");
if (cart!=null){
// 修改商品数量
cart.updateCount(id,count);
// 重定向回原来购物车展示页面
resp.sendRedirect(req.getHeader("Referer"));
}
}
protected void clear(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 获取购物车对象
Cart cart = (Cart) req.getSession().getAttribute("cart");
if (cart!=null){
// 清空购物车
cart.clear();
// 重定向回原来购物车展示页面
resp.sendRedirect(req.getHeader("Referer"));
}
}
protected void deleteItem(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 获取商品编号
int id = WebUtils.parseInt(req.getParameter("id"), 0);
// 获取购物车对象
Cart cart = (Cart) req.getSession().getAttribute("cart");
if (cart!=null){
// 删除 了购物车商品项
cart.deleteItem(id);
// 重定向回原来购物车展示页面
resp.sendRedirect(req.getHeader("Referer"));
}
}
protected void addItem(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 获取请求的参数 商品编号
int id = WebUtils.parseInt(req.getParameter("id"), 0);
// 调用 bookService.queryBookById(id):Book 得到图书的信息
Book book = bookService.queryBookById(id);
// 把图书信息,转换成为 CartItem 商品项
CartItem cartItem = new CartItem(book.getId(),book.getName(),1,book.getPrice(),book.getPrice());
// 调用 Cart.addItem(CartItem);添加商品项
Cart cart = (Cart) req.getSession().getAttribute("cart");
if (cart == null) {
cart = new Cart();
req.getSession().setAttribute("cart",cart);
}
cart.addItem(cartItem);
System.out.println(cart);
System.out.println("请求头 Referer 的值:" + req.getHeader("Referer"));
// 重定向回原来商品所在的地址页面
resp.sendRedirect(req.getHeader("Referer"));
}
}
修改 pages/cart/cart.jsp 购物车页面:

修改商品数量 js 代码:
// 给输入框绑定 onchange 内容发生改变事件
$(".updateCount").change(function () {
// 获取商品名称
var name = $(this).parent().parent().find("td:first").text();
var id = $(this).attr('bookId');
// 获取商品数量
var count = this.value;
if ( confirm("你确定要将【" + name + "】商品修改数量为:" + count + " 吗?") ) {
//发起请求。给服务器保存修改
location.href = "cartServlet?action=updateCount&count="+count+"&id="+id;
} else {
//defaultValue 属性是表单项 Dom 对象的属性。它表示默认的 value 属性值。
this.value = this.defaultValue;
}
});
12、首页,购物车数据回显
在添加商品到购物车的时候,保存最后一个添加的商品名称:

在 pages/client/index.jsp 页面中输出购物车信息:


浙公网安备 33010602011771号