天猫整站(简易版)SSM(十三)需要登录才能使用的功能

 

目录

一、加入购物车

1.1 效果

1.2 在产品页点击加入购物车

1.3 ForeController.addCart

二、查看购物车页面

2.1 界面效果

2.2 ForeController.cart()

2.3 cart.jsp

2.4 cartPage.jsp

三、登录状态拦截器

3.1 查看购物车页面的问题

3.2 解决思路

3.3 LoginInterceptor

3.4 springMVC.xml

3.5 参考

四、其他拦截器

4.1 搜索栏下的分类信息

4.2 跳转首页超链接

4.3 购物车中数量显示

4.4 新增拦截器

4.5 修改springMVC.xml


一、加入购物车

1.1 效果

在产品页面点击加入购物车的,除了得到像立即购买中在OrderItem表里插入一条数据外,把界面上的加入购物车按钮变成灰色并且不可点击

1.2 在产品页点击加入购物车

如果未登录,那么点击加入购物车会弹出登录窗口。登录之后,点击加入购物车,会使用ajax异步访问地址:

http://127.0.0.1:8080/tmall_ssm/foreaddCart?pid=264&num=4

 并带上了产品id 264和购买数量4

1.3 ForeController.addCart

上一步访问地址/foreaddCart导致ForeController.addCart()方法被调用
addCart()方法和立即购买中的 ForeController.buyone()步骤做的事情是一样的,区别在于返回不一样
1. 获取参数pid
2. 获取参数num
3. 根据pid获取产品对象p
4. 从session中获取用户对象user

接下来就是新增订单项OrderItem, 新增订单项要考虑两个情况
a. 如果已经存在这个产品对应的OrderItem,并且还没有生成订单,即还在购物车中。 那么就应该在对应的OrderItem基础上,调整数量
a.1 基于用户对象user,查询没有生成订单的订单项集合
a.2 遍历这个集合
a.3 如果产品是一样的话,就进行数量追加
a.4 获取这个订单项的 id

b. 如果不存在对应的OrderItem,那么就新增一个订单项OrderItem
b.1 生成新的订单项
b.2 设置数量,用户和产品
b.3 插入到数据库
b.4 获取这个订单项的 id

与ForeController.buyone()客户端跳转到结算页面不同的是, 最后返回字符串"success",表示添加成功

    @RequestMapping("foreaddCart")
    @ResponseBody
    public String addCart(@RequestParam("pid") int pid,@RequestParam("num") int num,HttpSession session){
        Product product =productService.get(pid);
        User user = (User) session.getAttribute("user");

        boolean found = false;
        List<OrderItem> orderItems = orderItemService.listByUser(user.getId());
        for (OrderItem orderItem : orderItems){
            if (orderItem.getPid().intValue() == product.getId().intValue()){
                orderItem.setNumber(orderItem.getNumber()+num);
                orderItemService.update(orderItem);
                found = true;
                break;
            }
        }

        if (!found){
            OrderItem orderItem = new OrderItem();
            orderItem.setUid(user.getId());
            orderItem.setNumber(num);
            orderItem.setPid(product.getId());
            orderItemService.add(orderItem);
        }
        return "success";
    }

二、查看购物车页面

2.1 界面效果

2.2 ForeController.cart()

访问地址/forecart导致ForeController.cart()方法被调用
1. 通过session获取当前用户
所以一定要登录才访问,否则拿不到用户对象,会报错
2. 获取为这个用户关联的订单项集合 ois
3. 把ois放在model中
4. 服务端跳转到cart.jsp

    @RequestMapping("forecart")
    public String cart(Model model,HttpSession session){
        User user = (User) session.getAttribute("user");
        List<OrderItem> orderItems = orderItemService.listByUser(user.getId());
        model.addAttribute("ois",orderItems);
        return "fore/cart";
    }

2.3 cart.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8" isELIgnored="false"%>
 
<%@include file="../include/fore/header.jsp"%>
<%@include file="../include/fore/top.jsp"%>
<%@include file="../include/fore/simpleSearch.jsp"%>
 
<%@include file="../include/fore/cart/cartPage.jsp"%>
<%@include file="../include/fore/footer.jsp"%>

2.4 cartPage.jsp

<%--
  Created by IntelliJ IDEA.
  User: 
  Date: 2018/9/29
  Time: 17:50
  To change this template use File | Settings | File Templates.
--%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
         pageEncoding="UTF-8" isELIgnored="false"%>

