• 微信公众号:美女很有趣。 工作之余,放松一下,关注即送10G+美女照片!

京淘项目Day20

互联网 diligentman 2周前 (02-22) 10次浏览

cgb2010-京淘项目Day20

京淘项目Day20

1.完成京淘购物车操作

1.1 数量更新操作

1.1.1 页面分析

1).页面URL分析
京淘项目Day20
2).页面html分析

`<div class="quantity-form" data-bind="">
    <a href="javascript:void(0);" class="decrement" clstag="clickcart|keycount|xincart|diminish1" id="decrement">-</a>
    <input type="text" class="quantity-text" itemPrice="${cart.itemPrice}" itemId="${cart.itemId}" value="${cart.num }" id="changeQuantity-11345721-1-1-0">
    <a href="javascript:void(0);" class="increment" clstag="clickcart|keycount|xincart|add1" id="increment">+</a>
</div>

3).页面JS

`$(".increment").click(function(){//+
            var _thisInput = $(this).siblings("input");
            _thisInput.val(eval(_thisInput.val()) + 1);
            $.post("/cart/update/num/"+_thisInput.attr("itemId")+"/"+_thisInput.val(),function(data){
                TTCart.refreshTotalPrice();
            });
        });

1.1.3 编辑CartController

`/**
     * 购物车数量更新操作
     * URL地址: http://www.jt.com/cart/update/num/1474391990/16
     * 参数:    itemId,num
     * 返回值:  没有 void
     */
    @RequestMapping("/update/num/{itemId}/{num}")
    @ResponseBody //将返回值转化为json   代表ajax程序结束
    public void updateNum(Cart cart){

        long userId = 7;
        cart.setUserId(userId);
        cartService.updateNum(cart);
    }

1.1.2 编辑CartService

 `//sql: update tb_cart set num=#{num},updated=#{updated} where user_id=#{userId} and
    //     item_id = #{itemId}
    @Override
    public void updateNum(Cart cart) {
        Cart temp = new Cart();
        temp.setNum(cart.getNum());
        QueryWrapper queryWrapper = new QueryWrapper();
        queryWrapper.eq("user_id", cart.getUserId());
        queryWrapper.eq("item_id", cart.getItemId());
        cartMapper.update(temp,queryWrapper);
    }

1.2 购物车删除操作

1.2.1 页面分析

业务说明: 当用户点击删除按钮时,应该重定向到购物车展现页面.
京淘项目Day20

1.2.2 编辑CartController

 `/**
     * URL地址:http://www.jt.com/cart/delete/1474391990.html
     * 返回值:  String类型
     */
    @RequestMapping("/delete/{itemId}")
    public String deleteCart(Cart cart){

        long userId = 7;
        cart.setUserId(userId);
        cartService.deleteCart(cart);
        return "redirect:/cart/show.html";
    }

1.2.3 编辑CartService

 `@Override
    public void deleteCart(Cart cart) {
        //根据对象中不为null的属性充当where条件
        cartMapper.delete(new QueryWrapper<>(cart));
    }

2 关于前台权限控制

2.1 业务说明

当用户在没有登录的条件下,不允许访问敏感业务数据例如购物车/订单业务等…
难点:
1.如何判断用户是否登录? 1.检查cookie 2.检查redis
2.如何控制权限? 拦截器!

2.2 拦截器业务实现原理

2.2.1 SpringMVC流程图复习

京淘项目Day20

2.2.2 拦截器工作流程

京淘项目Day20

2.2.3 配置拦截器

京淘项目Day20

2.2.4 编辑拦截器接口

`package com.jt.interceptor;

import com.jt.pojo.User;
import com.jt.util.CookieUtil;
import com.jt.util.ObjectMapperUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import redis.clients.jedis.JedisCluster;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.function.Predicate;
@Component  //将对象交给Spring容器管理
public class UserInterceptor implements HandlerInterceptor {

    @Autowired
    private JedisCluster jedisCluster;

    /**
     * 通过拦截器实现拦截,重定向系统登录页面
     * @param request
     * @param response
     * @param handler
     * @return
     * @throws Exception
     *
     * 返回值说明:
     *      boolean   false 表示拦截 一般配合重定向方式使用
     *
     * 业务调用:
     *      1.获取cookie中的数据
     *      2.检查redis中是否有数据
     *      3.校验用户是否登录.
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        //1.获取cookie中的数据,检查是否登录
        String ticket = CookieUtil.getCookieValue(request, "JT_TICKET");
        if(StringUtils.hasLength(ticket) && jedisCluster.exists(ticket)){//判断数据是否有值
                //2.动态获取user信息
                String json = jedisCluster.get(ticket);
                //3.将json转化为用户对象
                User user = ObjectMapperUtil.toObj(json, User.class);
                request.setAttribute("JT_USER", user);
                return true;    //表示程序放行
        }

        //实现用户重定向
        response.sendRedirect("/user/login.html");
        return false;
    }

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

    }

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

        request.removeAttribute("JT_USER");
    }
}

2.2.5 编辑CartController

京淘项目Day20

2.3 ThreadLocal

2.3.1 ThreadLocal作用

名称: 本地线程变量
作用: 在同一个线程内,实现数据共享.
京淘项目Day20

2.3.2 封装工具API

`package com.jt.util;

