首页 > 其他分享 >P2项目答辩总结

P2项目答辩总结

时间:2022-11-25 17:34:35浏览次数:63  
标签:P2 总结 ordersForm 轮播 用户 订单 vip 答辩 orderMsgMapToQueue

1、登录

1.1 登录的时候做vip的判断;

1.2 使用JWT(Java Web token),验证登录,更加安全

2、连续签到

2.1判断是否断签:

​ 通过判断昨天是否登录,可以判断;

2.2判断连续签到多少天:

​ 将每次签到的记录保存在redis中,判断保存的数量,有多少个,就连续签到多少天;

2.3 签到流水:

​ 签到流水如果可以,直接保存在数据库;(考虑使用redis的bitMaps);

《Redis实战》之使用BitMap实现用户签到功能:https://blog.csdn.net/qq_31905135/article/details/124032880

Redis中是利用String类型数据结构实现BitMap,因此最大上限是512M,转换为bit则是2^32个bit位。

bitmap的操作命令有:

setbit:向指定位置offset存入一个0或1

getbit:获取指定位置offset的bit值

bitcount:统计BitMap中值为1的bit位的数量

bitfield: 操作(查询,修改,自增)BitMap中bit数组中的指定位置offset的值

bitfield_ro: 获取BitMap中bit数组,并以十进制形式返回

bittop:  将多个BitMap的结果做位运算(与,或,异或)

bitpos:  查找bit数组中指定范围内第一个0或者1出现的位置
2.4 签到初始化(自我考虑)

​ 每天0点的时候每个用户初始化一条没有登录的信息(例如:status=0),如果用户登录了就对用户的状态进行修改(status=1);

3、VIP

3.1 vip续约

redis中存用户vip的唯一标识key,设置ttl,并设置用户vip字段为vip;续约直接增加key值得时间;

3.2 判断用户是不是VIP会员状态

​ 一些需要使用到vip的权限的时候,先对vip进行检查,如果vip失效,需要将用户的vip字段设置为 普通会员;(主要两个地方判断:1.用户登录;2.用户使用vip权限);这样可以大大节省时时判断用户vip状态的消耗;

4、 关键词匹配

考虑,模糊匹配,近义词,(俗名),ES分词,IK分词(ElasticSearch+Kibana)

5、热词

5.1 热词库

需要添加热词库,只有在热词库中的词语,命中才算热词;热词的管理权在商家手里;

5.2 添加热词(候选热词库)
  1. 通过商品的销量添加对应的热词;
  2. 对正常搜索到的词语进行搜索次数的记录,作为候选热词库;如果后期需要添加,可以从候选热词库中挑选;
  3. 可以使用老师的关键字的方式进行模仿实现命中;

6 、轮播图

6.1 轮播图的数量

可以根据不同时段进行不同数量的展示,人越多,数量越多;

6.2 多商户下,轮播图的挑选
  1. 添加到轮播图需要一定的费用;
  2. 可以根据商品的销量和热卖品挑选轮播图;
6.3 轮播图排序
  1. 返回的前端的轮播图需要排序好;
6.4 轮播图每个人不一样
  1. 每个人的轮播图不一样;
6.5轮播图设计

img

1.1 :关于背景色:也可以不用,主要看你的轮播图占多大空间,如果是下图那样占全部空间,因为图片不可能将其全部占据,如果不用背景色,那么,轮播图片的两旁就是白色,会很难看。所以看自己
1.2 商品id:有时候,需要客户点击轮播图,直接跳转到 商品详情页面,所以 商品id 是线索

1.3 商品分类id:有时,点击后,会跳转到某一分类下,不是具体的商品详情页面

1.4 轮播图类型(type):用于判断,可以根据商品id或者分类进行页面跳转,1:商品 2:分类

6、首页展示

  1. 每个人展示的商品不一样,可以从用户收藏,用户购买,添加购物车,用户浏览记录,等等推荐;
  2. 用户的行为数据(用户收藏,用户购买,添加购物车,用户浏览记录,等等)不能物理删除,因为这个数据是经过用户的自主赛选后得到的数据,十分宝贵;

7、优惠劵

  1. 优惠劵池(优惠劵有不同的分类可以领取);
  2. 优惠劵的领取情况;
  3. 智能优惠劵挑选,在使用的时候,给用户展示优惠劵,需要将金额大的放在第一个,用户可以自行挑选;
  4. 用户优惠劵挑选过一次,在下订单的时候还需要再次判断优惠劵是否使用过,是否过期(除非可以确定该优惠劵一定可以用);

8、商品下单及自动签收

  1. 商品发货
  2. 需要考虑商品的自动签收,用户不主动签收,需要自动签收;考虑使用延时队列,(或者定时+普通消息队列,注意定时对性能消耗比较大);