<script>
    var deleteOrderItem = false;
    var deleteOrderItemid = 0;
    $(function(){

        $("a.deleteOrderItem").click(function(){
            deleteOrderItem = false;
            var oiid = $(this).attr("oiid")
            deleteOrderItemid = oiid;
            $("#deleteConfirmModal").modal('show');
        });
        $("button.deleteConfirmButton").click(function(){
            deleteOrderItem = true;
            $("#deleteConfirmModal").modal('hide');
        });

        $('#deleteConfirmModal').on('hidden.bs.modal', function (e) {
            if(deleteOrderItem){
                var page="foredeleteOrderItem";
                $.post(
                    page,
                    {"oiid":deleteOrderItemid},
                    function(result){
                        if("success"===result){
                            $("tr.cartProductItemTR[oiid="+deleteOrderItemid+"]").hide();
                        }
                        else{
                            location.href="loginPage";
                        }
                    }
                );

            }
        })

        $("img.cartProductItemIfSelected").click(function(){
            var selectit = $(this).attr("selectit")
            if("selectit"===selectit){
                $(this).attr("src","${pageContext.request.contextPath}/img/site/cartNotSelected.png");
                $(this).attr("selectit","false")
                $(this).parents("tr.cartProductItemTR").css("background-color","#fff");
            }
            else{
                $(this).attr("src","${pageContext.request.contextPath}/img/site/cartSelected.png");
                $(this).attr("selectit","selectit")
                $(this).parents("tr.cartProductItemTR").css("background-color","#FFF8E1");
            }
            syncSelect();
            syncCreateOrderButton();
            calcCartSumPriceAndNumber();
        });
        $("img.selectAllItem").click(function(){
            var selectit = $(this).attr("selectit")
            if("selectit"===selectit){
                $("img.selectAllItem").attr("src","${pageContext.request.contextPath}/img/site/cartNotSelected.png");
                $("img.selectAllItem").attr("selectit","false")
                $(".cartProductItemIfSelected").each(function(){
                    $(this).attr("src","img/site/cartNotSelected.png");
                    $(this).attr("selectit","false");
                    $(this).parents("tr.cartProductItemTR").css("background-color","#fff");
                });
            }
            else{
                $("img.selectAllItem").attr("src","${pageContext.request.contextPath}/img/site/cartSelected.png");
                $("img.selectAllItem").attr("selectit","selectit")
                $(".cartProductItemIfSelected").each(function(){
                    $(this).attr("src","${pageContext.request.contextPath}/img/site/cartSelected.png");
                    $(this).attr("selectit","selectit");
                    $(this).parents("tr.cartProductItemTR").css("background-color","#FFF8E1");
                });
            }
            syncCreateOrderButton();
            calcCartSumPriceAndNumber();

        });

        $(".orderItemNumberSetting").keyup(function(){
            var pid=$(this).attr("pid");
            var stock= $("span.orderItemStock[pid="+pid+"]").text();
            var price= $("span.orderItemPromotePrice[pid="+pid+"]").text();

            var num= $(".orderItemNumberSetting[pid="+pid+"]").val();
            num = parseInt(num);
            if(isNaN(num))
                num= 1;
            if(num<=0)
                num = 1;
            if(num>stock)
                num = stock;

            syncPrice(pid,num,price);
        });

        $(".numberPlus").click(function(){

            var pid=$(this).attr("pid");
            var stock= $("span.orderItemStock[pid="+pid+"]").text();
            var price= $("span.orderItemPromotePrice[pid="+pid+"]").text();
            var num= $(".orderItemNumberSetting[pid="+pid+"]").val();

            num++;
            if(num>stock)
                num = stock;
            syncPrice(pid,num,price);
        });
        $(".numberMinus").click(function(){
            var pid=$(this).attr("pid");
            var stock= $("span.orderItemStock[pid="+pid+"]").text();
            var price= $("span.orderItemPromotePrice[pid="+pid+"]").text();

            var num= $(".orderItemNumberSetting[pid="+pid+"]").val();
            --num;
            if(num<=0)
                num=1;
            syncPrice(pid,num,price);
        });

        $("button.createOrderButton").click(function(){
            var params = "";
            $(".cartProductItemIfSelected").each(function(){
                if("selectit"===$(this).attr("selectit")){
                    var oiid = $(this).attr("oiid");
                    params += "&oiid="+oiid;
                }
            });
            params = params.substring(1);
            location.href="forebuy?"+params;
        });

    })

    function syncCreateOrderButton(){
        var selectAny = false;
        $(".cartProductItemIfSelected").each(function(){
            if("selectit"===$(this).attr("selectit")){
                selectAny = true;
            }
        });

        if(selectAny){
            $("button.createOrderButton").css("background-color","#C40000");
            $("button.createOrderButton").removeAttr("disabled");
        }
        else{
            $("button.createOrderButton").css("background-color","#AAAAAA");
            $("button.createOrderButton").attr("disabled","disabled");
        }

    }
    function syncSelect(){
        var selectAll = true;
        $(".cartProductItemIfSelected").each(function(){
            if("false"==$(this).attr("selectit")){
                selectAll = false;
            }
        });

        if(selectAll)
            $("img.selectAllItem").attr("src","${pageContext.request.contextPath}/img/site/cartSelected.png");
        else
            $("img.selectAllItem").attr("src","${pageContext.request.contextPath}/img/site/cartNotSelected.png");

    }
    function calcCartSumPriceAndNumber(){
        var sum = 0;
        var totalNumber = 0;
        $("img.cartProductItemIfSelected[selectit='selectit']").each(function(){
            var oiid = $(this).attr("oiid");
            var price =$(".cartProductItemSmallSumPrice[oiid="+oiid+"]").text();
            price = price.replace(/,/g, "");
            price = price.replace(/¥/g, "");
            sum += new Number(price);

            var num =$(".orderItemNumberSetting[oiid="+oiid+"]").val();
            totalNumber += new Number(num);

        });

        $("span.cartSumPrice").html("¥"+formatMoney(sum));
        $("span.cartTitlePrice").html("¥"+formatMoney(sum));
        $("span.cartSumNumber").html(totalNumber);
    }
    function syncPrice(pid,num,price){
        $(".orderItemNumberSetting[pid="+pid+"]").val(num);
        var cartProductItemSmallSumPrice = formatMoney(num*price);
        $(".cartProductItemSmallSumPrice[pid="+pid+"]").html("¥"+cartProductItemSmallSumPrice);
        calcCartSumPriceAndNumber();

        var page = "forechangeOrderItem";
        $.post(
            page,
            {"pid":pid,"number":num},
            function(result){
                if("success" !== result){
                    location.href="login.jsp";
                }
            }
        );

    }