import com.jt.pojo.User;

public class UserThreadLocal {
    //线程的一个属性  ThreadLocal是线程安全的
    private static ThreadLocal<User> threadLocal = new ThreadLocal<>();

    public static void set(User user){
        threadLocal.set(user);
    }

    public static User get(){

        return threadLocal.get();
    }

    public static void remove(){

        threadLocal.remove();   //删除数据
    }
}

2.3.3 基于ThreadLocal实现数据取赋值操作

1.拦截器赋值
京淘项目Day20
2.用户取值
京淘项目Day20
3.数据销毁
京淘项目Day20

3.订单模块

3.1 订单确认页面跳转

3.1.1 业务分析

说明: 当点击去结算按钮时,应该跳转到订单确认页面order-cart.jsp.
京淘项目Day20

3.1.2 编辑OrderController

`package com.jt.controller;

import com.alibaba.dubbo.config.annotation.Reference;
import com.jt.pojo.Cart;
import com.jt.service.DubboCartService;
import com.jt.util.UserThreadLocal;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;

import java.util.List;

@Controller
@RequestMapping("/order")
public class OrderController {

    @Reference
    private DubboCartService cartService;

    /**
     * 业务说明:
     *      当点击按钮时,跳转到订单确认页面  cartList购物车数据
     * URL地址:http://www.jt.com/order/create.html
     * 参数:  userId
     * 返回值: 页面逻辑名称 order-cart
     * 页面取值: ${carts}
     */
    @RequestMapping("/create")
    public String orderCreate(Model model){

        long userId = UserThreadLocal.get().getId();
        List<Cart> cartList = cartService.findCartListByUserId(userId);
        model.addAttribute("carts",cartList);
        return "order-cart";
    }

}

3.1.3 页面效果展现

京淘项目Day20

3.2 订单项目创建

3.2.1 创建订单项目

京淘项目Day20

3.2.2 添加继承/依赖/插件

 `<dependencies>
        <dependency>
            <groupId>com.jt</groupId>
            <artifactId>jt-common</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
    </dependencies>

    <!--添加插件 有main方法时 需要添加插件-->
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <excludes>
                        <exclude>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok</artifactId>
                        </exclude>
                    </excludes>
                </configuration>
            </plugin>
        </plugins>
    </build>

3.2.3 关于订单表设计说明

京淘项目Day20

3.2.4 编辑POJO

京淘项目Day20

3.2.5 代码结构如下

京淘项目Day20

3.3 SpringMVC 参数传递方式

3.3.1 为简单参数赋值

`<input  type="text" name="username"  value="admin" />
 `public void addUser(String username){
    }

3.3.2 为对象赋值

 `<input  type="text" name="id"  value="100" />
    <input  type="text" name="username"  value="admin" />
    <input  type="text" name="age"  value="18" />
 `public void addUser(User user){
    }

3.3.3 为对象引入赋值

问题: 有时可能遇到重名属性! 如何处理?

 `<input  type="text" name="name"  value="二郎神" />
    <input  type="text" name="age"  value="30" />
    <input  type="text" name="dog.name"  value="啸天犬" />
    <-- 为list集合赋值   -->
    <input  type="text" name="hobbys[0]"  value="敲代码" />
    
 `//利用对象的方式进行封装
    public class User {
        private String name;
        private Integer age;
        private Dog dog;
        private List hobbys
    }
    
    public class Dog {
        private String name;
        private Integer age;
    }

    //    SpringMVC 参数接收
    public void addUser(User user){
    }

3.4 订单提交

3.4.1 页面分析