9、分享有礼

  1. 隐藏分享用户的信息(因为需要对分析的用户进行奖励,但是又不能随便暴露用户的信息)
    1. 可以将用户信息MD5加密后在加盐,(内部有永固加盐库,自己人可以知道)
    2. 需要动态生成用户相关信息,主要目的就是保护用户信息安全;

10、某个商品比较冷清没有多少评论

  1. 将同一个商铺下,类似产品的评论移过来;(个人感觉不是太好);

11、多负载的时候,防止定时任务重复执行

  1. XXL-Job
  2. 分布式的redis加锁,执行完释放;
  3. 通过ip指定配置,指定执行定时任务的服务器;

12、做项目中遇到的问题

12.1 日期格式问题

//1.返回给前端的日期格式
//实体参数上添加日期格式化注解
@JsonFormat(pattern="yyyy-MM-dd HH:mm:ss",timezone="GMT+8")

//2.前端传给后端的日期格式
//实体参数上添加日期格式化注解
@DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss")

12.2 feign远程调用传输时间相差(快了)14个小时

1.先说结论:在feign接口调用时使用表单形式(@RequestParam)传date类型会发生时间精度错乱,在8时区会多14个小时。

2.使用json格式(@RequestBody)传date类型不会发生这种情况。
表单形式我的解决办法是:在对外暴露的feign接口中使用字符串类型。

3.(String date)来接收日期,在真正feign调用的controller服务中使用@DateTimeFormat(pattern=“yyyy-MM-dd”)Date date来转换字符串类型的日期。

4.将接收到的时间减去14小时(强烈不建议,比较麻烦且冗余,多次远程调用可能会再相差时间)。

5.扩展ZonedDateTime

java8 日期 时间 时区:https://blog.csdn.net/z69183787/article/details/87176339

ZonedDateTime时区日期时间类的运用:https://blog.csdn.net/qx020814/article/details/125580729

LocalDateTime、OffsetDateTime、ZonedDateTime互转:https://blog.csdn.net/f641385712/article/details/112732546

12.3 swagger返回参数不显示实体属性注解

需要添加@ApiModel(value = "xxx")注解,@ApiModelProperty(value = "xxx")注解,由于我之前没有怎么使用这个注解,导致忘记了,特此记录一下;

12.4 一个消息队列出列多个业务

12.4.1 发消息

将要处理的消息内容转换成JOSN字符对象,再放入到map集合中,监听到消息后,根据不同的消息内容进行不同的处理;

点击查看代码
//将订单信息封装成map集合,方便发送
Map<String, Object> orderMsgMapToQueue = new HashMap<>();
//父订单
orderMsgMapToQueue.put("ordersForm", JSON.toJSONString(ordersForm));
//子订单
orderMsgMapToQueue.put("orderItemListSize", orderItemListForm.size());
for (int i = 0; i < orderItemListForm.size(); i++) {
    orderMsgMapToQueue.put("orderItem"+i,JSON.toJSONString(orderItemListForm.get(i)));
}

//发送生成抢购订单的消息到消息队列,并在redis中添加此订单的记录
//0 正在生成
if(redisUtils.set("weddingshop:orders:"+ordersForm.getOid(),ordersForm)){
    //发送生成的 订单信息 到 消息队列
    rabbitTemplate.convertAndSend(OrderMQConstant.WEDDINGSHOP_SAVE_ORDER_EXCHANGE,
                                  OrderMQConstant.WEDDINGSHOP_SAVE_ORDER_ROUTING,
                                  orderMsgMapToQueue);
}

12.4.2 接收消息

监听到消息后,从map集合中取出不同的消息,根据不同的消息内容进行不同的处理;

点击查看代码
@Slf4j
@Component
//指定接听的 消息队列 名字
@RabbitListener(queues = OrderMQConstant.WEDDINGSHOP_SAVE_ORDER_QUEUE)
public class SeckillOrderSaveListener {

    @Autowired
    private RedisUtils redisUtils;

    @Autowired(required = false)
    private OrdersMapper ordersMapper;

    @Autowired(required = false)
    private OrderItemMapper orderItemMapper;

    @Autowired
    private OrdersService ordersService;

