【业务功能篇105】 微服务-springcloud-springboot-电商订单模块--秒杀服务-定时任务【上篇】

news2024/11/19 17:25:25

秒杀服务

一、商品上架

秒杀活动的结构图

image.png

通过定时任务触发:

  • 定时任务由spring提供,需要通过注解开启,这里通过定义一个配置类,注入spring,对其配置类进行相应的注解,当然也可以注解放在我们的服务启动类上
  • cron表达式定时示例

0 * * * * ? 每1分钟触发一次
0 0 * * * ? 每天每1小时触发一次
0 0 10 * * ? 每天10点触发一次
0 * 14 * * ? 在每天下午2点到下午2:59期间的每1分钟触发
0 30 9 1 * ? 每月1号上午9点半
0 15 10 15 * ? 每月15日上午10:15触发
*/5 * * * * ? 每隔5秒执行一次
0 */1 * * * ? 每隔1分钟执行一次
0 0 5-15 * * ? 每天5-15点整点触发
0 0/3 * * * ? 每三分钟触发一次
0 0 0 1 * ? 每月1号凌晨执行一次

对照上面的字段含义写自定义的cron时间表达式基本就ok了,写完后可以到 http://cron.qqe2.com/ 验证下。

注意:"0 0/50 * * * ?"这个表达式很多人会认为是每隔50分钟执行,实际不是,会每个小时的50分、60分钟跑一次,例如1:50,2:00,2:50,3:00……

//开启异步,还需要在具体的任务方法加@Async表示需要异步 ,定时任务默认是同步的,主要是为了定时可以按时跑起来,比如说我们任务是每10秒执行一次,但是任务逻辑跑完不止10秒,这样就需要等任务执行完再接着跑,这样频率就没有达到预期效果,所以我们开启异步,多线程去每隔10秒运行任务,即使任务10秒内没跑完也会开启其他线程来跑,而这里的线程池的数量,是系统默认给的,这里可以通过配置参数在yaml文件自定义
//spring.task.execution.pool.core-size=5  .max-size=20 进行设置
@EnableAsync

//开启定时功能  还需要在具体扥任务方法加@Scheduled表示定时频率
@EnableScheduling
@Configuration
public class ScheduleConfig {
}
/**
 * 定时上架秒杀商品信息
 */
@Slf4j
@Component
public class SeckillSkuSchedule {

    @Autowired
    SeckillService seckillService;

    @Autowired
    RedissonClient redissonClient;

    /**
     *
     */
    @Async
    //每5s执行一次
    @Scheduled(cron = "*/5 * * * * *")
    public void uploadSeckillSku3Days(){
        log.info("定时上架秒杀商品执行了...." + new Date());
        // 分布式锁 避免多节点多集群场景下,会重复执行,先提供一个分布式锁,使各个节点通过这种获取锁方式来执行,当然拿到锁还是会去重复执行的,所以接着再业务方法里头还要通过逻辑判断去过滤处理,比如已经存储在redis的key 那么就不再执行,不存在的说明还没执行就进行插入 if(!key)
        RLock lock = redissonClient.getLock("seckill:upload:lock");
        lock.lock(10, TimeUnit.SECONDS);
        try {
            // 调用上架商品的方法
            seckillService.uploadSeckillSku3Days();
        }catch (Exception e){
            lock.unlock();
        }
    }

}

进入到Service中处理

@Override
    public void uploadSeckillSku3Days() {
        // 1. 通过OpenFegin 远程调用Coupon服务中接口来获取未来三天的秒杀活动的商品
        R r = couponFeignService.getLates3DaysSession();
        if(r.getCode() == 0){
            // 表示查询操作成功
            String json = (String) r.get("data");
            List<SeckillSessionEntity> seckillSessionEntities = JSON.parseArray(json,SeckillSessionEntity.class);
            // 2. 上架商品  Redis数据保存
            // 缓存商品
            //  2.1 缓存每日秒杀的SKU基本信息
            saveSessionInfos(seckillSessionEntities);
            // 2.2  缓存每日秒杀的商品信息
            saveSessionSkuInfos(seckillSessionEntities);

        }
    }

