栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

【尚硅谷

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

【尚硅谷

javaweb属实是比蓝桥杯好玩,算法都不学,话说,明天就要转线下上课了來

在这个阶段,我们需要完成3个模块、用户模块、购物车模块 、订单模块

珞不许开摆目录

珞1、用户模块

1.1、登陆--显示用户名1.2、登出-注销用户1.3、表单重复提交-验证码1.4、使用谷歌 kaptcha 图片验证1.5、用户点击,替换验证码 珞2、购物车模块

2.1、购物车模型的创建2.2、购物车方法的实现和测试2.3、添加商品到购物车2.4、购物车的商品数据展示2.5、删除购物车的商品项2.6、清空购物车2.7、修改购物车商品的数量2.8、首页购物车数据显示 珞3、订单模块

3.1、创建数据库3.2、编写order和orderItem3.3、Dao层的编写和测试3.4、Service层的编写和测试3.5、结账功能实现3.6、关于结账功能小bug的修改

珞1、用户模块 1.1、登陆–显示用户名

我们找到登录的Servlet,src/main/java/com/flzj/web/UserServlet.java 在请求转发之前,把loginuser 存到Session域中,request.getSession().setAttribute("user",loginUser )

public class UserServlet extends baseServlet {

    private UserService userService = new UserServiceImpl();

    protected void login(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //        1、获取请求的参数
        String username = request.getParameter("username");
        String password = request.getParameter("password");
        System.out.println("接收到用户的账为"+username+"t"+password);
        //        2、调用XxxService. xxx()处理业务
        //        userService. login(登录
        User loginUser = userService.login(new User(null, username, password, null));
        //                3、根据login()方法返回结果判断登录是否成功
        if(!(loginUser == null)) {
            //                成功
            //                跳到成功页面login_ success. html
            // 保存用户登入的信息到Session域中
            request.getSession().setAttribute("user",loginUser);
            System.out.println(username + " 登入成功");
            request.getRequestDispatcher("/pages/user/login_success.jsp").forward(request,response);
        }else {
            // 失败
            ...
        }

在src/main/webapp/pages/common/login_success_menu.jsp,我们修改展示出来的效果

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
欢迎${sessionScope.user.username}光临尚硅谷书城 我的订单 注销   返回

同时首页也需要更改,我们登入以后,一般的网站首页,没有 登入 | 注册 这一选项,效果如下图

我们需要来到src/main/webapp/pages/client/index.jsp ,进行一整猛改


1.2、登出-注销用户

1、销毁Session中用户登入的信息

2、重定向到首页(或登入界面)

又回到,我们的src/main/java/com/flzj/web/UserServlet.java,这次,我们完善logout()方法

protected void logout(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    //        1、销毁Session中用户登入的信息
    request.getSession().invalidate();
    //        2、重定向到首页(或登入界面)
    response.sendRedirect(request.getContextPath());
}

同时在src/main/webapp/pages/common/login_success_menu.jsp 和 src/main/webapp/pages/client/index.jsp 的

注销
1.3、表单重复提交-验证码

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

一、提交完表单。服务器使用请求转来进行页面跳转。这个时候,用户按下功能键F5,就会发起最后一次的请求。造成表单重复提交问题。

解决方法:使用重定向来进行跳转

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

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

这时候,家人们就会问了,二、三怎么解决,我们可以通过验证码,来解决,下面是图解

这里我们用谷歌 kaptcha 图片验证

1.4、使用谷歌 kaptcha 图片验证

1、导包

kaptcha-2.3.2.jar

2、在web.xml中去配置用于生成验证码的Servlet程序


    KaptchaServlet
    com.google.code.kaptcha.servlet.KaptchaServlet


    KaptchaServlet
    /kaptcha.jpg

3、在表当中使用img标签去显示验证图片并使用

我们来到src/main/webapp/pages/user/regist.jsp ,在验证码部分,修改src属性,和小改下style属性,使验证码更好看




4、在服务器获取谷歌生成的验证码,和客户端发来的验证码进行比较

protected void regist(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    // 获取Session中的验证码
    String token = (String)request.getSession().getAttribute(KAPTCHA_SESSION_KEY);
    // 删除Session中的验证码
    request.getSession().removeAttribute(KAPTCHA_SESSION_KEY);

    //  1获取请求的参数
    ...
        // 2对验证码进行判断
        if(token != null && token.equals(code)) {
            //              正确

            //        3、检查用户名是否可用
            if(!userService.existsUsername(username)) {
                //                可用
                //        调用Sservice保存到数据库
                //userService.registUser(new User(null,username,password,email));
                //        跳到注册成功末面regist_success.jsp
               request.getRequestDispatcher("/pages/user/regist_success.jsp").forward(request,response);
// ...

效果

1.5、用户点击,替换验证码

在src/main/webapp/pages/user/regist.jsp下,给图片一个class,并给它绑定上单击事件


【尚硅谷
$("#code_img").click(function (){
    // 在事件响应的function函数中有一个this对象。这个this对象,是当前正在响应事件的dom对象
    // src属性表示验证码的img标签的 图片路径 它可读可写
    this.src = "${basePath}kaptcha.jpg?d=" + new Date();
});

这时候,好奇的家人们,会问了,为什么要加new Date()这个时间戳呢,我们是为了解决浏览器缓存,导致点击图片不更换验证码的事情发生,如下图所示

珞2、购物车模块

对购物车模块进行分析


这里我们使用Session版本,来实现购物车

2.1、购物车模型的创建

购物车的商品项

public class CartItem {
    private Integer id;
    private String name;
    private Integer count;
    private BigDecimal price;
    private BigDecimal totalPrice;
    // construcet、getXxx、setXxx、toString 省略
}

购物车对象

public class Cart {
    private Integer totalCount;
    private BigDecimal totalPrice;
    private List items = new ArrayList();
     // getXxx、setXxx、toString 省略
}
2.2、购物车方法的实现和测试

实现

private Map items = new linkedHashMap();

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()))); // 更新总金额
    }
}


