JavaWeb——Redis数据库之Jedis操作5种类型数据的使用总结与前端Ajax获取Redis缓存数据的案例实战(结合了MySQL数据库)

时间:2022-07-25
本文章向大家介绍JavaWeb——Redis数据库之Jedis操作5种类型数据的使用总结与前端Ajax获取Redis缓存数据的案例实战(结合了MySQL数据库),主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

1 Jedis基本操作

上一博文中,我们都是用命令直接操作Redis数据库,那么Java代码的形式该如何操作数据库?本博文介绍下Jedis,是一款java操作Redis数据库的工具。其使用步骤:

1)下载jedis的jar包:commons-pool2-2.3.jar、jedis-2.7.0.jar;

2)使用入门:相较于jdbc要简单的多

  • 获取连接;
  • 操作;
  • 关闭连接
    @Test
    public void test1(){
        //1、获取连接
        Jedis jedis = new Jedis("localhost", 6379); //ip 及端口号,空参构造默认就是如左所示
        //2、操作
        jedis.set("username","zhangsan");
        //3、关闭连接
        jedis.close();
    }

1.1 Jedis操作字符串类型数据

  • 1)存储:set(key, value)方法;
  • 2)获取:get(key)方法;
  • 3)setex(key,seconds,value)方法:存储可以指定过期时间的key value,时间过后自动删除该键值对,该方法可以用于存储注册时用的验证码,比较实用;

【练习案例】:

@Test
    public void test2(){
        //1、获取连接
        Jedis jedis = new Jedis("localhost", 6379); //ip 及端口号
        //2、操作
        //存储
        jedis.set("username","zhangsan");
        //获取
        String username = jedis.get("username");
        System.out.println(username);//zhangsan

        jedis.setex("activecode",20,"haha");
        //3、关闭连接
        jedis.close();
    }

1.2 Jedis操作哈希类型数据

  • 1)存储:hset(key, field,value)方法;
  • 2)获取:hget(key,field)方法;
  • 3)获取所有map数据:hgetAll(key);
@Test
    public void test3(){
        //1、获取连接
        Jedis jedis = new Jedis("localhost", 6379); //ip 及端口号
        //2、操作
        //存储
        jedis.hset("myhash","username","lisi");
        jedis.hset("myhash","age","18");
        //获取
        String username = jedis.hget("myhash","username");
        System.out.println(username);//zhangsan

        Map<String, String> myhash = jedis.hgetAll("myhash");
        for (String key : myhash.keySet()) {
            String value = myhash.get(key);
            System.out.println(value);
        }
        //3、关闭连接
        jedis.close();
    }

1.3 Jedis操作列表类型数据

  • 1)存储:lpush(key,value1,value2...)、rpush(key,value1,value2...)
  • 2)获取:lrange(key,start,end),范围获取
@Test
    public void test4(){
        //1、获取连接
        Jedis jedis = new Jedis("localhost", 6379); //ip 及端口号
        //2、操作
        //存储
        jedis.lpush("mylist","a","b","c");//左边存
        jedis.rpush("mylist","a","b","c");//右边存
        //获取
        List<String> mylist = jedis.lrange("mylist", 0, -1);
        System.out.println(mylist);//[c, b, a, a, b, c]
        //删除
        String ele = jedis.lpop("mylist");
        System.out.println(ele);  //c
        String ele1 = jedis.rpop("mylist");
        System.out.println(ele1);  //c

        List<String> mylist1 = jedis.lrange("mylist", 0, -1);
        System.out.println(mylist1);//[b, a, a, b]
        //3、关闭连接
        jedis.close();
    }

1.4 Jedis操作Set类型数据

  • 1)存储:sadd(key,members)
  • 2)获取:smembers(key),返回的是Set集合
    @Test
    public void test5(){
        //1、获取连接
        Jedis jedis = new Jedis("localhost", 6379); //ip 及端口号
        //2、操作
        //存储
        jedis.sadd("myset","a","b","c");
        //获取
        Set<String> myset = jedis.smembers("myset");
        System.out.println(myset);//[a, b, c]

        //3、关闭连接
        jedis.close();
    }