</script>

<title>购物车</title>
<div class="cartDiv">
    <div class="cartTitle pull-right">
        <span>已选商品  (不含运费)</span>
        <span class="cartTitlePrice">¥0.00</span>
        <button class="createOrderButton" disabled="disabled">结 算</button>
    </div>

    <div class="cartProductList">
        <table class="cartProductTable">
            <thead>
            <tr>
                <th class="selectAndImage">
                    <img selectit="false" class="selectAllItem" src="${pageContext.request.contextPath}/img/site/cartNotSelected.png">
                    全选

                </th>
                <th>商品信息</th>
                <th>单价</th>
                <th>数量</th>
                <th width="120px">金额</th>
                <th class="operation">操作</th>
            </tr>
            </thead>
            <tbody>
            <c:forEach items="${ois }" var="oi">
                <tr oiid="${oi.id}" class="cartProductItemTR">
                    <td>
                        <img selectit="false" oiid="${oi.id}" class="cartProductItemIfSelected" src="${pageContext.request.contextPath}/img/site/cartNotSelected.png">
                        <a style="display:none" href="#nowhere"><img src="${pageContext.request.contextPath}/img/site/cartSelected.png"></a>
                        <img class="cartProductImg"  src="${pageContext.request.contextPath}/img/productSingle_middle/${oi.product.productImage.id}.jpg">
                    </td>
                    <td>
                        <div class="cartProductLinkOutDiv">
                            <a href="foreproduct?pid=${oi.product.id}" class="cartProductLink">${oi.product.name}</a>
                            <div class="cartProductLinkInnerDiv">
                                <img src="${pageContext.request.contextPath}/img/site/creditcard.png" title="支持信用卡支付">
                                <img src="${pageContext.request.contextPath}/img/site/7day.png" title="消费者保障服务,承诺7天退货">
                                <img src="${pageContext.request.contextPath}/img/site/promise.png" title="消费者保障服务,承诺如实描述">
                            </div>
                        </div>

                    </td>
                    <td>
                        <span class="cartProductItemOringalPrice">¥${oi.product.originalPrice}</span>
                        <span  class="cartProductItemPromotionPrice">¥${oi.product.promotePrice}</span>
                    </td>
                    <td>

                        <div class="cartProductChangeNumberDiv">
                            <span class="hidden orderItemStock " pid="${oi.product.id}">${oi.product.stock}</span>
                            <span class="hidden orderItemPromotePrice " pid="${oi.product.id}">${oi.product.promotePrice}</span>
                            <a  pid="${oi.product.id}" class="numberMinus" href="#nowhere">-</a>
                            <input pid="${oi.product.id}" oiid="${oi.id}" class="orderItemNumberSetting" autocomplete="off" value="${oi.number}">
                            <a  stock="${oi.product.stock}" pid="${oi.product.id}" class="numberPlus" href="#nowhere">+</a>
                        </div>

                    </td>
                    <td >
                            <span class="cartProductItemSmallSumPrice" oiid="${oi.id}" pid="${oi.product.id}" >
                            ¥<fmt:formatNumber type="number" value="${oi.product.promotePrice*oi.number}" minFractionDigits="2"/>
                            </span>

                    </td>
                    <td>
                        <a class="deleteOrderItem" oiid="${oi.id}"  href="#nowhere">删除</a>
                    </td>
                </tr>
            </c:forEach>
            </tbody>

        </table>
    </div>

    <div class="cartFoot">
        <img selectit="false" class="selectAllItem" src="${pageContext.request.contextPath}/img/site/cartNotSelected.png">
        <span>全选</span>
        <!--         <a href="#">删除</a> -->

        <div class="pull-right">
            <span>已选商品 <span class="cartSumNumber" >0</span> 件</span>

            <span>合计 (不含运费): </span>
            <span class="cartSumPrice" >¥0.00</span>
            <button class="createOrderButton" disabled="disabled" >结  算</button>
        </div>

    </div>

