文章目录

  • 说明
  • Redis
  • 存储的数据结构
  • 基本的操作
  • Redis持久化
  • jedis
  • jedis的连接池
  • 案例





说明

  因为是个人复习java的总结,所以结构稍显杂乱,有些语句过于口语化.

Redis

  其实就是一款高性能的NOSQL非关系型数据库.非关系型数据库其实就是指的存储的数据之间没有明显的关联,不像关系型数据库设计的时候可能还要去考虑不同表之间的ER图.非关系型数据库中存储的数据有点像是键值对存储,不同键值对之间没有太大的关联.

  其实非关系型数据库的种类非常多,而且每种之间都存在较大的差异,不像关系型数据库学会了SQL,很多的数据库都可以通用.但是非关系型的数据库主要是成本比较低,并且查询速度比较快,因为数据存储在缓存中.

  所以在使用中一般是关系型数据库和非关系型数据库相结合的方式,非关系型数据库作为关系型数据库的备份.比如说用Redis做服务器中查询后数据结果的备份,那么再次查询的时候就不需要去查询硬盘中的数据库.


存储的数据结构

redis中存储的是键值对的形式,其中key是字符串类型的,而value有不同的数据类型.

  1. 字符串类型:String
  2. 哈希类型hash:map格式
  3. 列表类型list:linkedlist格式
  4. 集合类型set:
  5. 有序集合类型sortedset

  其实就是存储的value中可以再存储集合,可以存储键值对形式的集合,也可以存储可以重复的list集合,抑或是存储不可重复的集合,或者是存储排序的集合.


基本的操作



字符串类型数据的操作

set key value
get key
del key



hash类型数据的操作

hset key 键 值
hget key键
heggtall key
hdel key键 值

  就不解释了,这命令很容易看懂

列表类型数据的操作

lpush key value
rpush key value

  list左右插入数据

lrange key start end

  范围获取数据,可以使用-1来表示倒取的顺序

lpop key
rpop key

  删除左右的数据并返回

集合类型数据操作

sadd key value

  存多个元素就使用空格分开value,注意存入的不保证顺序

smembers key
srem key value

有序集合的数据操作

zadd key score value:

  这个集合的排序方式很有意思,是使用传入的score来排序的,这是一个double类型的数据

zrange key start end
zrem key value



通用命令

keys *

  可以可以用来获取符合要求的key,其实后面可以跟正则表达式

type key

  可以用来查看键对应值存储的数据格式

del key

  删除键


Redis持久化

  因为redis其实是非关系型数据库,其中的数据不是存储在内存中的,所以会随着服务器的重启导致数据消失.那么肯定需要让数据能够持久化的存储.


RDB
  这是默认的持久化机制,在一定时间内去检测key的变化情况,然后持久化数据.这也是比较推荐的方式,因为性能的影响比较小

  如果需要主动去设置,可以修改redis数据库中的redis.windows.conf,因为是在windows下自己用用看,之后肯定不会放在windows上.其实就是去修改这个配置文件.

save 900 1
save 300 10
save 60 10000

  其实就是表示在60秒之后如果有10000次的键操作,那么就会存储数据.可以自主去修改,但是修改之后需要使用redis-server.exe redis.windows.conf的方式在命令行启动,因为需要加载配置文件,还有命令行肯定是在对应文件夹下打开的,或者配环境变量.学到这了应该没有不知道这个的吧…

  持久化之后会在目录下生成rdb后缀的文件


AOF
  这是一种日志记录的方式,每次操作之后都进行数据的持久化.不大推荐,这样做就像在主动失去自己的优势
  配置AOF同样在配置文件中修改appendonly yes   另外其中还有一个设置appendsync,后面跟参数always的时候表示每次操作都会持久化,跟everysec的时候表示每一秒进行一次,跟no表示不进行持久化

jedis

  这个其实就是用来操作redis的java工具包,类似之前的jdbc
  主要的使用语句如下

Jedis jedis = new Jedis("localhost",6379);
jedis.set("username","zhangsan");
jedis.close();

  其中存储有一个指定时间过期的存储方式,可以使用这种方式做一些比如说有期限的激活码或者是验证信息的存储.

jedis.setex("key",seconds,value)

  其实具体数据的操作方法名和上面使用命令行的方法名一样,传入参数也一样,只是这里是在java中使用方法的方式获取内容.所以具体的方法就不写了,获取的时候注意传出的数据的类型就好了.

jedis的连接池

  其实就是jedisPool,这是jedis中包含的连接池,那么使用语句大致如下:

JedisPool jedisPool = new JedisPool();
Jedis jedis = jedisPool.getResource();
jedis.close();

  和之前的Druid差别不大.

  如果想要对连接池进行一些设置,可以使用给连接池的构造器传入的参数.也就是传入一个JedisPoolConfig对象,主机名和端口号
  主要就是JedisPoolConfig对象,可以使用setXXX来设置一些连接池的设置.比如说下面:

JedisPoolConfig config = new JedisPoolConfig();
config.setMaxTotal(50);
config.setMaxIdle(10);
JedisPool jedisPool = new JedisPool(config, "localhost", 6379);

  设置最大连接连接数50,最大空闲连接10

  当然上面的配置肯定不能这么用,还是使用properties来配置更为合理,那么就需要去写一个工具类,这其实也是之前jdbc中的操作。
  这个工具类就不写了,就是通过反射得到ClassLoader然后加载文件到properties中,再加载流,然后读取其中的数据进行设置。