1.5 Jedis操作SortSet类型数据

  • 1)存储:zadd(key,score,member)
  • 2)获取:zrange(key,start,end),返回的是Set集合
    @Test
    public void test6(){
        //1、获取连接
        Jedis jedis = new Jedis("localhost", 6379); //ip 及端口号
        //2、操作
        //存储
        jedis.zadd("mysortedset",10,"a");
        jedis.zadd("mysortedset",20,"b");
        jedis.zadd("mysortedset",5,"c");
        //获取
        Set<String> mysortedset = jedis.zrange("mysortedset", 0, -1);
        System.out.println(mysortedset);//[c, a, b]

        //3、关闭连接
        jedis.close();
    }

2 Jedis连接池

2.1 Jedis连接池的基本使用

类似于jdbc连接池,所不同的是jdbc需要使用第三方的,jedis自带连接池JedisPool连接池对象。那么如何使用?

  • 1)创建JedisPool连接池对象;
  • 2)调用方法getResource方法获取Jedis的连接;
  • 3)关闭连接;
    @Test
    public void test7(){

        //0.创建一个配置对象
        JedisPoolConfig config = new JedisPoolConfig();
        config.setMaxTotal(50); //最大连接数
        config.setMaxIdle(10);  //最大空闲连接

        //1、创建Jedis连接池对象
        JedisPool jedisPool = new JedisPool("localhost",6379);
        //2、获取连接
        Jedis jedis = jedisPool.getResource();
        jedis.set("hello","world");
        //3、关闭连接
        jedis.close();
    }

【注意】:关于连接池的参数配置,需要根据自己计算机的性能及业务合理配置,配置参数说明如下:

  • 最大活动对象数:redis.pool.maxTotal=1000    
  • 最大能够保持idle状态的对象数:redis.pool.maxIdle=100  
  • 最小能够保持idle状态的对象数:redis.pool.minIdle=50    
  • 当池内没有返回对象时,最大等待时间:redis.pool.maxWaitMillis=10000    
  • 当调用borrow Object方法时,是否进行有效性检查:redis.pool.testOnBorrow=true    
  • 当调用return Object方法时,是否进行有效性检查:redis.pool.testOnReturn=true  
  • “空闲链接”检测线程,检测的周期,毫秒数。如果为负值,表示不运行“检测线程”。默认为-1.:redis.pool.timeBetweenEvictionRunsMillis=30000  
  • 向调用者输出“链接”对象时,是否检测它的空闲超时:redis.pool.testWhileIdle=true  
  • 对于“空闲链接”检测线程而言,每次检测的链接资源的个数。默认为3:redis.pool.numTestsPerEvictionRun=50  
  • redis服务器的IP:redis.ip=xxxxxx  
  • redis服务器的Port:redis1.port=6379  

2.2 Jedis连接池的工具类

以上Jedis连接池的操作可见比较简单,但是涉及到一些配置参数一个个写还是比较麻烦,所以,可以抽取一个Jedis连接池的工具类,包含以下两个需求:

  • 1)加载配置文件,配置连接池的参数;
  • 2)提供获取连接的方法;

【代码实现】:

1)jedis.properties配置文件

host=127.0.0.1
port=6379
maxTotal=50
maxIdle=10

2)JedisPoolUtils工具类

public class JedisPoolUtils {

    private static JedisPool jedisPool;