1).页面URL分析
京淘项目Day20
2).参数说明
京淘项目Day20
3).POJO对象封装
京淘项目Day20
4).页面JS分析

`jQuery.ajax( {
            type : "POST",
            dataType : "json",
            url : "/order/submit",
            //将name属性与值进行拼接 形式 name=value1&name2=value2&name3=value3......
            //表单序列化,可以简化参数写法
            data : $("#orderForm").serialize(),
            cache : false,
            success : function(result) {    //SysResult对象
                if(result.status == 200){   //要求返回orderId
                    location.href = "/order/success.html?id="+result.data;
                }else{
                    $("#submit_message").html("订单提交失败,请稍后重试...").show();
                }
            },
            error : function(error) {
                $("#submit_message").html("亲爱的用户请不要频繁点击, 请稍后重试...").show();
            }
        });

3.4.2 编辑OrderController

`/**
     * 实现订单入库操作
     * url分析:   http://www.jt.com/order/submit
     * 参数:      整个form表单 Order对象
     * 返回值:    SysResult对象
     * 页面取值:  要求返回orderId
     */
    @RequestMapping("/submit")
    @ResponseBody
    public SysResult submit(Order order){
        long userId = UserThreadLocal.get().getId();
        order.setUserId(userId);
        String orderId = orderService.saveOrder(order);
        //完成订单之后,应该删除购物车.. 分布式事务....
        //cartService.deleteCart();
        return SysResult.success(orderId);
    }

3.4.3 编辑OrderService

`package com.jt.service;

import java.util.Calendar;
import java.util.Date;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;

import com.alibaba.dubbo.config.annotation.Service;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.jt.mapper.OrderItemMapper;
import com.jt.mapper.OrderMapper;
import com.jt.mapper.OrderShippingMapper;
import com.jt.pojo.Order;
import com.jt.pojo.OrderItem;
import com.jt.pojo.OrderShipping;

@Service
public class OrderServiceImpl implements DubboOrderService {
    
    @Autowired
    private OrderMapper orderMapper;
    @Autowired
    private OrderShippingMapper orderShippingMapper;
    @Autowired
    private OrderItemMapper orderItemMapper;

    /**
     * 完成3张表入库操作
     * order表入库
     * orderItem表入库
     * OrderShipping表入库
     * 动态生成orderId.设定默认状态
     * 注意数据库事务控制
     * @param order
     * @return
     */
    @Override
    @Transactional
    public String saveOrder(Order order) {
        //动态生成主键
        String orderId = "" + order.getUserId() + System.currentTimeMillis();
        //1.完成订单入库操作
        order.setOrderId(orderId).setStatus(1);
        orderMapper.insert(order);
        System.out.println("订单入库操作成功!!!");

        //2.完成订单物流入库
        OrderShipping orderShipping = order.getOrderShipping();
        orderShipping.setOrderId(orderId);
        orderShippingMapper.insert(orderShipping);
        System.out.println("订单物流入库成功!!!");

        //3.完成订单商品入库操作
        List<OrderItem> orderItems = order.getOrderItems();
        for (OrderItem orderItem : orderItems){
            orderItem.setOrderId(orderId);
            orderItemMapper.insert(orderItem);
        }
        System.out.println("订单全部入库成功!!!!");
        return orderId;
    }
}

3.5 订单查询

3.5.1 业务分析

说明: 当用户订单入库之后,应该跳转到订单的成功页面. 格式如下:
页面数据: ${order}
京淘项目Day20
京淘项目Day20

3.5.2 编辑OrderController

 `/**
     * 实现订单查询
     * url: http://www.jt.com/order/success.html?id=71613981329562
     * 参数: orderId
     * 返回值: 成功页面 success.jsp
     * 页面取值: Order对象(包含其它2个业务数据) ${order.orderId}
     */
    @RequestMapping("/success")
    public String success(String id,Model model){
        //根据id 查询订单对象
        Order order = orderService.findOrderById(id);
        model.addAttribute("order", order);
        return "success";
    }

3.5.3 编辑OrderService