/**
     * 保存每日活动的信息到Redis中
     * @param seckillSessionEntities
     */
    private void saveSessionInfos(List<SeckillSessionEntity> seckillSessionEntities) {
        for (SeckillSessionEntity seckillSessionEntity : seckillSessionEntities) {
            // 循环缓存每一个活动  key: start_endTime
            long start = seckillSessionEntity.getStartTime().getTime();
            long end = seckillSessionEntity.getEndTime().getTime();
            // 生成Key
            String key = SeckillConstant.SESSION_CHACE_PREFIX+start+"_"+end;
            Boolean flag = redisTemplate.hasKey(key);
            if(!flag){// 表示这个秒杀活动在Redis中不存在,也就是还没有上架,那么需要保存
                // 需要存储到Redis中的这个秒杀活动涉及到的相关的商品信息的SKUID
                List<String> collect = seckillSessionEntity.getRelationEntities().stream().map(item -> {
                    // 秒杀活动存储的 VALUE是 sessionId_SkuId
                    return item.getPromotionSessionId()+"_"+item.getSkuId().toString();
                }).collect(Collectors.toList());
                redisTemplate.opsForList().leftPushAll(key,collect);
            }
        }
    }

    /**
     * 存储活动对应的 SKU信息
     * @param seckillSessionEntities
     */
    private void saveSessionSkuInfos(List<SeckillSessionEntity> seckillSessionEntities) {
        seckillSessionEntities.stream().forEach(session -> {
            // 循环取出每个Session,然后取出对应SkuID 封装相关的信息
            BoundHashOperations<String, Object, Object> hashOps = redisTemplate.boundHashOps(SeckillConstant.SKU_CHACE_PREFIX);
            session.getRelationEntities().stream().forEach(item->{
                String skuKey = item.getPromotionSessionId()+"_"+item.getSkuId();
                Boolean flag = redisTemplate.hasKey(skuKey);
                if(!flag){
                    SeckillSkuRedisDto dto = new SeckillSkuRedisDto();
                    // 1.获取SKU的基本信息
                    R info = productFeignService.info(item.getSkuId());
                    if(info.getCode() == 0){
                        // 表示查询成功
                        String json = (String) info.get("skuInfoJSON");
                        dto.setSkuInfoVo(JSON.parseObject(json,SkuInfoVo.class));
                    }
                    // 2.获取SKU的秒杀信息
                    /*dto.setSkuId(item.getSkuId());
                    dto.setSeckillPrice(item.getSeckillPrice());
                    dto.setSeckillCount(item.getSeckillCount());
                    dto.setSeckillLimit(item.getSeckillLimit());
                    dto.setSeckillSort(item.getSeckillSort());*/
                    BeanUtils.copyProperties(item,dto);
                    // 3.设置当前商品的秒杀时间
                    dto.setStartTime(session.getStartTime().getTime());
                    dto.setEndTime(session.getEndTime().getTime());

                    // 4. 随机码
                    String token = UUID.randomUUID().toString().replace("-","");
                    dto.setRandCode(token);
                    // 分布式信号量的处理  限流的目的
                    RSemaphore semaphore = redissonClient.getSemaphore(SeckillConstant.SKU_STOCK_SEMAPHORE + token);
                    // 把秒杀活动的商品数量作为分布式信号量的信号量
                    semaphore.trySetPermits(item.getSeckillCount().intValue());
                    hashOps.put(skuKey,JSON.toJSONString(dto));
                }
            });
        });
    }

通过OpenFegin 远程调用Coupon服务中接口来获取未来三天的秒杀活动的商品
在秒杀服务中,创建fegin调用接口,去调用Coupon的接口服务

package com.msb.mall.feign;
@FeignClient("mall-coupon")
public interface CouponFeignService {

  @GetMapping("/coupon/seckillsession/getLates3DaysSession")
  public R getLates3DaysSession();
}

Coupon服务也就是会员服务中创建接口,获取会员可以调用的 秒杀活动商品信息
controller层


@RestController
@RequestMapping("coupon/seckillsession")
public class SeckillSessionController {
      @Autowired
    private SeckillSessionService seckillSessionService;

    @GetMapping("/getLates3DaysSession")
    public R getLates3DaysSession(){
        List<SeckillSessionEntity> lates3DaysSession = seckillSessionService.getLates3DaysSession();
        String json = JSON.toJSONString(lates3DaysSession);
        return R.ok().put("data",json);
    }
}