</div>

三、登录状态拦截器

3.1 查看购物车页面的问题

查看购物车页面有个问题,必须建立在已经登录的状态之上,如果没有地址,去访问地址:

http://127.0.0.1:8080/tmall_ssm/forecart

会导致错误。

3.2 解决思路

所以在查看购物车之前,应该进行登录操作,但是又不能确保用户一定会记得登录,那么怎么办呢? 
准备一个过滤器,当访问那些需要登录才能做的页面的时候,进行是否登录的判断,如果不通过,那么就跳转到login.jsp页面去,提示用户登录。
哪些页面需要登录?哪些页面不需要呢?
a. 不需要登录也可以访问的
如:注册,登录,产品,首页,分类,查询等等
b. 需要登录才能够访问的
如:购买行为,加入购物车行为,查看购物车,查看我的订单等等

3.3 LoginInterceptor

新建一个过滤器LoginInterceptor ,根据3.2解决思路中
哪些页面需要登录?哪些页面不需要呢?
a. 不需要登录也可以访问的
如:注册,登录,产品,首页,分类,查询等等
b. 需要登录才能够访问的
如:购买行为,加入购物车行为,查看购物车,查看我的订单等等
不需要登录也可以访问的已经确定了,但是需要登录才能够访问,截止目前为止还不能确定,所以这个过滤器就判断如果不是注册,登录,产品这些,就进行登录校验
1. 准备字符串数组 notNeedAuthPage,存放哪些不需要登录也能访问的路径(注:因为本项目中前端的请求大部分都是以fore开始的,然后后边紧接着具体的功能,如:forehome、forecategory、foreproduct等)
2. 获取uri
3. 去掉前缀/tmall_ssm
4. 如果访问的地址是/fore开头
4.1 取出fore后面的字符串,比如是forecart,那么就取出cart
4.2 判断cart是否是在notNeedAuthPage 
4.2 如果不在,那么就需要进行是否登录验证
4.3 从session中取出"user"对象
4.4 如果对象不存在,就客户端跳转到login.jsp
4.5 否则就正常执行

package interceptor;

import com.li.tmall.pojo.User;
import com.li.tmall.service.CategoryService;
import com.li.tmall.service.OrderItemService;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.util.Arrays;

/**
 * @Author: 98050
 * Time: 2018-09-29 19:04
 * Feature:登录拦截器
 */
public class LoginInterceptor extends HandlerInterceptorAdapter {

    @Autowired
    private CategoryService categoryService;

    @Autowired
    private OrderItemService orderItemService;