`@Override
    public Order findOrderById(String id) {

        Order order = orderMapper.selectById(id);
        OrderShipping orderShipping = orderShippingMapper.selectById(id);
        QueryWrapper queryWrapper = new QueryWrapper();
        queryWrapper.eq("order_id", id);
        List<OrderItem> orderItems = orderItemMapper.selectList(queryWrapper);
        return order.setOrderShipping(orderShipping).setOrderItems(orderItems);
    }

3.5.4 页面效果

京淘项目Day20

4 京淘项目总结

4.1 Maven工作原理

1).maven作用 一站式的项目管理工具 管理jar包 项目打包部署
2).maven 依赖传递性 A –B–C 如何实现的
3).Maven如何保证jar包文件不被篡改 sha1 消息摘要.

4.2 SpringBoot工作原理

1).开箱即用原则? 如何实现的??
2).为属性赋值用法 @Value(“${key}”)
3).动态导入pro配置文件 @propertySource
4).环境分割 — 环境命名 默认环境选择
5).LOMBOK插件 注解 @Data xxxx
6).SpringBoot整合Mybatis 理解配置文件 别名包/驼峰映射规则
7).SpringBoot整合MybatisPlus ORM思想 对象关系映射.
8).SpringBoot整合web动态资源 JSP 项目打包 war包

4.3 分布式架构设计方案

1).分布式架构设计 按照模块拆分 按照层级拆分
2).理解分布式/集群/高可用的概念
3).构建分布式系统的原则 如何统一管理jar包 如何统一管理工具API

4.4 京淘后端项目搭建

1).业务 商品CURD操作 /商品分类CURD操作
2).VO对象的编辑原则 调用别人的JS 必须按照要求返回JSON.
3).全局异常处理的设计.
4).如何定义系统返回值对象 SysResult对象
5).文件上传案例.

4.5 反向代理服务器

1).什么是反向代理
2).什么是正向代理
3).nginx相关配置 命令 配置
4).hosts文件作用 实现域名与IP地址的映射
5).nginx 负载均衡方式 1.轮询 2.权重 3.iphash
6).nginx 高级属性用法 1.down 2.backup 3.高可用设定.

4.6 Linux

1).命令: cd/cp/mv/mkdir/rm/vim/…
2).安装JDK vim /etc/profile java -version
3).mariadb数据库安装 考虑权限 导入数据库/表 防火墙命令
4).实现manage项目Linux部署.
5).Linux的nginx项目部署
6).实现数据库高可用 数据库主从同步命令 基于Mycat实现数据库高可用.

4.7 Redis相关学习

1).redis命令 支持1-5-8种数据类型
2).redis分片机制 实现内存扩容 一致性hash算法 2^32取值方式
3).redis哨兵机制 实现高可用 哨兵的工作原理 如何监控
4).redis集群配置 redis分区算法. crc16(key)%16384
5).redis持久化策略 RDB快照 /AOF 操作过程
6).redis内存优化策略 LRU/LFU/random/TTL
7).什么是缓存穿透 访问不存在的数据 布隆过滤器算法
8).什么是缓存击穿 访问某个热点数据失效了 多级缓存
9).什么是缓存雪崩 大量的数据同时失效 多级缓存
10).SpringBoot整合redis相关配置.

4.8 实现前端搭建

1).跨域思想 同源策略(协议://域名:端口)
2).跨域解决方案 1.JSONP方式(1.利用script标签 src实现跨域 2.自定义回调函数 3.特殊格式封装)
2.CORS(设定服务端数据共享 设定响应头信息)
3).httpClient 万能的远程过程调用的方法 一般多见于框架底层代码 例如SpringCloud
4).伪静态思想 以.html结尾的请求

4.9 微服务框架

1).SOA思想
2).RPC 远程过程调用 相对本地而言 代词
3).微服务调用思想
4).注册中心 zookeeper服务. 单台—> 集群搭建
5).微服务框架的调用的流程 ZK集群的选举机制/工作原理
6).Dubbo框架 1.中立的接口 2.服务生产者 3.服务器消费者
7).Dubbo负载均衡机制 1.一致性hash 2.最小访问 3.随机策略 4.轮询机制 客户端负载均衡

4.10 业务流程调用

1).基于dubbo 实现商品数据的获取
2).基于dubbo实现jt-sso单点登录 Cookie操作 登录/登出/数据回显
3).完成购物车功能 CRUD操作 购物车中的记录如果存在则更新数量/不存在新增购物车.
4).完成权限控制 基于拦截器
5).利用request对象/ThreadLocal方式动态取值.
6).订单业务逻辑 表3张 为对象的引用赋值. 多张表业务操作 注意事务控制.

主要学习SpringCloud机制… docker容器 MQ技术.


程序员灯塔
转载请注明原文链接:京淘项目Day20
喜欢 (0)