推广

如何使用feign直接调用XXL-JOB平台API

iseeyu3年前 (2024-02-22)推广135

image.png

三、潜在问题
  1. 网络开销:
    每次调用接口如果都请求一次登录接口,难免会产生额外的网络开销,可以通过redis缓存cookie值去处理。
  2. 登录失效:
    由于调度中心cookie有效时间为2小时,需每两小时登录一次,获取新的cookie,可以通过重试机制,实现过期重新登录
    解决方案:可以参考 XxlJobComponent.java
四、代码实现
  1. 引入相关jar
<dependency>
  <groupId>org.springframework.cloud</groupId>
  <artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<dependency>
  <groupId>com.xuxueli</groupId>
  <artifactId>xxl-job-core</artifactId>
  <version>2.3.0</version>
</dependency>
  1. XxlJobClient.java
import com.alibaba.fastjson.JSONObject;
import com.gaodun.pms.cdp.common.dto.external.xxljob.HttpResultForXxlJob;
import feign.Response;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;
 
import java.util.Map;
 
/**
 * xxl-job客户端
 *
 * @author liudong
 * @date 2021/4/25 16:33
 */
@FeignClient(name = "xxlJobClient", url = "${third-party.config.xxl-job.host:not found xxl-job service url}")
public interface XxlJobClient {
    /**
     * xxl-job登录接口
     *
     * @param params 参数
     * @return 响应信息
     */
    @PostMapping(value = "/xxl-job-admin/login", consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
    Response login(@RequestBody Map<String, ?> params);
 
    /**
     * 创建定时任务
     *
     * @param cookie cookie
     * @param params 定时任务参数
     * @return 定时任务ID
     */
    @PostMapping(value = "/xxl-job-admin/jobinfo/add", consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
    HttpResultForXxlJob<Integer> add(@RequestHeader("Cookie") String cookie, @RequestBody Map<String, ?> params);
 
    /**
     * 更新定时任务
     *
     * @param cookie cookie
     * @param params 定时任务更新参数
     * @return 执行结果
     */
    @PutMapping(value = "/xxl-job-admin/jobinfo/update", consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
    HttpResultForXxlJob<String> update(@RequestHeader("Cookie") String cookie, @RequestBody Map<String, ?> params);
 
    /**
     * 删除定时任务
     *
     * @param cookie cookie
     * @param id     定时任务更新参数
     * @return 执行结果
     */
    @DeleteMapping(value = "/xxl-job-admin/jobinfo/remove")
    HttpResultForXxlJob<String> remove(@RequestHeader("Cookie") String cookie, @RequestParam("id") int id);
 
    /**
     * 开启任务
     *
     * @param cookie cookie
     * @param id     定时任务ID
     * @return 执行结果
     */
    @PutMapping(value = "/xxl-job-admin/jobinfo/start")
    HttpResultForXxlJob<String> start(@RequestHeader("Cookie") String cookie, @RequestParam("id") int id);
 
    /**
     * 结束任务
     *
     * @param cookie cookie
     * @param id     定时任务ID
     * @return 执行结果
     */
    @PutMapping(value = "/xxl-job-admin/jobinfo/stop")
    HttpResultForXxlJob<String> stop(@RequestHeader("Cookie") String cookie, @RequestParam("id") int id);
 
    /**
     * 结束任务
     *
     * @param cookie cookie
     * @param params 查询参数
     * @return 执行结果
     */
    @GetMapping(value = "/xxl-job-admin/joblog/pageList")
    JSONObject log(@RequestHeader("Cookie") String cookie, @RequestParam("params") Map<String, Object> params);
}
  1. XxlJobComponent.java
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.http.HttpStatus;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.gaodun.pms.cdp.common.constant.CacheConstant;
import com.gaodun.pms.cdp.common.constant.XxlJobConstant;
import com.gaodun.pms.cdp.common.dto.external.xxljob.HttpResultForXxlJob;
import com.gaodun.pms.cdp.common.dto.xxljob.XxlJobLogDTO;
import com.gaodun.pms.cdp.common.exception.ErrorCode;
import com.gaodun.pms.cdp.common.request.xxljob.AddOrUpdateXxlJobInfoRequest;
import com.gaodun.pms.cdp.service.acm.ApplicationConfig;
import com.gaodun.pms.cdp.service.acm.JobConfig;
import com.gaodun.pms.cdp.service.external.feign.XxlJobClient;
import com.gaodunwangxiao.pms.exception.AbstractAssert;
import com.gaodunwangxiao.pms.exception.ExceptionFactory;
import com.gaodunwangxiao.pms.exception.SystemException;
import feign.FeignException;
import feign.Response;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.assertj.core.util.Lists;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.retry.annotation.Backoff;
import org.springframework.retry.annotation.Recover;
import org.springframework.retry.annotation.Retryable;
import org.springframework.stereotype.Component;
 
import javax.annotation.Resource;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
 
/**
 * 任务管理处理器
 *
 * @author liudong
 * @date 2021/4/25 10:56
 */
@Slf4j
@Component
public class XxlJobComponent {
 
    /**
     * xxl job 账号
     */
    @Value("${xxl.job.user-name}")
    private String userName;
 
    /**
     * xxl job 密码
     */
    @Value("${xxl.job.password}")
    private String password;
 
    /**
     * xxl-job客户端
     */
    @Resource
    private XxlJobClient xxlJobClient;
 
    /**
     * 应用全局配置
     */
    @Resource
    private ApplicationConfig applicationConfig;
    /**
     * redis操作类
     */
    @Resource
    private RedisTemplate<String, Object> redisTemplate;
 
    /**
     * 登录xxl-job
     */
    public void login() {
        Map<String, Object> userInfo = new HashMap<>(MapUtil.DEFAULT_INITIAL_CAPACITY);
        userInfo.put("userName", userName);
        userInfo.put("password", password);
        // 设置cookie永久有效,对应xxl-job记住密码
        userInfo.put("ifRemember", "on");
        Response response = xxlJobClient.login(userInfo);
        if (HttpStatus.HTTP_OK == response.status()) {
            response.headers().get(XxlJobConstant.COOKIE_KEY).forEach(e -> {
                if (e.contains(XxlJobConstant.XXL_JOB_LOGIN_IDENTITY)) {
                    redisTemplate.opsForValue().set(CacheConstant.XXL_JOB_COOKIE_REDIS_KEY, e, CacheConstant.XXL_JOB_COOKIE_REDIS_TIMEOUT, TimeUnit.HOURS);
                }
            });
        } else {
            throw ExceptionFactory.systemException(ErrorCode.LOGIN_XXL_JOB_FAILURE_EXCEPTION);
        }
    }
 
    /**
     * 创建任务
     *
     * @param addOrUpdateXxlJobInfoRequest 任务参数
     * @return 任务ID
     */
 
    public Integer add(AddOrUpdateXxlJobInfoRequest addOrUpdateXxlJobInfoRequest) {
        if (Boolean.FALSE.equals(redisTemplate.hasKey(CacheConstant.XXL_JOB_COOKIE_REDIS_KEY))) {
            login();
        }
        if (ObjectUtils.isNotEmpty(addOrUpdateXxlJobInfoRequest)) {
            HttpResultForXxlJob result = xxlJobClient.add(String.valueOf(redisTemplate.opsForValue().get(CacheConstant.XXL_JOB_COOKIE_REDIS_KEY)), BeanUtil.beanToMap(addOrUpdateXxlJobInfoRequest));
            if (HttpStatus.HTTP_OK == result.getCode()) {
                log.info(result.getMsg());
                return (int) result.getContent();
            }
        }
        return null;
    }
 
    /**
     * 更新任务
     *
     * @param addOrUpdateXxlJobInfoRequest 任务参数
     */
    public void update(AddOrUpdateXxlJobInfoRequest addOrUpdateXxlJobInfoRequest) {
        if (Boolean.FALSE.equals(redisTemplate.hasKey(CacheConstant.XXL_JOB_COOKIE_REDIS_KEY))) {
            login();
        }
        if (ObjectUtils.isNotEmpty(addOrUpdateXxlJobInfoRequest)) {
            HttpResultForXxlJob result = xxlJobClient.update(String.valueOf(redisTemplate.opsForValue().get(CacheConstant.XXL_JOB_COOKIE_REDIS_KEY)), BeanUtil.beanToMap(addOrUpdateXxlJobInfoRequest));
            log.info(result.getMsg());
            AbstractAssert.isTrue(HttpStatus.HTTP_OK == result.getCode(), ErrorCode.UPDATE_JOB_FAILURE_EXCEPTION);
        }
    }
 
    /**
     * 删除任务
     *
     * @param id 任务ID
     */
    public void remove(Integer id) {
        if (Boolean.FALSE.equals(redisTemplate.hasKey(CacheConstant.XXL_JOB_COOKIE_REDIS_KEY))) {
            login();
        }
        if (ObjectUtils.isNotEmpty(id)) {
            HttpResultForXxlJob result = xxlJobClient.remove(String.valueOf(redisTemplate.opsForValue().get(CacheConstant.XXL_JOB_COOKIE_REDIS_KEY)), id);
            log.info(result.getMsg());
            AbstractAssert.isTrue(HttpStatus.HTTP_OK == result.getCode(), ErrorCode.REMOVE_JOB_FAILURE_EXCEPTION);
        }
    }
 
 
    /**
     * 启动任务
     *
     * @param id 任务ID
     */
    public void start(Integer id) {
        if (Boolean.FALSE.equals(redisTemplate.hasKey(CacheConstant.XXL_JOB_COOKIE_REDIS_KEY))) {
            login();
        }
        if (ObjectUtils.isNotEmpty(id)) {
            HttpResultForXxlJob result = xxlJobClient.start(String.valueOf(redisTemplate.opsForValue().get(CacheConstant.XXL_JOB_COOKIE_REDIS_KEY)), id);
            log.info(result.getMsg());
            AbstractAssert.isTrue(HttpStatus.HTTP_OK == result.getCode(), ErrorCode.START_JOB_FAILURE_EXCEPTION);
        }
    }
 
    /**
     * 停止任务
     *
     * @param id 任务ID
     */
    public void stop(Integer id) {
        if (Boolean.FALSE.equals(redisTemplate.hasKey(CacheConstant.XXL_JOB_COOKIE_REDIS_KEY))) {
            login();
        }
        if (ObjectUtils.isNotEmpty(id)) {
            HttpResultForXxlJob result = xxlJobClient.stop(String.valueOf(redisTemplate.opsForValue().get(CacheConstant.XXL_JOB_COOKIE_REDIS_KEY)), id);
            log.info(result.getMsg());
            AbstractAssert.isTrue(HttpStatus.HTTP_OK == result.getCode(), ErrorCode.STOP_JOB_FAILURE_EXCEPTION);
        }
    }
 
    /**
     * 查询日志
     *
     * @param params 查询参数
     * @return 结果集
     */
    @Retryable(value = SystemException.class, backoff = @Backoff(delay = 2000L, multiplier = 1.5))
    public List<XxlJobLogDTO> log(Map<String, Object> params) {
        try {
            if (Boolean.FALSE.equals(redisTemplate.hasKey(CacheConstant.XXL_JOB_COOKIE_REDIS_KEY))) {
                login();
            }
            if (ObjectUtils.isEmpty(params)) {
                return Lists.newArrayList();
            }
            JSONObject result = xxlJobClient.log(String.valueOf(redisTemplate.opsForValue().get(CacheConstant.XXL_JOB_COOKIE_REDIS_KEY)), params);
            if (ObjectUtils.isNotEmpty(result) && ObjectUtils.isNotEmpty(result.getString("data"))) {
                return JSON.parseArray(result.getString("data"), XxlJobLogDTO.class);
            }
 
        } catch (FeignException e) {
            redisTemplate.delete(CacheConstant.XXL_JOB_COOKIE_REDIS_KEY);
            throw ExceptionFactory.systemException("远程操作xxl-job失败,进行重试!", e);
        }
        return Lists.newArrayList();
    }
 
 
    /**
     * 重试次数达到最大后回调处理
     *
     * @param systemException 重试异常
     */
    @Recover
    public void recoverCallback(SystemException systemException) {
        log.error("远程操作xxl-job异常!", systemException);
    }
 
}
五、测试用例:
import cn.hutool.core.bean.BeanUtil;
import com.gaodun.pms.cdp.common.dto.xxljob.XxlJobInfoDTO;
import com.gaodun.pms.cdp.common.enums.MisfireStrategyEnum;
import com.gaodun.pms.cdp.common.request.xxljob.AddOrUpdateXxlJobInfoRequest;
import com.gaodun.pms.cdp.web.CdpApplication;
import feign.Response;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.BeanUtils;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

import javax.annotation.Resource;
import java.util.HashMap;
import java.util.Map;

/**
 * xxl-job api Test
 *
 * @author liudong
 * @date 2021/4/26 9:45
 */
@RunWith(SpringRunner.class)
@SpringBootTest(classes = CdpApplication.class)
public class XxlJobClientTest {

    @Resource
    private XxlJobClient xxlJobClient;

    @Test
    public void login() {
    }

    @Test
    public void add() {
        Map<String, Object> hashMap = new HashMap(2);
        hashMap.put("userName", "admin");
        hashMap.put("password", "123456");
        Response response = xxlJobClient.login(hashMap);
        AddOrUpdateXxlJobInfoRequest addOrUpdateXxlJobInfoRequest = new AddOrUpdateXxlJobInfoRequest();
        addOrUpdateXxlJobInfoRequest.setJobGroup(2);
        addOrUpdateXxlJobInfoRequest.setJobDesc("test");
        addOrUpdateXxlJobInfoRequest.setAuthor("liudong");
        addOrUpdateXxlJobInfoRequest.setAlarmEmail("");
        addOrUpdateXxlJobInfoRequest.setScheduleType("CRON");
        addOrUpdateXxlJobInfoRequest.setScheduleConf("0/6 * * * * ?");
        addOrUpdateXxlJobInfoRequest.setGlueType("BEAN");
        addOrUpdateXxlJobInfoRequest.setExecutorHandler("testHandler");
        addOrUpdateXxlJobInfoRequest.setExecutorRouteStrategy("FIRST");
        addOrUpdateXxlJobInfoRequest.setMisfireStrategy(MisfireStrategyEnum.DO_NOTHING.toString());
        addOrUpdateXxlJobInfoRequest.setExecutorBlockStrategy("SERIAL_EXECUTION");
        XxlJobInfoDTO xxlJobInfoDTO = new XxlJobInfoDTO();
        BeanUtils.copyProperties(addOrUpdateXxlJobInfoRequest, xxlJobInfoDTO);
        Map<String, Object> stringObjectMap = BeanUtil.beanToMap(addOrUpdateXxlJobInfoRequest);
        response.headers().get("set-cookie").forEach(e -> {
            if (e.contains("XXL_JOB_LOGIN_IDENTITY")) {
                System.out.println(xxlJobClient.add(e, stringObjectMap).toString());
            }
        });
    }

    @Test
    public void update() {
        Map<String, Object> hashMap = new HashMap(2);
        hashMap.put("userName", "admin");
        hashMap.put("password", "123456");
        Response response = xxlJobClient.login(hashMap);
        AddOrUpdateXxlJobInfoRequest addOrUpdateXxlJobInfoRequest = new AddOrUpdateXxlJobInfoRequest();
        addOrUpdateXxlJobInfoRequest.setId(14);
        addOrUpdateXxlJobInfoRequest.setJobGroup(2);
        addOrUpdateXxlJobInfoRequest.setJobDesc("update");
        addOrUpdateXxlJobInfoRequest.setAuthor("liudong");
        addOrUpdateXxlJobInfoRequest.setAlarmEmail("");
        addOrUpdateXxlJobInfoRequest.setScheduleType("CRON");
        addOrUpdateXxlJobInfoRequest.setScheduleConf("0/6 * * * * ?");
        addOrUpdateXxlJobInfoRequest.setGlueType("BEAN");
        addOrUpdateXxlJobInfoRequest.setExecutorHandler("testHandler");
        addOrUpdateXxlJobInfoRequest.setExecutorRouteStrategy("FIRST");
        addOrUpdateXxlJobInfoRequest.setMisfireStrategy(MisfireStrategyEnum.DO_NOTHING.toString());
        addOrUpdateXxlJobInfoRequest.setExecutorBlockStrategy("SERIAL_EXECUTION");
        XxlJobInfoDTO xxlJobInfoDTO = new XxlJobInfoDTO();
        BeanUtils.copyProperties(addOrUpdateXxlJobInfoRequest, xxlJobInfoDTO);
        Map<String, Object> stringObjectMap = BeanUtil.beanToMap(addOrUpdateXxlJobInfoRequest);
        response.headers().get("set-cookie").forEach(e -> {
            if (e.contains("XXL_JOB_LOGIN_IDENTITY")) {
                System.out.println(xxlJobClient.update(e, stringObjectMap).toString());
            }
        });
    }

    @Test
    public void remove() {
        Map<String, Object> hashMap = new HashMap(2);
        hashMap.put("userName", "admin");
        hashMap.put("password", "123456");
        Response response = xxlJobClient.login(hashMap);
        response.headers().get("set-cookie").forEach(e -> {
            if (e.contains("XXL_JOB_LOGIN_IDENTITY")) {
                System.out.println(xxlJobClient.remove(e, 23).toString());
            }
        });
    }

    @Test
    public void start() {
        Map<String, Object> hashMap = new HashMap(2);
        hashMap.put("userName", "admin");
        hashMap.put("password", "123456");
        Response response = xxlJobClient.login(hashMap);
        response.headers().get("set-cookie").forEach(e -> {
            if (e.contains("XXL_JOB_LOGIN_IDENTITY")) {
                System.out.println(xxlJobClient.start(e, 22).toString());
            }
        });
    }

    @Test
    public void stop() {
        Map<String, Object> hashMap = new HashMap(2);
        hashMap.put("userName", "admin");
        hashMap.put("password", "123456");
        Response response = xxlJobClient.login(hashMap);
        response.headers().get("set-cookie").forEach(e -> {
            if (e.contains("XXL_JOB_LOGIN_IDENTITY")) {
                System.out.println(xxlJobClient.stop(e, 22).toString());
            }
        });
    }
}

扫描二维码推送至手机访问。

版权声明:本文由西安泽虎代运营发布,如需转载请注明出处。

转载请注明出处https://www.0291.com.cn/post/56235.html

相关文章

西安企业做百度推广,一个月花三千和花三万到底差在哪?

4|最近跟几个西安的老板聊天,发现一个挺有意思的现象:同样做百度推广,有人一个月花三千块,询盘不断;有人一个月砸三万,水花都没见着。问他们区别在哪,大多数人说不清楚,只知道'钱花了,没效果'。 5| 6|百度推广这东西,说复杂也复杂,说简单也简单。核心就一件事:让你的潜在客户搜某个词的时候,你的信息...

我想当策划,大学应该选什么专业?

我想当策划,大学应该选什么专业?

学,广告,传播,公关,这些专业其实都可以。另外也可以学像汉语言文学,以及一些跟文学相关的一些专业,会对你找工作有帮助。但是,你想从事这个这份职业,除了专业的学习之外,更多的是,你要在上学的时候积极参与一些更营销策划相关的社会实践。比如说你可以做一些兼职,比如说帮别人去写稿,...

服装市场营销策略分析,“定位不慎满盘皆输”

服装市场营销策略分析,“定位不慎满盘皆输”

不同的区域需要不同的策略,而不同的营销策略需要不同的销售思路来配合。因此,在研究女装产品销售思路之前,最好先对于市场与营销策略做一次深入地了解。1.市场区域化(market segmentation):目标营销的第一步,是将整个市场拆分成若干个同性质的小市场。2.目标市场的...

晚间悦读丨你的思维方式,决定你的人生高度!

晚间悦读丨你的思维方式,决定你的人生高度!

越长大,越发现,能够决定你人生高度的,往往是你的认知层次。 你的认知在哪个层级,你的人生就处在什么状态。你认知的高度,决定了你人生的高度。 那如何才能升级方式、提升认知能力呢?可以从这三个方面做出改变。 NO. 1 改变态度 有人...

编写项目营销策划方案六大要点

编写项目营销策划方案六大要点

现在商业发展非常迅速,的需求非常的大,但是要做好营销策划是有一定难度的,我把自己做营销策划的一些体会在这里分享给朋友们。营销策划方案六大要点我们先说项目营销策划方案这个话题。大部分的营销策划人都是在企业里工作,大部分项目之初都是来源于一个想法,创始人、老板或者创始团队的一个...

【商场营销策划】如何进行商场营销策划?

【商场营销策划】如何进行商场营销策划?

商场是策划者们关注的永恒话题,那么究竟该如何作好商场营销策划呢?掌握以下这几点营销策略设计原则,至关重要!1.义利兼顾的原则。商场在获取利润的同时要充分考虑到消费者的合法利益和商场的长远利益。在作商场活动营销策略方案的时候应该将这一点作为首要的原则。对商场有利而对顾客不利的...

现在,非常期待与您的又一次邂逅

我们努力让每一部企业宣传片和抖音短视频成为商业大片