service层

@Service("seckillSessionService")
public class SeckillSessionServiceImpl extends ServiceImpl<SeckillSessionDao, SeckillSessionEntity> implements SeckillSessionService {

    @Autowired
    SeckillSkuRelationService relationService;

 @Override
    public List<SeckillSessionEntity> getLates3DaysSession() {
        // 计算未来3天的时间
        List<SeckillSessionEntity> list =  this.list(new QueryWrapper<SeckillSessionEntity>().
                between("start_time",startTime(),endTime()));
        List<SeckillSessionEntity> newList = list.stream().map(session -> {
            // 根据对应的sessionId活动编号查询出对应的活动商品信息
            List<SeckillSkuRelationEntity> relationEntities = relationService.list(new QueryWrapper<SeckillSkuRelationEntity>()
                    .eq("promotion_session_id", session.getId()));
            session.setRelationEntities(relationEntities);
            return session;
        }).collect(Collectors.toList());
        return newList;
    }

    private String startTime(){
        LocalDate now = LocalDate.now();
        LocalDate startDay = now.plusDays(0);
        LocalTime min = LocalTime.MIN;
        LocalDateTime start = LocalDateTime.of(startDay, min);
        return start.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
    }

    private String endTime(){
        LocalDate now = LocalDate.now();
        LocalDate endDay = now.plusDays(2);
        LocalTime max = LocalTime.MAX;
        LocalDateTime end = LocalDateTime.of(endDay, max);
        return end.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
    }
}

启动服务,数据会被保存到Redis中

image.png

image.png

二、秒杀商品查询

  通过当前时间获取对应的秒杀活动及对应的SKU信息。

   /**
     * 查询出当前时间内的秒杀活动及对应的商品SKU信息
     * @return
     */
    @Override
    public List<SeckillSkuRedisDto> getCurrentSeckillSkus() {
        // 1.确定当前时间是属于哪个秒杀活动的
        long time = new Date().getTime();
        // 从Redis中查询所有的秒杀活动
        Set<String> keys = redisTemplate.keys(SeckillConstant.SESSION_CHACE_PREFIX + "*");
        for (String key : keys) {
            //seckill:sessions1656468000000_1656469800000
            String replace = key.replace(SeckillConstant.SESSION_CHACE_PREFIX, "");
            // 1656468000000_1656469800000
            String[] s = replace.split("_");
            Long start = Long.parseLong(s[0]); // 活动开始的时间
            Long end = Long.parseLong(s[1]); // 活动结束的时间
            if(time > start && time < end){
                // 说明的秒杀活动就是当前时间需要参与的活动
                // 取出来的是SKU的ID  2_9
                List<String> range = redisTemplate.opsForList().range(key, -100, 100);
                BoundHashOperations<String, String, String> ops = redisTemplate.boundHashOps(SeckillConstant.SKU_CHACE_PREFIX);
                List<String> list = ops.multiGet(range);
                if(list != null && list.size() > 0){
                    List<SeckillSkuRedisDto> collect = list.stream().map(item -> {
                        SeckillSkuRedisDto seckillSkuRedisDto = JSON.parseObject(item, SeckillSkuRedisDto.class);
                        return seckillSkuRedisDto;
                    }).collect(Collectors.toList());
                    return collect;
                }
            }
        }
        return null;
    }

然后定义相关的Controller接口就可以访问了

@RestController
@RequestMapping("/seckill")
public class SeckillController {

    @Autowired
    SeckillService seckillService;

    @GetMapping("/currentSeckillSessionSkus")
    public R getCurrentSeckillSessionSkus(){
        List<SeckillSkuRedisDto> currentSeckillSkus = seckillService.getCurrentSeckillSkus();

        return R.ok().put("data", JSON.toJSONString(currentSeckillSkus));
    }
}

然后对应的访问效果:

image.png

三、页面渲染

1.网关配置

首先在host中配置域名

image.png

然后在网关中配置路由信息

image.png

然后重启服务访问:

image.png

能访问到数据就表示域名配置成功