案例

  这个案例就是页面中有一个省份下拉列表,页面加载完之后发送ajax请求加载省份列表
  其实这个需求看起来很普通,没什么难度,但是通过表面看本质,综合复习前面学过的内容,然后这个案例就变得有点麻烦。这次案例会尽量写到详尽。

  分析:
  首先需要数据库,数据库中建张表,存省份数据。

  然后还需要一个简陋的前端页面,页面里放一个下拉框,然后用jquery写一段ajax的请求代码,请求数据并且在下拉框中补option。当然这部分最后再写也没问题。

  再接下来就是导入一堆jar包,然后开始建立项目的包结构。要servlet包,要dao包,要utils包,要service包,要domain包。

  然后先根据数据库在domain下写一个Province实体类,getter,setter。

  接下来就开始写Servlet,因为没有请求数据,那就直接调用Service获取数据,然后设置响应的格式为json,返回。这时先补一下Service接口放着。

  再写Service的实现类,这里就需要考虑从哪里获取数据,省份数据不大改变,那就可以考虑使用redis的方式缓存数据。那么就需要utils中写Jedis工具类。那就先写一个报错的工具类放着,通过工具类获取Jedis连接,然后查询数据。
  如果存在就直接返回,不存在就调用dao来查询数据库,然后使用jackson转换一个格式到json。写好这里就可以先补充一下工具类。

  写JedisPool工具类,既然使用Jedis,就再使用一下JedisPool,那就还需要写一个properties文件写配置内容。

  接下来就可以写dao的实现类,首先就还是jdbc的工具类,先写着,获取数据库连接,然后写sql语句,查询数据并返回,很简单。

  最后补充一下jdbc工具类,需要配置文件来配置druid。

  到这就结束了,前面html还没写完补充一下就好了。


  index.html

<script src="js/jquery-3.4.1.min.js"></script>
    <script>
        $(function () {
            //这里是之前学的ajax请求方式,请求查找省份的Servlet
            $.get("ProvinceServlet",{},function (data) {
                //请求成功之后将所有的省份选择添加进下拉框中
                var province = $("#province");
                $(data).each(function () {
                    var option = "<option name='"+this.id+"'>"+this.name+"</option>"
                    province.append(option);
                })
            });
        });
</script>



  省份的实体类不贴了,贴着占空间


  ProvinceServlet

@WebServlet("/ProvinceServlet")
public class ProvinceServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //获取查找省份的Service接口并查找
        ProvinceService service = new ProvinceServiceImpl();
        String json = service.findAllJson();

        //设置响应的数据格式为json并写入json数据
        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);
    }
}



  ProvinceService

public class ProvinceServiceImpl implements ProvinceService {

    private ProvinceDao dao = new ProvinceDaoImpl();

    @Override
    public String findAllJson() {
        //使用JedisPoolUtils工具类获取JedisPool中Redis数据库的连接
        Jedis jedis = JedisPoolUtils.getJedis();

        //在Redis数据库中查找省份信息
        String province_json = jedis.get("province");

        //判断省份信息是否未进入缓存
        if (province_json == null || province_json.length()==0){
            //调用dao在数据库查找数据
            List<Province> all = dao.findAll();

            //使用jackson转换数据为json格式
            ObjectMapper mapper = new ObjectMapper();
            try{
                province_json  = mapper.writeValueAsString(all);
                //数据写入缓存
                jedis.set("province",province_json);
            } catch (JsonProcessingException e) {
                e.printStackTrace();
            }finally {
                jedis.close();
            }
        }
        return province_json;
    }
}



  ProvinceDao

public class ProvinceDaoImpl implements ProvinceDao {

    private JdbcTemplate jdbcTemplate = new JdbcTemplate(JDBCUtils.getDataSource());

    @Override
    public List<Province> findAll() {
        String sql = "select * from province";
        List<Province> query = jdbcTemplate.query(sql, new BeanPropertyRowMapper<>(Province.class));
        return query;
    }
}



  jedis.properties

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



  JedisPoolUtils

public class JedisPoolUtils {

    private static JedisPool jedisPool;

    static {
        //通过ClassLoader获取Jedis的配置文件
        InputStream resourceAsStream = JedisPoolUtils.class.getClassLoader().getResourceAsStream("jedis.properties");

        //获取properties并加载配置文件的输入流
        Properties properties = new Properties();
        try {
            properties.load(resourceAsStream);
        } catch (IOException e) {
            e.printStackTrace();
        }

        //配置Jedis的相关市何止
        JedisPoolConfig config = new JedisPoolConfig();
        config.setMaxTotal(Integer.parseInt(properties.getProperty("maxTotal")));
        config.setMaxIdle(Integer.parseInt(properties.getProperty("maxIdle")));
        jedisPool = new JedisPool(config,properties.getProperty("host"),
                Integer.parseInt(properties.getProperty("port")));

    }

    public static Jedis getJedis(){
        return jedisPool.getResource();
    }
}



  druid.properties

driverClassName=com.mysql.cj.jdbc.Driver
url=jdbc:mysql:///pro?serverTimezone = GMT&characterEncoding=utf8
username=root
password=123
initialSize=5
maxActive=10
maxWait=3000



  JDBCUtils

public class JDBCUtils {
    private static DataSource dataSource;

    static {
        //加载配置文件并配置
        InputStream resourceAsStream = JDBCUtils.class.getClassLoader().getResourceAsStream("druid.properties");
        Properties properties = new Properties();
        try {
            properties.load(resourceAsStream);
            dataSource = DruidDataSourceFactory.createDataSource(properties);
        } catch (IOException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static DataSource getDataSource(){
        return dataSource;
    }
}


如有错误欢迎读者批评指正!!