public void deleteItem(Integer id){
    items.remove(id);
}


public void clear(){
    items.clear();
}


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()))); // 更新总金额
    }
}

我们会发现,之前写的private List items = new ArrayList();,不方便维护,所以我们改成Map

测试

CTRL + SHIFT + T 熟练了嗷

@Test
public void addItem() {
    Cart cart = new Cart();
    cart.addItem(new CartItem(1,"书本1",1,new BigDecimal(100),new BigDecimal(100)));
    cart.addItem(new CartItem(1,"书本1",1,new BigDecimal(100),new BigDecimal(100)));
    cart.addItem(new CartItem(2,"书本2",1,new BigDecimal(100),new BigDecimal(100)));
    System.out.println(cart);
}
@Test
public void deleteItem() {
    Cart cart = new Cart();
    cart.addItem(new CartItem(1,"书本1",1,new BigDecimal(100),new BigDecimal(100)));
    cart.addItem(new CartItem(1,"书本1",1,new BigDecimal(100),new BigDecimal(100)));
    cart.addItem(new CartItem(2,"书本2",1,new BigDecimal(100),new BigDecimal(100)));
    cart.deleteItem(1);
    System.out.println(cart);
}
@Test
public void clear() {
    Cart cart = new Cart();
    cart.addItem(new CartItem(1,"书本1",1,new BigDecimal(100),new BigDecimal(100)));
    cart.addItem(new CartItem(1,"书本1",1,new BigDecimal(100),new BigDecimal(100)));
    cart.addItem(new CartItem(2,"书本2",1,new BigDecimal(100),new BigDecimal(100)));
    cart.clear();
    System.out.println(cart);
}