    /**
     * 在业务处理器处理请求之前被调用
     * 如果返回false
     *      则从当前的拦截器往回执行所有拦截器的afterCompletion(),再退出拦截器链
     * 如果返回true
     *      执行下一个拦截器,直到所有拦截器都执行完毕
     *      再执行被拦截的Controller
     *      然后进入拦截器链
     *      从最后一个拦截器往回执行所有的postHandle()
     *      紧接着再从最后一个拦截器往回执行所有的afterCompletion()
     * @param request
     * @param response
     * @param handler
     * @return
     * @throws IOException
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws IOException {

        HttpSession session = request.getSession();
        String contextPath = session.getServletContext().getContextPath();
        System.out.println(contextPath);
        String[] notNeedAuthPage = new String[]{
                "home",
                "checkLogin",
                "register",
                "loginAjax",
                "login",
                "product",
                "category",
                "search"
        };
        String uri = request.getRequestURI();
        System.out.println(uri);
        uri = StringUtils.remove(uri,contextPath);
        if (uri.startsWith("/fore")){
            String method = StringUtils.substringAfterLast(uri,"/fore");
            if (!Arrays.asList(notNeedAuthPage).contains(method)){
                User user = (User) session.getAttribute("user");
                if (user == null){
                    response.sendRedirect("loginPage");
                    return false;
                }
            }
        }
        return true;
    }

    /**
     * 在业务处理器处理请求执行完成后,生成视图之前执行的动作
     * 可在modelAndView中加入数据,比如当前时间
     * @param request
     * @param response
     * @param handler
     * @param modelAndView
     * @throws Exception
     */
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        super.postHandle(request, response, handler, modelAndView);
    }

    /**
     * 在DispatcherServlet完全处理完请求后被调用,可用于清理资源等
     * 当有拦截器抛出异常时,会从当前拦截器往回执行所有的拦截器的afterCompletion()
     * @param request
     * @param response
     * @param handler
     * @param ex
     * @throws Exception
     */
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        super.afterCompletion(request, response, handler, ex);
    }
}

3.4 springMVC.xml

3.5 参考

有关SpringMVC中拦截器的工作过程,请参考 :

https://www.cnblogs.com/lyj-gyq/p/8919551.html

https://www.cnblogs.com/lyj-gyq/p/8920773.html

四、其他拦截器

4.1 搜索栏下的分类信息

以前在非主页的搜索栏下面是空的,因为只有在访问主页的Controller.home()中才添加了cs对象,在其他页面中并没有添加

但是其他主页也引入了search.jsp,因为没有专门添加cs属性,所以一开始就无法在搜索框下显示分类。

添加拦截器,在渲染视图时将分类信息放入cs中进行渲染。

4.2 跳转首页超链接

点击下面两个图标会跳转到首页

各自对应的前端代码为:

<a href="${contextPath}/forehome">
	<img id="logo" src="${pageContext.request.contextPath}/img/site/logo.gif" class="logo">
</a>
    <a href="${contextPath}/forehome">
        <img id="simpleLogo" class="simpleLogo" src="${pageContext.request.contextPath}/img/site/simpleLogo.png">
    </a>

 通过拦截器给contextPath赋值为tmall_ssm就可以正常跳转了。

4.3 购物车中数量显示

一开始购物车中的商品数量是无法显示的,通过设置拦截器进行显示。

4.4 新增拦截器

package interceptor;

import com.li.tmall.pojo.Category;
import com.li.tmall.pojo.OrderItem;
import com.li.tmall.pojo.User;
import com.li.tmall.service.CategoryService;
import com.li.tmall.service.OrderItemService;
import com.sun.istack.internal.NotNull;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.util.List;

/**
 * @Author: 98050
 * Time: 2018-09-29 21:04
 * Feature:其他功能的拦截器
 */
public class OtherInterceptor extends HandlerInterceptorAdapter {

    @Autowired
    private CategoryService categoryService;

    @Autowired
    private OrderItemService orderItemService;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        return super.preHandle(request, response, handler);
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        super.postHandle(request, response, handler, modelAndView);

        HttpSession session = request.getSession();
        /**
         * 获取分类集合信息,放在搜索栏下面
         */
        List<Category> categories = categoryService.list();
        session.setAttribute("cs",categories);

        /**
         * 获取当前的contextPath:tmall_ssm,用与放在左上角那个变形金刚,点击之后才能够跳转到首页,否则点击之后也仅仅停留在当前页面
         */
        String contextPath = session.getServletContext().getContextPath();
        session.setAttribute("contextPath",contextPath);

        /**
         * 获取购物车中一共有多少数量
         */
        @NotNull
        User user = (User) session.getAttribute("user");
        List<OrderItem> orderItems =orderItemService.listByUser(user.getId());
        int  cartTotalItemNumber = 0;
        for (OrderItem orderItem : orderItems){
            cartTotalItemNumber+=orderItem.getNumber();
        }
        session.setAttribute("cartTotalItemNumber",cartTotalItemNumber);
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        super.afterCompletion(request, response, handler, ex);
    }
}

4.5 修改springMVC.xml

猜你喜欢

转载自blog.csdn.net/lyj2018gyq/article/details/82897113