2.首页配置

  通过Ajax来访问获取秒杀的相关信息

  $.get("http://seckill.msb.com/seckill/currentSeckillSessionSkus",function(resp){
     if(resp.data.length > 0){
        // 说明有秒杀的数据
        console.log($.parseJSON(resp.data))
       $.parseJSON(resp.data).forEach(function(item){
         $("<li></li>").append("<img width='130px' height='130px' src='"+item.skuInfoVo.skuDefaultImg+"'/>")
                 .append("<p>"+item.skuInfoVo.skuSubtitle+"</p>")
                 .append("<span>"+item.seckillPrice+"</span>")
                 .append("<s>"+item.skuInfoVo.price+"</s>")
                 .appendTo("#seckillSessionContent");
       })
       /*<li>
       <img src="/static/index/img/section_second_list_img1.jpg" alt="">
               <p>花王 (Merries) 妙而舒 纸尿裤 大号 L54片 尿不湿(9-14千克) (日本官方直采) 花王 (Merries) 妙而舒 纸尿裤 大号 L54片 尿不湿(9-14千</p>
       <span>¥83.9</span><s>¥99.9</s>
     </li>*/

     }
  })

展示的效果

image.png

3.商品详情

  在购买商品的时候,进入到商品详情页,如果该商品也参与了秒杀活动,那么对应的需要展示相关的信息

image.png

首先我们需要在秒杀服务中提供一个根据SKUID查询相关的秒杀活动的接口

   /**
     * 根据SKUID查询秒杀活动对应的信息
     * @param skuId
     * @return
     */
    @Override
    public SeckillSkuRedisDto getSeckillSessionBySkuId(Long skuId) {
        // 1.找到所有需要参与秒杀的商品的sku信息
        BoundHashOperations<String, String, String> ops = redisTemplate.boundHashOps(SeckillConstant.SKU_CHACE_PREFIX);
        Set<String> keys = ops.keys();
        if(keys != null && keys.size() > 0){
            String regx = "\\d_"+ skuId;
            for (String key : keys) {
                boolean matches = Pattern.matches(regx, key);
                if(matches){
                    // 说明找到了对应的SKU的信息
                    String json = ops.get(key);
                    SeckillSkuRedisDto dto = JSON.parseObject(json, SeckillSkuRedisDto.class);
                    return dto;
                }
            }
        }
        return null;
    }

然后在查询商品详情的时候异步查询出对应的秒杀活动信息

image.png

然后在模板页面中展示相关的信息