@Test
public void updateCount() {
    Cart cart = new Cart();
    cart.addItem(new CartItem(1,"书本1",1,new BigDecimal(100),new BigDecimal(100)));
    cart.addItem(new CartItem(1,"书本1",1,new BigDecimal(100),new BigDecimal(100)));
    cart.updateCount(1,10);
    System.out.println(cart);
}

这里经过测试,我们发现,购物车对象(Cart.java )里的setTotalCount 和 setTotalPrice 不能存在,并且我们要对get方法进行修改,因此上面类的字段,totalCount 和 totalPrice, 可以变成局部变量

public Integer getTotalCount() {
    Integer totalCount = 0;
    for(Map.Entry entry : items.entrySet()){
        totalCount += entry.getValue().getCount();
    }
    return totalCount;
}
public BigDecimal getTotalPrice() {
    BigDecimal totalPrice = new BigDecimal(0);
    for(Map.Entry entry : items.entrySet()){
        totalPrice = totalPrice.add(entry.getValue().getTotalPrice());
    }
    return totalPrice;
}
2.3、添加商品到购物车

编写CartServlet 完成 addItem() 方法 ,这里请求重定向,有一个细节,请求头,有一个参数Referer,是浏览器搜索栏的地址 ,这样就可以让我们每次添加商品,跳转的页面,是当前的页面

protected void addItem(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    //     System.out.println("商品编号" + req.getParameter("id"));
    // 获取请求的商品编号
    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);
    }
    // 重定向回原来商品所在列表页面
    resp.sendRedirect(req.getHeader("Referer"));
}

    CartServlet
    com.flzj.web.CartServlet


    CartServlet
    /cartServlet

给加入购物车按钮,绑定单击事件



2.4、购物车的商品数据展示

我们先来到src/main/webapp/pages/cart/cart.jsp,小小修改下,循环读取Session域中的商品项,判断否为空,展示不同的页面效果

<%--商品为空--%> <%--商品非空--%>
商品名称 数量 单价 金额 操作
当前购物车为空!,快去浏览商品吧>
${entry.value.name} ${entry.value.count} ${entry.value.price} ${entry.value.totalPrice} 删除
<%--商品非空--%>
购物车中共有${sessionScope.cart.totalCount}件商品 总金额${sessionScope.cart.totalPrice}元 清空购物车 去结账
2.5、删除购物车的商品项

src/main/webapp/pages/cart/cart.jsp , 我们对删除的a标签,链接跳转到CartServlet执行deleteItem()方法,需要传商品的ID,同时添加提醒

删除				
	

deleteItem()方法

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"));
    }
}
2.6、清空购物车

这里,我们又要在src/main/webapp/pages/cart/cart.jsp下,就行修改,给清空购物车对应的标签,加上href和id,方便调用CartServlet的clear()方法和清空提醒

清空购物车
// 给【清空】添加单击事件
$("#clearCart").click(function (){
    return /confirm/i("你确定要,清空购物车吗?")
})

CartServlet的clear()方法

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"));
    }
}
2.7、修改购物车商品的数量

图解

src/main/webapp/pages/cart/cart.jsp ,添加个输入框,并给输入框添加一个onchange事件


    

// 给输入框绑定onchange事件
$(".updateCount").change(function (){
    // 获取商品名和id
    var name = $(this).parent().parent().find("td:first").text();
    var id = $(this).attr('bookId');
    // 获取商品数量
    var count = this.value;
    if(/confirm/i("你确定要将【"+ name +"】商品,修改数量为:" + count + "吗?")){
        // 发起请求。服务器保存修改
        location.href = "http://localhost:8080/book/cartServlet?action=updateItem&id="+id+"&count="+count;
    }else{
        // defaultValue属性是表单项Dom对象的属性。它表示默认的value属性值
        this.value = this.defaultValue;
    }
});

updateCount()方法

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 = (Cart) req.getSession().getAttribute("cart");
    if(cart != null){
        // 修改商品数量
        cart.updateCount(id,count);
        // 重定向回原来购物车展示页面
        resp.sendRedirect(req.getHeader("Referer"));
    }
}
2.8、首页购物车数据显示