    /**
     * @author : huayu
     * @date   : 1/11/2022
     * @param  : [directMsgJson]
     * @return : void
     * @description : Direct 直连模式消费者One,消费信息
     */
    //指定消息队列中的消息,交给对应的方法处理
    @RabbitHandler
    public void saveSeckillOrder(Map<String,Object> orderMsgMapToQueue){

        //子订单消息
        if(orderMsgMapToQueue.get("orderItemListSize") != null){
            //插入子订单
            int orderItemListSize = Integer.parseInt(orderMsgMapToQueue.get("orderItemListSize").toString());
            for (int i = 0; i < orderItemListSize; i++) {
                OrderItem orderItem = JSON.parseObject(orderMsgMapToQueue.get("orderItem" + i).toString(), OrderItem.class);
                log.info("***** 秒杀抢购子订单:{},开始入库 ******",orderItem);
                if(orderItemMapper.insert(orderItem) > 0){
                    log.info("***** 秒杀抢购子订单:{},开始入库 成功 ******",orderItem);
                }
            }
        }


        //父订单消息
        if(orderMsgMapToQueue.get("ordersForm")!= null){
            Orders ordersForm = JSON.parseObject(orderMsgMapToQueue.get("ordersForm").toString(), Orders.class);
            log.info("***** 秒杀抢购父订单:{},开始入库 ******",ordersForm);

            //TODO 将消息中的订单实体对象,调入业务接口,插入到数据库,和redis中
            //插入 父订单
            if(ordersMapper.insert(ordersForm)>0){
                log.info("***** 秒杀抢购父订单:{},入库 成功 ******",ordersForm);
            }
        }


       //父订单 付款后 ,操作
        if(orderMsgMapToQueue.get("ordersPayOid") != null){
            // 父订单付款后 对 父订单 修改状态,用户增加积分 和 子订单 修改状态,生成物流单号
            String ordersPayOid = orderMsgMapToQueue.get("ordersPayOid").toString();
            log.info("------ 父订单:{},支付成功,对 父订单 修改状态,用户增加积分 和 子订单 修改状态,生成物流单号------",ordersPayOid);
             if(ordersService.paySuccessOrders(ordersPayOid)){
                 log.info("------ 父订单:{},入库成功,对 父订单 修改状态,用户增加积分 和 子订单 修改状态,生成物流单号------",ordersPayOid);
             }
        }

    }


}



标签:P2,总结,ordersForm,轮播,用户,订单,vip,答辩,orderMsgMapToQueue
From: https://www.cnblogs.com/xiaoqigui/p/16925371.html

相关文章

  • 最全的PyInputPlus模块方法总结
    安装第三方模块    在Windows和macOS中,pip会随着Python自动安装。可以通过命令行窗口输入pip检查是否已经安装。但在Linux中,必须由你单独安装。在UbuntuLi......
  • 最全的Python海龟绘图总结
    在Python中使用海龟绘图,需要导入相应的模块,那么什么是模块呢?逻辑上来说模块就是一组功能的组合;实质上一个模块就是一个包含了python定义和声明的文件,文件名就是模块名字加上......
  • RIP2
    RIP2RIP2的意思是RIP第二版。它是在RIP使用过程中总结了经验的基础上进行改良后的一种协议。第二版与第一版的工作机制基本相同,不过仍有如下几个新的特点.使用多播R......
  • Tomcat常见问题总结,无法启动服务,无法访问,控制台乱码问题
    Tomcat无法启动,无法访问新下载的Tomcat,运行startup.bat后一闪而过,无法启动Tomcat服务。可能会有这样的效果可以在CMD窗口下进入Tomcat安装目录,运行startup可以看到报错......
  • Go语言错误总结(三)
    15、Strings无法修改尝试使用索引操作来更新字符串变量中的单个字符将会失败。string是只读的byteslice(和一些额外的属性)。如果你确实需要更新一个字符串,那么使用byteslic......
  • Go语言错误总结(二)
    8、使用“nil”SlicesandMaps在一个nil的slice中添加元素是没问题的,但对一个map做同样的事将会生成一个运行时的panic。正确代码:packagemainfuncmain(){vars[]i......
  • P7962 [NOIP2021] 方差
    [NOIP2021]方差时隔一年。我又回来做这个题了。。。我们通过观察是可以发现这里的操作实际上就是交换相邻差分,但是差分\(c_1\)不可被交换。然后如果要求方差最小的话......
  • Go语言错误总结(五)
    29、未导出的结构体不会被编码以小写字母开头的结构体将不会被(json、xml、gob等)编码,因此当你编码这些未导出的结构体时,你将会得到零值。packagemainimport("encoding/......
  • Go语言错误总结(四)
    22、内建的数据结构操作不是同步的即使Go本身有很多特性来支持并发,并发安全的数据集合并不是其中之一,确保数据集合以原子的方式更新是你的职责。Goroutines和channels是实现......
  • 咕噜校园项目总结
    咕噜校园项目功能解刨技术分析校园后台:正方软件后台系统抓包登录:抓取账号密码,看看加密各方面查看请求参数成功和失败动作课表查询抓取URL查看请求参数解......