    static {
        //读取配置文件
        InputStream is = JedisPoolUtils.class.getClassLoader().getResourceAsStream("jedis.properties");
        //创建Properties对象
        Properties pro = new Properties();
        //关联文件
        try {
            pro.load(is);
        } catch (IOException e) {
            e.printStackTrace();
        }
        //获取数据,设置到JedisPoolConfig
        JedisPoolConfig config = new JedisPoolConfig();
        config.setMaxTotal(Integer.parseInt(pro.getProperty("maxTotal")));
        config.setMaxIdle(Integer.parseInt(pro.getProperty("maxIdle")));
        //初始化JedisPool
        jedisPool =  new JedisPool(config,pro.getProperty("host"),Integer.parseInt(pro.getProperty("port")));

    }
    //获取连接
    public static Jedis getJedis(){
        return jedisPool.getResource();
    }

}

3)测试使用该工具类:我们可以发现,代码变得精简多了。

@Test
    public void test8(){
        //获取连接
        Jedis jedis = JedisPoolUtils.getJedis();
        //使用
        jedis.set("hello","world");
        //关闭
        jedis.close();
    }

3 Redis案例实战

上篇博文讲解了Redis的基本指令操作及数据结构,本篇博文前部分讲解了如何利用Jedis Java代码形式操作Redis数据库,此处我们来一个Redis实战案例,此处也会用到我们之前学到的MySQL数据库的内容,可以回顾下,做到学以致用:)如下步骤基本是按照开发思路写的,按照步骤一步步就可以搞定。这也是一个最简单的前端通过Ajax从后端获取数据的小模板了。

【需求】:

  • 1)提供一个index.html页面,页面中有一个省份下拉列表;
  • 2)当页面加载完成后,发送ajax请求,加载所有省份。

【分析】:

【实现步骤】:

1)先准备MySQL数据库,新建一个db3数据库,新建province表,表中插入省份数据;

CREATE DATABASE db3;
USE db3;
CREATE TABLE province(
	id INT PRIMARY KEY AUTO_INCREMENT,
	NAME VARCHAR(20) NOT NULL
);
INSERT INTO province VALUES(NULL,'大庆');
INSERT INTO province VALUES(NULL,'上海');
INSERT INTO province VALUES(NULL,'北京');
INSERT INTO province VALUES(NULL,'南京');

2)JavaWeb工程的准备工作

  • 导入jar包;
  • 新建需要的包;

3)在domain包中写一个Province类,对应数据库的province表;

public class Province {
    private int id;
    private String name;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

4)在dao包下写一个ProvinceDao接口,定义一个findAll方法,返回Province的List列表;在dao.impl包下写一个ProvinceDao接口的实现类ProvinceDaoImpl,用于服务层调用,操作MySQL数据库,查询province表返回List列表;

public interface ProvinceDao {
    public List<Province> findAll();
}
public class ProvinceDaoImpl implements ProvinceDao {

    //1、声明成员变量 jdbctemplement
    private JdbcTemplate template = new JdbcTemplate(JDBCUtils.getDataSource());

    @Override
    public List<Province> findAll() {
        //1、定义sql
        String sql = "select * from province";
        //2、执行sql
        List<Province> list = template.query(sql, new BeanPropertyRowMapper<Province>(Province.class));
        return list;
    }
}

5)在service包下写一个ProvinceService接口,定义一个findAll方法,返回Province的List列表;在service.impl包下写一个ProvinceService接口的实现类ProvinceServiceImpl,用于应用层调用,只需要new ProvinceDaoImpl()一个实例化对象,调用其findAll()方法,返回查询MySQL的List列表;

public interface ProvinceService {
    public List<Province> findAll();
}
public class ProvinceServiceImpl implements ProvinceService {
    //声明dao
    private ProvinceDao dao = new ProvinceDaoImpl();

    @Override
    public List<Province> findAll() {
        return dao.findAll();
    }
}

6)在web.servlet包下写一个ProvinceServlet,要做的就是调用service查询数据库,再将查询的list转换为json,最后响应结果,至此,后台代码已OK;