我们修改CartServlet的addItem() 方法,往seesion 域中存储最后添加的书

req.getSession().setAttribute("lastName",cartItem.getName());

然后在首页中显示

<%-- 购物车为空 --%>
当前购物车为空
<%-- 购物车非空 --%> 您的购物车中有${sessionScope.cart.totalCount}件商品
您刚刚将${sessionScope.lastName}加入到了购物车中
>
珞3、订单模块

3.1、创建数据库
CREATE TABLE t_order(
    `order_id` VARCHAR(50) PRIMARY KEY,
    `create_time` DATETIME,
    `price` DECIMAL(11,2),
    `status` INT,
    `user_id` INT,
    FOREIGN KEY (`user_id`) REFERENCES t_user(`id`)
);

CREATE TABLE t_order_item(
    `id` INT PRIMARY KEY AUTO_INCREMENT,
    `name` VARCHAR(100),
    `count` INT,
    `price` DECIMAL(11,2),
    `total_price` DECIMAL(11,2),
    `order_id` VARCHAR(50),
    FOREIGN KEY(`order_id`) REFERENCES t_order(`order_id`)
);
3.2、编写order和orderItem
public class Order {
    private String orderId;
    private Date createTime;
    private BigDecimal price;
    // 0未发货,1已发货,2已签收
    private Integer status = 0;
    private Integer userId;
    // construct、getXxx、setXxx、toStirng 省略
}
public class OrderItem {
    private Integer id;
    private String name;
    private Integer count;
    private BigDecimal price;
    private BigDecimal totalPrice;
    private String orderId;
    // construct、getXxx、setXxx、toStirng 省略
}
3.3、Dao层的编写和测试

这里我们主要完成saveOrder(Order) 方法 和 saveOrderItem(OrderItem) 方法

编写

oderDao

public interface OrderDao {
    public int saveOrder(Order order);
}

orderDaoImpl

public class OrderDaoImpl extends baseDao implements OrderDao {
    @Override
    public int saveOrder(Order order) {
        String sql = "insert into t_order(`order_id`,`create_time`,`price`,`status`,`user_id`) values(?,?,?,?,?)";
        return update(sql,order.getOrderId(),order.getCreateTime(),order.getPrice(),order.getStatus(),order.getUserId());
    }
}

orderItem

public interface OrderItemDao {
    public int saveOrderItem(OrderItem orderItem);
}

orderItemImpl

public class OrderItemDaoImpl extends baseDao implements OrderItemDao {
    @Override
    public int saveOrderItem(OrderItem orderItem) {
        String sql = "insert into t_order_item(`name`,`count`,`price`,`total_price`,`order_id`) values(?,?,?,?,?)";
        return update(sql,orderItem.getName(),orderItem.getCount(),orderItem.getPrice(),orderItem.getTotalPrice(),orderItem.getOrderId());
    }
}

测试

CTRL + SHIFT + T

public class OrderDaoTest {
    OrderDao orderDao = new OrderDaoImpl();
    @Test
    public void saveOrder() {
        orderDao.saveOrder(new Order("1",new Date(),new BigDecimal(100),0,1));
    }
}
public class OrderItemDaoTest {
    OrderItemDao orderItemDao = new OrderItemDaoImpl();
    @Test
    public void saveOrderItem() {
        orderItemDao.saveOrderItem(new OrderItem(null,"java速通",1,new BigDecimal(100),new BigDecimal(100),"1"));
    }
}
3.4、Service层的编写和测试

这里我们只要实现createOrder(Cart,UserId)

编写

OrderService

public interface OrderService {
    public String createOrder(Cart cart,Integer userId);
}

OrderServiceImpl

