使用spring-boot2.0.4集成quartz多线程实现定时任务(极光推送)

使用quartz实现多线程定时任务(极光推送),通过订单号尾数去处理会重复推送问题,如果需要更多的线程,可以使用分布式锁。
pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.demo</groupId>
    <artifactId>demo</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.0.4.RELEASE</version>
    </parent>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <mybatis-plus.version>3.3.2</mybatis-plus.version>
        <oracle.driver.version>11.2.0.3</oracle.driver.version>
        <java.version>1.8</java.version>
        <lib.path>${basedir}/lib</lib.path>
        <framework.version>1.7</framework.version>
        <quartz.version>2.3.2</quartz.version>
        <slf4j.version>1.7.25</slf4j.version>
    </properties>

    <dependencies>
        <!--全栈式Web开发 包括Tomcat和spring-webmvc-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!--添加freemarker启动器依赖-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-freemarker</artifactId>
        </dependency>
        <!--引入JDBC-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
        </dependency>
        <!-- 引入Oracle驱动包 -->
        <dependency>
            <groupId>com.oracle</groupId>
            <artifactId>ojdbc6</artifactId>
            <version>${oracle.driver.version}</version>
            <scope>runtime</scope>
        </dependency>
        <!-- mybatis-plus -->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>${mybatis-plus.version}</version>
        </dependency>
        <!--通过简单的注解的形式 简化java bean代码-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <!--aop面向切面编程-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-aop</artifactId>
        </dependency>
        <!--热部署-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <!--字符串处理与校验的工具包-->
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-lang3</artifactId>
            <version>3.9</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.75</version>
        </dependency>
        <!--极光提供https推送操作的相关依赖包-->
        <dependency>
            <groupId>cn.jpush.api</groupId>
            <artifactId>jiguang-common</artifactId>
            <version>1.1.1</version>
        </dependency>
        <dependency>
            <groupId>cn.jpush.api</groupId>
            <artifactId>jpush-client</artifactId>
            <version>3.3.4</version>
        </dependency>
        <dependency>
            <groupId>org.quartz-scheduler</groupId>
            <artifactId>quartz</artifactId>
            <version>${quartz.version}</version>
        </dependency>
        <dependency>
            <groupId>org.quartz-scheduler</groupId>
            <artifactId>quartz-jobs</artifactId>
            <version>${quartz.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-quartz</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context-support</artifactId>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.slf4j/slf4j-api -->
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>${slf4j.version}</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

application.yml配置
以下有两个key的配置,如果只需一个则写一个appKey和secret即可。

hm:
  appKey: app申请的key
  secret: app申请的密钥
  salesmanAppKey: app申请的密钥
  salesmanSecret: app申请的密钥
  threadId: 0

application-quartz.yml配置

quartz:
  # jobGroup名称一致的情况下,不可出现相同jobName
  jobs[0]:
    jobName: 推送订单消息到APP-尾数01
    # 以服务名为组名
    jobGroup: hm
    # 业务逻辑处理类的包名
    jobClassName: com.zhitengda.job.PushMessageToAppJobOne
    # cron表达式 每10秒执行一次
    cronExpression: 0/10 * * * * ?
    # 任务状态 1 正常 0 暂停
    triggerState: 1
    # 排序
    sort: 1
  jobs[1]:
    jobName: 推送订单消息到APP-尾数23
    # 以服务名为组名
    jobGroup: hm
    # 业务逻辑处理类的包名
    jobClassName: com.zhitengda.job.PushMessageToAppJobTwo
    # cron表达式 每10秒执行一次
    cronExpression: 0/10 * * * * ?
    # 任务状态 1 正常 0 暂停
    triggerState: 1
    # 排序
    sort: 2
  jobs[2]:
    jobName: 推送订单消息到APP-尾数45
    # 以服务名为组名
    jobGroup: hm
    # 业务逻辑处理类的包名
    jobClassName: com.zhitengda.job.PushMessageToAppJobThree
    # cron表达式 每10秒执行一次
    cronExpression: 0/10 * * * * ?
    # 任务状态 1 正常 0 暂停
    triggerState: 1
    # 排序
    sort: 3
  jobs[3]:
    jobName: 推送订单消息到APP-尾数67
    # 以服务名为组名
    jobGroup: hm
    # 业务逻辑处理类的包名
    jobClassName: com.zhitengda.job.PushMessageToAppJobFour
    # cron表达式 每10秒执行一次
    cronExpression: 0/10 * * * * ?
    # 任务状态 1 正常 0 暂停
    triggerState: 1
    # 排序
    sort: 4
  jobs[4]:
    jobName: 推送订单消息到APP-尾数89
    # 以服务名为组名
    jobGroup: hm
    # 业务逻辑处理类的包名
    jobClassName: com.zhitengda.job.PushMessageToAppJobFive
    # cron表达式 每10秒执行一次
    cronExpression: 0/10 * * * * ?
    # 任务状态 1 正常 0 暂停
    triggerState: 1
    # 排序
    sort: 5

对应的处理类
在这里插入图片描述
这里只提供一个PushMessageToAppJobOne,其它一样的

@PersistJobDataAfterExecution
@DisallowConcurrentExecution
public class PushMessageToAppJobOne implements Job, Serializable {

    @Autowired
    private TabAppMessagesServie tabAppMessagesServie;

    @Override
    public void execute(JobExecutionContext jobExecutionContext) {
        try {
            List<String> mantissa = new ArrayList<>();
            mantissa.add("0");
            mantissa.add("1");
            tabAppMessagesServie.pushMessageToApp(mantissa);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}

服务实现类

@Slf4j
@Service
public class TabAppMessagesServiceImpl extends ServiceImpl<TabAppMessagesMapper, AppMessage> implements TabAppMessagesServie {

    @Value("${hm.appKey}")
    private String appKey;
    @Value("${hm.secret}")
    private String secret;
    @Value("${hm.salesmanAppKey}")
    private String salesmanAppKey;
    @Value("${hm.salesmanSecret}")
    private String salesmanSecret;
    @Value("${hm.threadId}")
    private Long threadId;

    @Autowired
    private TabAppMessagesMapper tabAppMessagesMapper;

    @Override
    public List<AppMessage> getNeedPushMessage(AppMessageQry messageQry) {
        return null;
    }

    @Override
    public void pushMessageToApp(List<String> mantissa) {
        try {
            AppMessageQry messageQry = new AppMessageQry();
            messageQry.setThreadId(threadId);
            messageQry.setMantissa(mantissa);
            List<AppMessage> messages = tabAppMessagesMapper.getNeedPushMessage(messageQry);
            if (CollectionUtils.isNotEmpty(messages)) {
                for (AppMessage message : messages) {
                    AppMessage result = pushMessage(message);
                    tabAppMessagesMapper.updateAppMessage(result);
                }
            }
        } catch (Exception e) {
            log.error(null, e);
        }
    }

    public AppMessage pushMessage(AppMessage message) {
        AppMessage result = new AppMessage();
        try {
            result.setGuid(message.getGuid());
            result.setPushCount(message.getPushCount() == null ? 1 : message.getPushCount() + 1);
            JPushClient jpushClient;
            if (MessageTypeEnum.DISPATCH.getCode().equals(message.getMessageType())) {
                jpushClient = new JPushClient(salesmanSecret, salesmanAppKey, null, ClientConfig.getInstance());
            } else {
                jpushClient = new JPushClient(secret, appKey, null, ClientConfig.getInstance());
            }
            log.info("<<<<<<<<< 推送消息类型: {} >>>>>>>>>", message.getMessageType());
            Map<String, String> map = new HashMap<String, String>();
            map.put("content", message.getContent());
            map.put("messageType", message.getMessageType());
            // 由于运单号会为空,原封装运单号message.getBillCode()变更为使用订单号
            map.put("messageId", message.getOrderCode());

            String alias = message.getEmpCode();
            PushPayload pushPayload = PushPayload.newBuilder().setPlatform(Platform.android())
                    .setAudience(Audience.alias(alias))
                    .setNotification(Notification.android(message.getContent(), message.getMessageTitle(), map)).build();
            Long start = System.currentTimeMillis();
            PushResult pushResult = jpushClient.sendPush(pushPayload);
            log.info("<<<<<<<<< 极光推送耗时:{}秒 >>>>>>>>>", (System.currentTimeMillis() - start));
            if (pushResult.isResultOK()) {
                result.setPushRemark("消息id:" + pushResult.msg_id + "推送成功");
                result.setStatus(1L);
                result.setSendSuccessDate(new Date());
                log.info("<<<<<<<<< 极光推送成功 >>>>>>>>>");
            }
        } catch (APIRequestException e) {
            Gson gson = new Gson();
            String msg = e.getMessage();
            PushResult pushResult = gson.fromJson(msg, PushResult.class);
            result.setPushRemark(pushResult.error.getMessage());
            result.setStatus(-1L);
            log.error("极光推送失败API异常信息: {}", msg);
        } catch (Exception e) {
            String msg = e.getMessage();
            if (msg.length() > 0) {
                msg = msg.substring(0, 200);
            }
            result.setPushRemark(msg);
            result.setStatus(-1L);
            log.error("极光推送失败Exception异常信息: {}", e.getMessage());
        }
        return result;
    }

}

最后就可以实现推送到app了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值