• springboot+quartz+redis用法,防止任务并发执行


      关于springboot+quartz用法,在上一篇博客已经详细说过(https://www.cnblogs.com/personblog/p/14030746.html),本文不在细说,本文重点是在项目中添加redis类的使用.

      值得注意的是,创建项目时,最好要规范些,避免不必要的麻烦,像config、model、service、util等包,最好创建在主包下面,也就是Application启动类的上面,因为springboot是自上而下进行扫描的,具体目录结构,请看最下面

    • 在配置文件,添加如下配置
      <!--redis-->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-data-redis</artifactId>
            </dependency>
            <!--ObjectMapper-->
            <dependency>
                <groupId>com.fasterxml.jackson.core</groupId>
                <artifactId>jackson-databind</artifactId>
                <version>2.9.5</version>
            </dependency>
            <!--fastjson-->
            <dependency>
                <groupId>com.alibaba</groupId>
                <artifactId>fastjson</artifactId>
                <version>1.2.47</version>
            </dependency>
    • 创建RedisConfig类
    package com.howdy.demo.config;
    import com.fasterxml.jackson.annotation.JsonAutoDetect;
    import com.fasterxml.jackson.annotation.PropertyAccessor;
    import com.fasterxml.jackson.databind.ObjectMapper;
    import org.springframework.cache.annotation.CachingConfigurerSupport;
    import org.springframework.cache.annotation.EnableCaching;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.data.redis.connection.RedisConnectionFactory;
    import org.springframework.data.redis.core.RedisTemplate;
    import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
    import org.springframework.data.redis.serializer.StringRedisSerializer;
    
    /**
     * redis配置类
     **/
    
    @Configuration
    @EnableCaching
    public class RedisConfig extends CachingConfigurerSupport {
    
        @Bean
        @SuppressWarnings("all")
        public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
    
            RedisTemplate<String, Object> template = new RedisTemplate<String, Object>();
            template.setConnectionFactory(factory);
            // 使用Jackson2JsonRedisSerialize 替换默认序列化(默认采用的是JDK序列化)
            Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class);
            ObjectMapper om = new ObjectMapper();
            om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
            om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
            jackson2JsonRedisSerializer.setObjectMapper(om);
            StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
          //  RedisSerializer serializer = new FastJsonRedisSerializer(Object.class);
            // key采用String的序列化方式
            template.setKeySerializer(jackson2JsonRedisSerializer);
            // hash的key也采用String的序列化方式
            template.setHashKeySerializer(jackson2JsonRedisSerializer);
            // value序列化方式采用jackson
            template.setValueSerializer(jackson2JsonRedisSerializer);
            // hash的value序列化方式采用jackson
            template.setHashValueSerializer(jackson2JsonRedisSerializer);
            template.afterPropertiesSet();
            return template;
        }
    
    }
    • 创建RedisUtil类库
    package com.howdy.demo.util;
    
    
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.data.redis.core.RedisTemplate;
    import org.springframework.stereotype.Service;
    import org.springframework.util.CollectionUtils;
    
    import java.util.List;
    import java.util.Map;
    import java.util.Set;
    import java.util.concurrent.TimeUnit;
    
    /**
     * Redis工具类
     */
    @Service
    public    class RedisUtil{
    
        @Autowired
        private RedisTemplate<String, Object> redisTemplate;
    
    
    // =============================common============================
    
        /**
         * 指定缓存失效时间
         *
         * @param key  键
         * @param time 时间(秒)
         * @return
         */
    
        public boolean expire(String key, long time) {
    
            try {
    
                if (time > 0) {
    
                    redisTemplate.expire(key, time, TimeUnit.SECONDS);
    
                }
    
                return true;
    
            } catch (Exception e) {
    
                e.printStackTrace();
    
                return false;
    
            }
    
        }
    
    
        /**
         * 根据key 获取过期时间
         *
         * @param key 键 不能为null
         * @return 时间(秒) 返回0代表为永久有效
         */
    
        public long getExpire(String key) {
    
            return redisTemplate.getExpire(key, TimeUnit.SECONDS);
    
        }
    
    
        /**
         * 判断key是否存在
         *
         * @param key 键
         * @return true 存在 false不存在
         */
    
        public boolean hasKey(String key) {
    
            try {
    
                return redisTemplate.hasKey(key);
    
            } catch (Exception e) {
    
                e.printStackTrace();
    
                return false;
    
            }
    
        }
    
    
        /**
         * 删除缓存
         *
         * @param key 可以传一个值 或多个
         */
    
        @SuppressWarnings("unchecked")
    
        public void del(String... key) {
    
            if (key != null && key.length > 0) {
    
                if (key.length == 1) {
    
                    redisTemplate.delete(key[0]);
    
                } else {
    
                    redisTemplate.delete(CollectionUtils.arrayToList(key));
    
                }
    
            }
    
        }
    
    
    // ============================String=============================
    
        /**
         * 普通缓存获取
         *
         * @param key 键
         * @return*/
    
        public Object get(String key) {
    
            return key == null ? null : redisTemplate.opsForValue().get(key);
    
        }
    
    
        /**
         * 普通缓存放入
         *
         * @param key   键
         * @param value 值
         * @return true成功 false失败
         */
    
        public boolean set(String key, Object value) {
    
            try {
    
                redisTemplate.opsForValue().set(key, value);
    
                return true;
    
            } catch (Exception e) {
    
                e.printStackTrace();
    
                return false;
    
            }
    
    
        }
    
    
        /**
         * 普通缓存放入并设置时间
         *
         * @param key   键
         * @param value 值
         * @param time  时间(秒) time要大于0 如果time小于等于0 将设置无限期
         * @return true成功 false 失败
         */
    
        public boolean set(String key, Object value, long time) {
    
            try {
    
                if (time > 0) {
    
                    redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS);
    
                } else {
    
                    set(key, value);
    
                }
    
                return true;
    
            } catch (Exception e) {
    
                e.printStackTrace();
    
                return false;
    
            }
    
        }
    
    
        /**
         * 递增
         *
         * @param key   键
         * @param delta 要增加几(大于0)
         * @return
         */
    
        public long incr(String key, long delta) {
    
            if (delta < 0) {
    
                throw new RuntimeException("递增因子必须大于0");
    
            }
    
            return redisTemplate.opsForValue().increment(key, delta);
    
        }
    
    
        /**
         * 递减
         *
         * @param key   键
         * @param delta 要减少几(小于0)
         * @return
         */
    
        public long decr(String key, long delta) {
    
            if (delta < 0) {
    
                throw new RuntimeException("递减因子必须大于0");
    
            }
    
            return redisTemplate.opsForValue().increment(key, -delta);
    
        }
    
    
    // ================================Map=================================
    
        /**
         * HashGet
         *
         * @param key  键 不能为null
         * @param item 项 不能为null
         * @return*/
    
        public Object hget(String key, String item) {
    
            return redisTemplate.opsForHash().get(key, item);
    
        }
    
    
        /**
         * 获取hashKey对应的所有键值
         *
         * @param key 键
         * @return 对应的多个键值
         */
    
        public Map<Object, Object> hmget(String key) {
    
            return redisTemplate.opsForHash().entries(key);
    
        }
    
    
        /**
         * HashSet
         *
         * @param key 键
         * @param map 对应多个键值
         * @return true 成功 false 失败
         */
    
        public boolean hmset(String key, Map<String, Object> map) {
    
            try {
    
                redisTemplate.opsForHash().putAll(key, map);
    
                return true;
    
            } catch (Exception e) {
    
                e.printStackTrace();
    
                return false;
    
            }
    
        }
    
    
        /**
         * HashSet 并设置时间
         *
         * @param key  键
         * @param map  对应多个键值
         * @param time 时间(秒)
         * @return true成功 false失败
         */
    
        public boolean hmset(String key, Map<String, Object> map, long time) {
    
            try {
    
                redisTemplate.opsForHash().putAll(key, map);
    
                if (time > 0) {
    
                    expire(key, time);
    
                }
    
                return true;
    
            } catch (Exception e) {
    
                e.printStackTrace();
    
                return false;
    
            }
    
        }
    
    
        /**
         * 向一张hash表中放入数据,如果不存在将创建
         *
         * @param key   键
         * @param item  项
         * @param value 值
         * @return true 成功 false失败
         */
    
        public boolean hset(String key, String item, Object value) {
    
            try {
    
                redisTemplate.opsForHash().put(key, item, value);
    
                return true;
    
            } catch (Exception e) {
    
                e.printStackTrace();
    
                return false;
    
            }
    
        }
    
    
        /**
         * 向一张hash表中放入数据,如果不存在将创建
         *
         * @param key   键
         * @param item  项
         * @param value 值
         * @param time  时间(秒) 注意:如果已存在的hash表有时间,这里将会替换原有的时间
         * @return true 成功 false失败
         */
    
        public boolean hset(String key, String item, Object value, long time) {
    
            try {
    
                redisTemplate.opsForHash().put(key, item, value);
    
                if (time > 0) {
    
                    expire(key, time);
    
                }
    
                return true;
    
            } catch (Exception e) {
    
                e.printStackTrace();
    
                return false;
    
            }
    
        }
    
    
        /**
         * 删除hash表中的值
         *
         * @param key  键 不能为null
         * @param item 项 可以使多个 不能为null
         */
    
        public void hdel(String key, Object... item) {
    
            redisTemplate.opsForHash().delete(key, item);
    
        }
    
    
        /**
         * 判断hash表中是否有该项的值
         *
         * @param key  键 不能为null
         * @param item 项 不能为null
         * @return true 存在 false不存在
         */
    
        public boolean hHasKey(String key, String item) {
    
            return redisTemplate.opsForHash().hasKey(key, item);
    
        }
    
    
        /**
         * hash递增 如果不存在,就会创建一个 并把新增后的值返回
         *
         * @param key  键
         * @param item 项
         * @param by   要增加几(大于0)
         * @return
         */
    
        public double hincr(String key, String item, double by) {
    
            return redisTemplate.opsForHash().increment(key, item, by);
    
        }
    
    
        /**
         * hash递减
         *
         * @param key  键
         * @param item 项
         * @param by   要减少记(小于0)
         * @return
         */
    
        public double hdecr(String key, String item, double by) {
    
            return redisTemplate.opsForHash().increment(key, item, -by);
    
        }
    
    
    // ============================set=============================
    
        /**
         * 根据key获取Set中的所有值
         *
         * @param key 键
         * @return
         */
    
        public Set<Object> sGet(String key) {
    
            try {
    
                return redisTemplate.opsForSet().members(key);
    
            } catch (Exception e) {
    
                e.printStackTrace();
    
                return null;
    
            }
    
        }
    
    
        /**
         * 根据value从一个set中查询,是否存在
         *
         * @param key   键
         * @param value 值
         * @return true 存在 false不存在
         */
    
        public boolean sHasKey(String key, Object value) {
    
            try {
    
                return redisTemplate.opsForSet().isMember(key, value);
    
            } catch (Exception e) {
    
                e.printStackTrace();
    
                return false;
    
            }
    
        }
    
    
        /**
         * 将数据放入set缓存
         *
         * @param key    键
         * @param values 值 可以是多个
         * @return 成功个数
         */
    
        public long sSet(String key, Object... values) {
    
            try {
    
                return redisTemplate.opsForSet().add(key, values);
    
            } catch (Exception e) {
    
                e.printStackTrace();
    
                return 0;
    
            }
    
        }
    
    
        /**
         * 将set数据放入缓存
         *
         * @param key    键
         * @param time   时间(秒)
         * @param values 值 可以是多个
         * @return 成功个数
         */
    
        public long sSetAndTime(String key, long time, Object... values) {
    
            try {
    
                Long count = redisTemplate.opsForSet().add(key, values);
    
                if (time > 0)
    
                    expire(key, time);
    
                return count;
    
            } catch (Exception e) {
    
                e.printStackTrace();
    
                return 0;
    
            }
    
        }
    
    
        /**
         * 获取set缓存的长度
         *
         * @param key 键
         * @return
         */
    
        public long sGetSetSize(String key) {
    
            try {
    
                return redisTemplate.opsForSet().size(key);
    
            } catch (Exception e) {
    
                e.printStackTrace();
    
                return 0;
    
            }
    
        }
    
    
        /**
         * 移除值为value的
         *
         * @param key    键
         * @param values 值 可以是多个
         * @return 移除的个数
         */
    
        public long setRemove(String key, Object... values) {
    
            try {
    
                Long count = redisTemplate.opsForSet().remove(key, values);
    
                return count;
    
            } catch (Exception e) {
    
                e.printStackTrace();
    
                return 0;
    
            }
    
        }
    
    // ===============================list=================================
    
    
        /**
         * 获取list缓存的内容
         *
         * @param key   键
         * @param start 开始
         * @param end   结束 0 到 -1代表所有值
         * @return
         */
    
        public List<Object> lGet(String key, long start, long end) {
    
            try {
    
                return redisTemplate.opsForList().range(key, start, end);
    
            } catch (Exception e) {
    
                e.printStackTrace();
    
                return null;
    
            }
    
        }
    
    
        /**
         * 获取list缓存的长度
         *
         * @param key 键
         * @return
         */
    
        public long lGetListSize(String key) {
    
            try {
    
                return redisTemplate.opsForList().size(key);
    
            } catch (Exception e) {
    
                e.printStackTrace();
    
                return 0;
    
            }
    
        }
    
    
        /**
         * 通过索引 获取list中的值
         *
         * @param key   键
         * @param index 索引 index>=0时, 0 表头,1 第二个元素,依次类推;index<0时,-1,表尾,-2倒数第二个元素,依次类推
         * @return
         */
    
        public Object lGetIndex(String key, long index) {
    
            try {
    
                return redisTemplate.opsForList().index(key, index);
    
            } catch (Exception e) {
    
                e.printStackTrace();
    
                return null;
    
            }
    
        }
    
    
        /**
         * 将list放入缓存
         *
         * @param key   键
         * @param value 值
         * @param time  时间(秒)
         * @return
         */
    
        public boolean lSet(String key, Object value) {
    
            try {
    
                redisTemplate.opsForList().rightPush(key, value);
    
                return true;
    
            } catch (Exception e) {
    
                e.printStackTrace();
    
                return false;
    
            }
    
        }
    
    
        /**
         * 将list放入缓存
         *
         * @param key   键
         * @param value 值
         * @param time  时间(秒)
         * @return
         */
    
        public boolean lSet(String key, Object value, long time) {
    
            try {
    
                redisTemplate.opsForList().rightPush(key, value);
    
                if (time > 0)
    
                    expire(key, time);
    
                return true;
    
            } catch (Exception e) {
    
                e.printStackTrace();
    
                return false;
    
            }
    
        }
    
    
        /**
         * 将list放入缓存
         *
         * @param key   键
         * @param value 值
         * @param time  时间(秒)
         * @return
         */
    
        public boolean lSet(String key, List<Object> value) {
    
            try {
    
                redisTemplate.opsForList().rightPushAll(key, value);
    
                return true;
    
            } catch (Exception e) {
    
                e.printStackTrace();
    
                return false;
    
            }
    
        }
    
    
        /**
         * 将list放入缓存
         *
         * @param key   键
         * @param value 值
         * @param time  时间(秒)
         * @return
         */
    
        public boolean lSet(String key, List<Object> value, long time) {
    
            try {
    
                redisTemplate.opsForList().rightPushAll(key, value);
    
                if (time > 0)
    
                    expire(key, time);
    
                return true;
    
            } catch (Exception e) {
    
                e.printStackTrace();
    
                return false;
    
            }
    
        }
    
    
        /**
         * 根据索引修改list中的某条数据
         *
         * @param key   键
         * @param index 索引
         * @param value 值
         * @return
         */
    
        public boolean lUpdateIndex(String key, long index, Object value) {
    
            try {
    
                redisTemplate.opsForList().set(key, index, value);
    
                return true;
    
            } catch (Exception e) {
    
                e.printStackTrace();
    
                return false;
    
            }
    
        }
    
    
        /**
         * 移除N个值为value
         *
         * @param key   键
         * @param count 移除多少个
         * @param value 值
         * @return 移除的个数
         */
    
        public long lRemove(String key, long count, Object value) {
    
            try {
    
                Long remove = redisTemplate.opsForList().remove(key, count, value);
    
                return remove;
    
            } catch (Exception e) {
    
                e.printStackTrace();
    
                return 0;
    
            }
    
        }
    }
    • 在.properties中添加如下配置
    # Redis数据库索引(默认为0)
    spring.redis.database=0  
    # Redis服务器地址
    spring.redis.host=localhost
    # Redis服务器连接端口
    spring.redis.port=6379  
    # Redis服务器连接密码(默认为空)
    spring.redis.password=
    # 连接池最大连接数(使用负值表示没有限制)
    spring.redis.pool.max-active=200  
    # 连接池最大阻塞等待时间(使用负值表示没有限制)
    spring.redis.pool.max-wait=-1  
    # 连接池中的最大空闲连接
    spring.redis.pool.max-idle=10 
    # 连接池中的最小空闲连接
    spring.redis.pool.min-idle=0  
    # 连接超时时间(毫秒)
    spring.redis.timeout=1000
    • 在Service的job类中添加redis锁,防止任务并发执行,也可以在quartz-config.xml中启用防止并发执行开关:

    方法一:

    <bean id="springQtzJob" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
    <!-- 执行目标job -->
    <property name="targetObject" ref="sysDataJob"></property>
    <!-- 要执行的方法 -->
    <property name="targetMethod" value="deleteInfo"></property>
    <property name="concurrent" value="false"></property><!--配置为false不允许任务并发执行-->
    </bean>

    方法二:

    package com.howdy.demo.service;
    import com.howdy.demo.util.RedisUtil;
    import org.apache.commons.logging.Log;
    import org.apache.commons.logging.LogFactory;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Service;
    
    import java.io.Serializable;
    
    @Service
    public class SysDataJob {
        private final Log log = LogFactory.getLog(SysDataJob.class);
        @Autowired
        private RedisUtil redisUtil;
        public void deleteInfo() throws InterruptedException {
    
            try{
                if(redisUtil.hasKey("delUser"))
                {
                    log.info("有正在处理任务,请稍等...");
                }else {
                    log.info("开始处理任务...");
                    redisUtil.set("delUser","del");
                    Thread.sleep(20000);//休息20秒,任务是每10秒执行一次
                    User u = new User();
                    u.age = 10;
                    u.uName = "张三";
                    redisUtil.set("quart2", u);
                    redisUtil.del("delUser");
                    log.info("完成任务处理...");
                }
            }catch (Exception e){
                redisUtil.del("delUser");
            }
        }
    
        private class User   implements Serializable {
            public int getAge() {
                return age;
            }
    
            public void setAge(int age) {
                this.age = age;
            }
    
            public String getuName() {
                return uName;
            }
    
            public void setuName(String uName) {
                this.uName = uName;
            }
    
            private int age;
            private String uName;
        }
    
    
    }
    • 任务执行结果如下:

      

  • 相关阅读:
    碰到一个在app内部浏览器锚点异常的问题
    常用js方法
    preg_match_all正则表达式的基本使用
    无线路由器WDS 桥接设置方法
    链表和数组的区别在哪里?
    php报错: PHP Warning: PHP Startup: memcache: Unable to initialize module
    mysql修改密码
    快速排序
    vuex到底是个啥
    vue实现简单表格组件
  • 原文地址:https://www.cnblogs.com/personblog/p/14074203.html
Copyright © 2020-2023  润新知