public class OrderServiceImpl implements OrderService {
    private OrderDao orderDao = new OrderDaoImpl();
    private OrderItemDao orderItemDao = new OrderItemDaoImpl();
    @Override
    public String createOrder(Cart cart, Integer userId) {
        // 订单号 === 唯一性
        String orderId = System.currentTimeMillis()+""+ userId;
        // 创建一个订单对象
        Order order = new Order(orderId,new Date(),cart.getTotalPrice(),0,userId);
        // 保存订单
        orderDao.saveOrder(order);

        // 遍历购物车中每一个商品项转换成为订单项保存到数据库
        for(Map.Entryentry : cart.getItems().entrySet()){
            // 获取每一个购物车中的商品项
            CartItem cartItem = entry.getValue();
            // 转换为每一个订单项
            OrderItem orderItem = new OrderItem(null,cartItem.getName(),cartItem.getCount(),cartItem.getPrice(),cartItem.getTotalPrice(),orderId);
            // 保存订单到数据库
            orderItemDao.saveOrderItem(orderItem);
        }
        // 清空购物车
        cart.clear();

        return orderId;
    }
}

测试

@Test
public void createOrder() {
    Cart cart = new Cart();
    cart.addItem(new CartItem(1,"书本1",1,new BigDecimal(100),new BigDecimal(100)));
    cart.addItem(new CartItem(1,"书本1",1,new BigDecimal(100),new BigDecimal(100)));
    cart.addItem(new CartItem(2,"书本2",1,new BigDecimal(100),new BigDecimal(100)));

    OrderService orderService = new OrderServiceImpl();
    System.out.println("订单号是" + orderService.createOrder(cart,1));

}
3.5、结账功能实现

OrderServlet实现createOrder()方法

public class OrderServlet extends baseServlet {
    OrderService orderService = new OrderServiceImpl();
    
    protected void createOrder(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        // 先获取Cart购物车对象
        Cart cart = (Cart) request.getSession().getAttribute("cart");

        // 获取loginUser对象
        User loginUser = (User) request.getSession().getAttribute("user");
        // 如果还没有登入,就跳转到登入页面
        if(loginUser == null){
            request.getRequestDispatcher("/pages/user/login.jsp").forward(request,response);
            return;
        }
        // 获取UserId
        Integer userId = loginUser.getId();
        

        
        // 调用OrderService.createOrder(Cart,UserId) 生成订单
        String orderId = orderService.createOrder(cart,userId);

        request.setAttribute("orderId",orderId);
        // 请求转发到/pages/cart/checkout.jsp
        request.getRequestDispatcher("/pages/cart/checkout.jsp").forward(request,response);
    }
}


    OrderServlet
    com.flzj.web.OrderServlet


    OrderServlet
    /orderServlet

来到src/main/webapp/pages/cart/checkout.jsp修改,生成的订单号

你的订单已结算,订单号为${requestScope.orderId}

在src/main/webapp/pages/cart/cart.jsp使得跳转调用createOrder()方法

去结账
3.6、关于结账功能小bug的修改

为了防止订单重复提交

我们改用请求重定向,来到 com/flzj/web/OrderServlet.java ,同时存在request域的值也要改成session域

//        request.setAttribute("orderId",orderId);
//  request.getRequestDispatcher("/pages/cart/checkout.jsp").forward(request,response);
// 修改为
request.getSession().setAttribute("orderId",orderId);
response.sendRedirect(request.getContextPath() + "/pages/cart/checkout.jsp");
    

同时在src/main/webapp/pages/cart/checkout.jsp 的取值,也要改成从session域中取

你的订单已结算,订单号为${sessionScope.orderId}

结算导致库存和销量变化

src/main/java/com/flzj/service/impl/OrderServiceImpl.java 在createOrder()方法,加上变化

private BookDao bookDao = new BookDaoImpl();
...
            // 修改库存和商品
            Book book = bookDao.queryBookById(cartItem.getId());
            book.setSales(book.getSales() + cartItem.getCount() );
            book.setStock(book.getStock() - cartItem.getCount() );
            bookDao.updateBook(book);
...

蓝桥杯都不学,算法都不学

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/754049.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号