Docker下Jedis体验
jedis是redis的java版本的客户端实现,本文通过一些web请求&响应的实例展示了jedis的基本用法;
开始编码前我们先把环境准备好,总共两个server,对应两个docker容器:
- redis,采用redis的3.2.8版本,本次实战用的是redis单机;
- tomcat,采用7.0.77-jre8版本,由于要支持在线部署,所以tomcat镜像对官方镜像做了少量定制,详情请参照《实战docker,编写Dockerfile定制tomcat镜像,实现web应用在线部署》,这里可以不用自己动手做,在hub.docker.com下载bolingcavalry/online_deploy_tomcat:0.0.1镜像即可,为了支持在线部署,请在本地maven环境的settings.xml中的servers节点内增加一个server节点,内容如下:
<server>
<id>tomcat7</id>
<username>bolingcavalry</username>
<password>bolingcavalrypswd</password>
</server>
以上只是对环境做个介绍,不需要自己动手去挨个构建,通过一个docker-compose.yml即可搭建成功,docker-compose.yml文件内容如下:
version: '2'
services:
redis001:
image: daocloud.io/library/redis:3.2.8
restart: always
tomcat001:
image: bolingcavalry/online_deploy_tomcat:0.0.1
links:
- redis001:redishost
ports:
- "8080:8080"
environment:
TOMCAT_SERVER_ID: tomcat_server_001
restart: always
打开控制台,在docker-compose.yml文件所在目录下执行以下命令:
docker-compose up -d
执行完毕后环境就搭建成功了,在浏览器输入"localhost:8080"可以看到熟悉的tomcat首页:
[外链图片转存中...(img-dXCPA2Gd-1568682376493)]
环境OK了,可以开始编码了,源代码的git地址是git@github.com:zq2599/blog_demos.git,里面有多个工程,本篇用到的工程是redisdemo,如下图红框所示:
这是个maven工程,首先看下maven依赖,pom中的依赖除了jedis,还要加上spring,jstl,common等常用库,如下:
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<!-- 表示开发的时候引入,发布的时候不会加载此包 -->
<scope>test</scope>
</dependency>
<!-- spring核心包 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-oxm</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- 导入java ee jar 包 -->
<dependency>
<groupId>javax</groupId>
<artifactId>javaee-api</artifactId>
<version>7.0</version>
</dependency>
<!-- JSTL标签类 -->
<dependency>
<groupId>jstl</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<!-- 映入JSON -->
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-mapper-asl</artifactId>
<version>1.9.13</version>
</dependency>
<!-- 上传组件包 -->
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3.1</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.4</version>
</dependency>
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
<version>1.9</version>
</dependency>
<!-- redis -->
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>2.9.0</version>
</dependency>
然后是web.xml中的配置,包括spring mvc配置和扩展配置文件(spring-extends.xml):
<!-- Spring的配置文件 -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring-extends.xml</param-value>
</context-param>
<!-- 编码过滤器 -->
<filter>
<filter-name>encodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<async-supported>true</async-supported>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- Spring监听器 -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- 防止Spring内存溢出监听器 -->
<listener>
<listener-class>org.springframework.web.util.IntrospectorCleanupListener</listener-class>
</listener>
<!-- Spring MVC servlet -->
<servlet>
<servlet-name>SpringMVC</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring-mvc.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
<async-supported>true</async-supported>
</servlet>
<servlet-mapping>
<servlet-name>SpringMVC</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
接下来就是java编码了,由于web请求是多线程并发进行的,多个线程会同时使用redis服务,所以我们使用jedis的连接池JedisPool来为并发请求同时提供jedis服务的实例;
连接池一个就够了,所以这里创建了一个单例的类RedisPool,它的功能如下:
实例化一个Jedis资源池对象,也就是JedisPool;
为业务线程提供获取Jedis和归还Jedis的服务;
接下来我们看一下RedisPool的关键代码,包括实例化,JedisPool创建,获取Jedis,归还Jedis四个部分:
RedisPool的实例化:
public static RedisPool getInstance(){
if(null==instance) {
synchronized (RedisPool.class){
if(null==instance){
instance = new RedisPool();
}
}
}
return instance;
}
下面时资源池的初始化代码,注意红框部分的ADDR参数是redis服务器的ip,本例中要连接的是docker 容器,所以ADDR的值用的是"redishost",这个和tomcat容器启动时的link参数中的redis容器的别名一致:
下面是getJedis方法,从资源池取出一个Jedis实例给业务线程,由于jedisPool.getResource方法是线程安全的,所以getJedis()可以被多个线程同时调用,不用锁操作:
public Jedis getJedis(){
try {
if(null!=jedisPool){
Jedis jedis = jedisPool.getResource();
return jedis;
}else{
return null;
}
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
下面是业务线程用完Jedis实例后,归还给资源池时调用的方法,注意,本次使用的jedis是2.9.0版本,所以继续使用jedisPool.returnResource,jedis3.0版本之后就要用新的方法来归还到资源池了:
public void returnResource(final Jedis jedis){
if(jedis!=null){
//jedis.close()取代jedisPool.returnResource(jedis)方法将3.0版本开始
jedisPool.returnResource(jedis);
}
}
写完了RedisPool,就解决了Jedis的来源问题,接下来我们看下如何使用Jedis:
本文只是入门学习,所以只展示了部分Jedis服务,通过RedisService接口对外提供,API如下:
/**
* string操作,常规设置key-value
* @param key
* @param value
*/
void strSet(String key, String value);
/**
* string操作,常规通过key获取value
* @param key
* @return
*/
String setGet(String key);
/**
* list操作,尾部追加数据
* @param key
* @param value
*/
void listAppend(String key, String value);
/**
* list操作,获取说有数据
*/
List<String> listGetAll(String key);
/**
* 指定键值在redis中是否存在
* @param key
* @return
*/
boolean exists(String key);
具体的实现在RedisServiceImpl中,我们挑几个看看:
@Override
public void strSet(String key, String value) {
Jedis jedis = borrowJedis();
if(null!=jedis){
jedis.set(key, value);
}
returnJedis(jedis);
}
@Override
public String setGet(String key) {
Jedis jedis = borrowJedis();
if(null!=jedis){
String value = jedis.get(key);
returnJedis(jedis);
return value;
}
return null;
}
@Override
public void listAppend(String key, String value) {
Jedis jedis = borrowJedis();
if(null!=jedis){
jedis.rpush(key, value);
returnJedis(jedis);
}
}
@Override
public List<String> listGetAll(String key) {
List<String> list = null;
Jedis jedis = borrowJedis();
if(null!=jedis){
list = jedis.lrange(key, 0, -1);
returnJedis(jedis);
}
return null==list ? new ArrayList() : list;
}
可以发现,Jedis提供的api与redis客户端上的命令是很像的,例如jedis.get,jedis.lrange等等,基本上会操作命令行就能找到对应的api了。
再看看上次的对RedisService的调用场景,本例中用的是spring mvc,所以我们先看下RedisController:
下面四个方法代表了四个url入口:
@RequestMapping("/simpleset")
public String simpleset(HttpServletRequest request, Model model) {
addCommon(model);
return "simple_set";
}
@RequestMapping("/simpleget")
public String simpleget(HttpServletRequest request, Model model) {
addCommon(model);
return "simple_get";
}
@RequestMapping("/listappend")
public String listappend(HttpServletRequest request, Model model) {
addCommon(model);
return "list_append";
}
@RequestMapping("/listgetall")
public String listgetall(HttpServletRequest request, Model model) {
addCommon(model);
return "list_get_all";
}
以第一个simpleset为例,在浏览器中输入http://localhost:8080/redisdemo/simpleset,对应的simpleset方法会被调用,打开simple_get.jsp,如下图:
输入了key,value,点击提交后,由于form中指定了提交地址是strget,所以RedisController的get方法会被调用:
@RequestMapping("/strget")
public String get(HttpServletRequest request, Model model) {
String key = request.getParameter("key");
String rlt;
//判断key在redis中是否存在
if(redisService.exists(key)){
rlt = "simple_get_success";
String value = redisService.setGet(key);
model.addAttribute("value", value);
}else{
rlt = "check";
model.addAttribute("exists", "不存在");
}
model.addAttribute("key", key);
addCommon(model);
return rlt;
}
key如果存在,就取出数据,并跳转到simple_get_success.jsp页面,否则跳转到check.jsp页面,分别展示不同的内容。
以上就是jedis基本用法的简介,详情请见redisdemo源码。
另外,部署工程的时候,请使用命令mvn clean package -U -Dmaven.test.skip=true tomcat7:redeploy,就能将工程编译打包部署到tomcat上去。
欢迎关注我的公众号:程序员欣宸
Docker下Jedis体验的更多相关文章
- Docker下的Spring Cloud三部曲之一:极速体验
版权声明:欢迎转载,请注明出处,谢谢. http://blog.csdn.net/boling_cavalry/article/details/79177930 目录(?)[+] 从本章开始, ...
- docker下的Jenkins安装和体验【转】
原文地址:http://blog.csdn.net/boling_cavalry/article/details/78942408 作为一款优秀的持续集成工具,jenkins在日常的项目中经常会用到, ...
- Docker下使用disconf:极速体验
Docker下的disconf实战全文链接 <Docker搭建disconf环境,三部曲之一:极速搭建disconf>: <Docker搭建disconf环境,三部曲之二:本地快速构 ...
- Docker下kafka学习三部曲之一:极速体验kafka
Kafka是一种高吞吐量的分布式发布订阅消息系统,从本章开始我们先极速体验,再实战docker下搭建kafka环境,最后开发一个java web应用来体验kafka服务. 我们一起用最快的速度体验ka ...
- Docker下实战zabbix三部曲之一:极速体验
对于想学习和实践zabbix的读者来说,在真实环境搭建一套zabbix系统是件费时费力的事情,本文内容就是用docker来缩减搭建时间,目标是让读者们尽快投入zabbix系统的体验和实践: 环境信息 ...
- 实战maven私有仓库三部曲之三:Docker下搭建maven私有仓库
本章是<实战maven私有仓库>系列的第三篇,在前两章中,我们先在linux搭建maven私有仓库,然后在开发环境使用此仓库,本章我们在docker下快速搭建maven私有仓库,然后像前面 ...
- Docker下使用disconf:细说demo开发
Docker下的disconf实战全文链接 <Docker搭建disconf环境,三部曲之一:极速搭建disconf>: <Docker搭建disconf环境,三部曲之二:本地快速构 ...
- Docker下kafka学习三部曲之二:本地环境搭建
在上一章< Docker下kafka学习,三部曲之一:极速体验kafka>中我们快速体验了kafka的消息分发和订阅功能,但是对环境搭建的印象仅仅是执行了几个命令和脚本,本章我们通过实战来 ...
- Docker下dubbo开发三部曲之三:java开发
在前两章<Docker下dubbo开发,三部曲之一:极速体验>和<Docker下dubbo开发,三部曲之二:本地环境搭建>中,我们体验了dubbo环境搭建以及服务的发布和消费, ...
随机推荐
- Android 使用 DiffUtil 处理 RecyclerView 数据更新问题
背景 RecyclerView.Adapter#notifyDataSetChanged() 会每次刷新整个布局: 每次手动调用 RecyclerView.Adapter#notifyItemXx 系 ...
- java 购物商城小项目训练
java web 模拟购物车练习(项目一) 首页(index.jsp) <div align="center" class="index"> < ...
- 100天搞定机器学习|Day35 深度学习之神经网络的结构
100天搞定机器学习|Day1数据预处理 100天搞定机器学习|Day2简单线性回归分析 100天搞定机器学习|Day3多元线性回归 100天搞定机器学习|Day4-6 逻辑回归 100天搞定机器学习 ...
- Windows Server 2008 R2服务器内存使用率过高,但与任务管理器中进程占用内存和不一致
系统环境: Windows Server 2008 R2 + Sql Server 2008 R2 问题描述: Windows Server 2008 R2系统内存占用率过大,而在任务管理器中各进 ...
- Spring入门(十):Spring AOP使用讲解
1. 什么是AOP? AOP是Aspect Oriented Programming的缩写,意思是:面向切面编程,它是通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术. 可以认为AOP是 ...
- C语言的输入
%*2d%d 去掉前面两位 新旧函数 scanf和scanf_s 去掉安全检查 整型 scanf(“%d”,&x); scanf_s(“%d”,&x); 字符型 char ch; sc ...
- GSS4&&花仔游历各国
首先呢,我们想到一种数据结构可以区间开方,一看就不行,但是一看就算是10^18开六次方也只剩一,就不用开根了,所以可以想到用线段树或者分块水过,由于本人 不会用分块,只能用常数巨大的线段树 Code ...
- SpringBoot 配置 AOP 打印日志
在项目开发中,日志系统是必不可少的,用AOP在Web的请求做入参和出参的参数打印,同时对异常进行日志打印,避免重复的手写日志,完整案例见文末源码. 一.Spring AOP AOP(Aspect-Or ...
- BeanUtils开发包的使用
对内省技术有了一定的了解之后,我们就可以来学习一下BeanUtils开发包的使用了. 我们先假设一个情景,有一个JSP文件,如果要将该JSP文件中表单数据封装到Servlet文件应该怎么办?此时方法显 ...
- socket-遇到一枚假程序员
1. 一脸懵比 今天又偶然看到socket,对socket有点简单的概念,知道是网络编程.客户端与服务端通信等,但是不是太了解,就随便搜了下,几千万条记录,随便点开看了几页,socket跟网络编程也是 ...