<div class="box-summary clear">
                    <ul>
                        <li>京东价</li>
                        <li>
                            <span></span>
                            <span th:text="${#numbers.formatDecimal(item.info.price,3,2)}">4499.00</span>
                        </li>
                        <li style="color: red">
                            <span th:if="${#dates.createNow().getTime() < item.seckillVO.startTime}">
                                商品将在:[[${#dates.format(new java.util.Date(item.seckillVO.startTime),'yyyy-MM-dd HH:mm:ss')}]] 开始秒杀
                            </span>
                            <span th:if="${#dates.createNow().getTime() > item.seckillVO.startTime
                             && #dates.createNow().getTime() < item.seckillVO.endTime }">
                                秒杀价: [[${#numbers.formatDecimal(item.seckillVO.seckillPrice,1,2)}]]
                            </span>
                        </li>
                        <li>
                            <a href="/static/item/">
                                预约说明
                            </a>
                        </li>
                    </ul>
                </div>

首页调整到商品详情页

function goItem(skuId){
    location.href="http://item.msb.com/"+skuId+".html"
  }

  $.get("http://seckill.msb.com/seckill/currentSeckillSessionSkus",function(resp){
     if(resp.data.length > 0){
        // 说明有秒杀的数据
        console.log($.parseJSON(resp.data))
       $.parseJSON(resp.data).forEach(function(item){
         $("<li οnclick='goItem("+item.skuId+")'></li>")
                 .append("<img width='130px' height='130px' src='"+item.skuInfoVo.skuDefaultImg+"'/>")
                 .append("<p>"+item.skuInfoVo.skuSubtitle+"</p>")
                 .append("<span>"+item.seckillPrice+"</span>")
                 .append("<s>"+item.skuInfoVo.price+"</s>")
                 .appendTo("#seckillSessionContent");
       })
       /*<li>
       <img src="/static/index/img/section_second_list_img1.jpg" alt="">
               <p>花王 (Merries) 妙而舒 纸尿裤 大号 L54片 尿不湿(9-14千克) (日本官方直采) 花王 (Merries) 妙而舒 纸尿裤 大号 L54片 尿不湿(9-14千</p>
       <span>¥83.9</span><s>¥99.9</s>
     </li>*/

     }
  })

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1001062.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

linux系统移植到开发板简要过程(移植bootloader引导加载程序---移植linux内核---制作根文件系统)

一.标准linux启动过程图 对于linux启动流程分析&#xff0c;我们需要移植bootloader引导加载程序---移植linux内核---制作根文件系统镜像文件&#xff1b; 二.为什么进行系统移植&#xff1f; 对于不同的硬件平台&#xff0c;linux系统启动流程大体相同&#xff0c;但是资源需求…

多线程的创建

一、基本概念 1 cpu CPU的中文名称是中央处理器&#xff0c;是进行逻辑运算用的&#xff0c;主要由运算器、控制器、寄存器三部分组成&#xff0c;从字面意思看就是运算就是起着运算的作用&#xff0c;控制器就是负责发出cpu每条指令所需要的信息&#xff0c;寄存器就是保存运…

spaCy库的实体链接踩坑,以及spaCy-entity-linker的knowledge_base下载问题

问题1. spacy Can’t find factory for ‘entityLinker’ 1&#xff09;问题 写了一个实体链接类&#xff0c;代码如下&#xff1a; nlp spacy.load("en_core_web_md")class entieyLink:def __init__(self, doc, nlp):self.nlp nlpself.doc self.nlp(doc)# Che…

MATLAB入门-矩阵的运算

MATLAB入门-矩阵的运算 本篇文章为学习笔记&#xff0c;课程链接为&#xff1a;头歌 相关知识 常见的矩阵运算有算术运算、关系运算和逻辑运算。MATLAB中的所有变量都是以矩阵的形式存储的&#xff0c;单个变量就相当于一个1*1的矩阵。 算术运算 下面展示的是常见的矩阵之…

云负载均衡

华为云&#xff1a;弹性负载均衡&#xff08;ELB&#xff09; 服务列表----弹性负载均衡 腾讯云&#xff1a;负载均衡 阿里云&#xff1a;弹性负载均衡&#xff08;SLB&#xff09;【ALB NLB CLB】 云服务&#xff1a; 云弹性负载均衡&#xff08;ELB/SLB&#xff09; 云服务…

Unity3D之简单溶解特效制作

文章目录 新建Shader Graph设置参数新建Step节点新建Simple Noise节点查看效果 新建Shader Graph 这里选择 Shader Graph -> URP -> Unlit Shader Graph 创建 设置参数 把 Surface Type 改成 Transparent 新建Step节点 创建一个Step的节点 把 Step 的 Out 连接到 Frag…

Java8-17 --- idea2022

目录 一、idea官网 二、使用idea编写hello world 三、查看工程中的JDK配置信息 四、详细设置 4.1、显示工具栏 4.2、默认启动项目配置 4.3、取消自动更新 4.4、选择整体主体与背景图 4.5、设置编辑器主题样式 4.5.1、编辑器主题 4.5.2、字体大小 4.5.3、修改注…

JS看板:bryntum taskboard 5.5.2 Crack

Bryntum 任务板是一个灵活的看板 Web 组件&#xff0c;可帮助您可视化和管理您的工作。 任务板非常灵活&#xff0c;允许您完全自定义卡片、列和泳道的渲染和样式。借助丰富的 API&#xff0c;您甚至可以在运行时打开或关闭功能。 在繁忙的团队中跟踪任务可能会令人畏惧。任务…

AMD GPU 内核驱动架构分析(一)

在Linux系统中&#xff0c;GPU驱动是集成在DRM框架中的&#xff0c;AMD GPU的内核驱动结构是一个复杂的软件堆栈&#xff0c;负责管理和控制AMD图形硬件&#xff0c;以便应用程序可以与GPU进行通信并利用其图形处理能力。以下是AMD GPU内核驱动的主要组成部分&#xff1a; 硬件…

【操作系统】聊聊进程、线程、协程

进程内部有那些数据 为什么创建进程的成本高 进程和线程 进程是资源分配的基本单位&#xff0c;而线程是程序执行的基本单位&#xff0c;一个是从资源分配的角度看&#xff0c;另一个是执行角度。 那么进程和程序的区别是什么&#xff1f; 程序&#xff0c;一段代码&#xff…

Linux 6.6 初步支持AMD 新一代 Zen 5 处理器

AMD 下一代 Zen 5 CPU 现已开始为 Linux 6.6 支持提交相关代码&#xff0c;最新补丁包括提供温度监控和 EDAC 报告等。 最新的 Linux 6.6 代码中已经加入了包括支持硬件监视器温度监控和 EDAC 报告的补丁。此外&#xff0c;新版本还加入了 x86 / misc 补丁&#xff0c;Phoronix…

9.11C高级day4

实现一个对数组求和的函数&#xff0c;数组通过实参传递给函数 sum0 function add() {for i in $*  #$*接收传来的所有参数do((sumi))doneecho $sum }#定义一个数组 arr(1 2 3 4 5 7 9)#向函数传参 add ${arr[*]}写一个函数&#xff0c;输出当前用户的uid和gid&#xff0c;并…

shell中分支语句,循环语句,函数

实现对一个数组求和的函数&#xff0c;将数组作为实参传给函数 #!/bin/bash sum() {for i in $do((sumi))doneecho $sum} read -p "请输入一组数字: " -a arr sum ${arr[*]}2 调用函数&#xff0c;输出当前用户的uid gid 并使用变量接收结果 #!/bin/bashget() {uid…

R语言发送邮件丨blastula包使用教程

R语言自动发送邮件 今天分享一个小技巧&#xff0c;用R语言脚本实现STMP邮件自动发送功能。 生信分析实际操作过程中&#xff0c;可能会偶尔会遇到耗时比较久的计算&#xff0c;比如基因组上游分析GATK标准流程往往耗时几天时间。 使用R语言自动发送邮件&#xff0c;在关键节点…

【性能测试】Jmeter —— jmeter计数器

jmeter计数器 如果需要引用的数据量较大&#xff0c;且要求不能重复或者需要递增&#xff0c;那么可以使用计数器来实现 如&#xff1a;新增功能&#xff0c;要求名称不能重复 1&#xff0c;新增计数器 计数器&#xff1a;允许用户创建一个在线程组之内都可以被引用的计数器…

LeGo-LOAM 源码解析

文章目录 0、整体框架1、imageProjection —— 点云分割0. main()1. cloudHandler()2. copyPointCloud()3. findStartEndAngle()4. projectPointCloud()5. groundRemoval()6. cloudSegmentation()7. labelComponents()8. publishCloud()9. resetParameters() 2、featureAssocia…

宠物互联网医院|宠物互联网医院掌上宠物的健康助手

宠物互联网医院依托于互联网技术&#xff0c;将宠物健康管理与现代科技相结合&#xff0c;为宠物主人们提供了全方位、便捷的养宠服务。通过智能手机APP&#xff0c;宠物主人不仅能够快速轻松地了解自己宠物的健康状况&#xff0c;还能够与兽医进行实时的在线咨询、预约就诊。不…

迷你无人车 Navigation 导航(3)

迷你无人车 Navigation 导航&#xff08;3&#xff09; 自己实现了对于迷你无人车关节的控制&#xff0c;由于原本的关节布置仅支持阿克曼转向&#xff0c;因此先进行阿克曼转向的控制 修改 URDF 文件 添加 transmission 标签&#xff0c;定义关节的驱动 <transmission …

MySQL Oracle区别

由于SQL Server不常用&#xff0c;所以这里只针对MySQL数据库和Oracle数据库的区别 (1) 对事务的提交 MySQL默认是自动提交&#xff0c;而Oracle默认不自动提交&#xff0c;需要用户手动提交&#xff0c;需要在写commit;指令或者点击commit按钮 (2) 分页查询 MySQL是直接在SQL语…

使用鳄鱼指标和ADX开立空头的条件,3秒讲清楚

使用鳄鱼指标和ADX开立空头的条件其实很简单&#xff0c;anzo capital昂首资本3秒钟讲清楚。 首先&#xff0c;市场行情需呈水平状态。再者&#xff0c;均线体系开始向上发散&#xff0c;给出明确的信号。最后&#xff0c;ADX确认该信号&#xff0c;要求指数上涨20%以上&#…