@WebServlet("/provinceServlet")
public class ProvinceServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //1、调用Service查询
        ProvinceService service = new ProvinceServiceImpl();
        List<Province> list = service.findAll();
        //2、list序列化为json
        ObjectMapper mapper = new ObjectMapper();
        String json = mapper.writeValueAsString(list);
        //3、响应结果
        response.setContentType("application/json;charset=utf-8");
        response.getWriter().write(json);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doPost(request, response);
    }
}

7)写前端部分代码,新建index.html页面,此处需要做的是:发送Ajax请求,加载省份数据-》获取select-》遍历获取的json数组-》创建option-》调用select的append追加option。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="js/jquery-3.3.1.min.js"></script>
    <script>
        $(function () {
            //发送Ajax请求,加载省份数据
            $.get("provinceServlet",{},function (data) {
                //[{"id":1,"name":"大庆"},{"id":2,"name":"上海"},{"id":3,"name":"北京"},{"id":4,"name":"南京"}]
                //获取select
                var province = $("#province");
                //遍历json数组
                $(data).each(function () {
                    //创建option
                    var option = "<option name='"+ this.id+"'>"+this.name+"</option>";
                    //调用select的append追加option
                    province.append(option);
                });
            });
        });
    </script>
</head>
<body>
    <select id="province">
        <option>--请选择城市--</option>
    </select>
</body>
</html>

好了,写到此处,我们启动服务器,看下运行效果吧:

这里看着效果还可以吧,但是~有没有发现哪里不对劲??我们做的是Redis案例实战,怎么半天玩的都是MySQL啦!!不要慌,我们分析下:

实际上上面数据库province表中的数据不是经常变化的;每一次都加载MySQL数据库性能会受影响,所以,我们可以使用Redis数据库做缓存,实现思路为:先从Redis中查询数据,若没有,再从数据库中查询,查询后将数据存入Redis,再返回数据;若Redis中有数据,直接返回数据。

【注意】:使用Redis缓存的是一些不经常发生变化的数据,若MySQL数据库的数据发生改变,如有增删改的相关操作,需要将Redis缓存数据清空(在service对应的增删改方法中),再次存入。

好了,这样关于Redis案例的知识点基本都串起来了,优化后的代码如下:

8)优化后的ProvinceServiceImpl及ProvinceService:

public interface ProvinceService {
    public List<Province> findAll();
    public String findAllJson();
}
public class ProvinceServiceImpl implements ProvinceService {
    //声明dao
    private ProvinceDao dao = new ProvinceDaoImpl();

    @Override
    public List<Province> findAll() {
        return dao.findAll();
    }

    //使用Redis缓存
    @Override
    public String findAllJson() {
        //1、从Redis查询数据
        //获取redis客户端连接
        Jedis jedis = JedisPoolUtils.getJedis();
        String province_json = jedis.get("province");
        //2、判断province_json是否null
        if(province_json==null || province_json.length()==0){
            //redis中无数据,从数据库中查询
            System.out.println("redis中无数据,从数据库中查询");
            List<Province> list = dao.findAll();
            //将list序列化为json
            ObjectMapper mapper = new ObjectMapper();
            try {
                province_json = mapper.writeValueAsString(list);
            } catch (JsonProcessingException e) {
                e.printStackTrace();
            }
            //将json数据存入redis
            jedis.set("province",province_json);
            jedis.close();
        }else{
            System.out.println("redis中有数据,查询Redis缓存");
        }
        return province_json;
    }
}

9)优化后的ProvinceServlet:

@WebServlet("/provinceServlet")
public class ProvinceServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //1、调用Service查询
        ProvinceService service = new ProvinceServiceImpl();
        String json = service.findAllJson();
        //3、响应结果
        response.setContentType("application/json;charset=utf-8");
        response.getWriter().write(json);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doPost(request, response);
    }
}

刷新index页面,从打印信息中我们看下效果:

———————————————————————————————————

本文为博主原创文章,转载请注明出处!