![b9d8dc5da9c18a4a1c5a4971b13e94be.png](https://i-blog.csdnimg.cn/blog_migrate/0e82002d4ac09787960c92f8149d8f23.jpeg)
// 连接本地的Redis服务
Jedis jedis = new Jedis("127.0.0.1", 6379);
// 存储List缓存数据
jedis.lpush("test-list", "Java");
jedis.lpush("test-list", "PHP");
jedis.lpush("test-list", "C++");
// 获取list缓存数据
List<String> listCache = jedis.lrange("test-list", 0, 3);
for (int i = 0; i < listCache.size(); i++)
{
System.out.println("缓存输出:" + listCache.get(i));
}
jedis.close();
我们直到,redis是走网络通信的数据库,应用程序与redis的交互需要进行网络通信。
当我们使用jedis的操作命令与数据库交互时,具体都发生了什么呢?
public Jedis()
{
super();
}
public Jedis(final String host)
{
super(host);
}
public Jedis(final String host, final int port)
{
super(host, port);
}
public Jedis(final String host, final int port, final int timeout)
{
super(host, port, timeout);
}
public Jedis(final String host, final int port, final int connectionTimeout,
final int soTimeout)
{
super(host, port, connectionTimeout, soTimeout);
}
此时super调用的父类是BinaryJedis类的构造函数
protected Client client = null;
protected Transaction transaction = null;
protected Pipeline pipeline = null;
public BinaryJedis()
{
client = new Client();
}
public BinaryJedis(final String host)
{
URI uri = URI.create(host);
if (uri.getScheme() != null && uri.getScheme().equals("redis"))
{
initializeClientFromURI(uri);
}
else
{
client = new Client(host);
}
}
public BinaryJedis(final String host, final int port)
{
client = new Client(host, port);
}
public BinaryJedis(final String host, final int port, final int timeout)
{
client = new Client(host, port);
client.setConnectionTimeout(timeout);
client.setSoTimeout(timeout);
}
public BinaryJedis(final String host, final int port, final int connectionTimeout, final int soTimeout)
{
client = new Client(host, port);
client.setConnectionTimeout(connectionTimeout);
client.setSoTimeout(soTimeout);
}
到这里就会发现与redis进行网络通信的类就是Client类,继续向上发现:
Connection<<BinaryClient<<Client类的继承关系
public class Client extends BinaryClient implements Commands {
public Client() {
super();
}
public Client(final String host) {
super(host);
}
public Client(final String host, final int port) {
super(host, port);
}
..........................................................
}
public class BinaryClient extends Connection {
private boolean isInMulti;
private String password;
private int db;
private boolean isInWatch;
public BinaryClient() {
super();
}
public BinaryClient(final String host) {
super(host);
}
public BinaryClient(final String host, final int port) {
super(host, port);
}
public BinaryClient(final String host, final int port, final boolean ssl) {
super(host, port, ssl);
}
...............
}
public class Connection implements Closeable {
private static final byte[][] EMPTY_ARGS = new byte[0][];
private String host = Protocol.DEFAULT_HOST;
private int port = Protocol.DEFAULT_PORT;
private Socket socket;
private RedisOutputStream outputStream;
private RedisInputStream inputStream;
private int connectionTimeout = Protocol.DEFAULT_TIMEOUT;
private int soTimeout = Protocol.DEFAULT_TIMEOUT;
private boolean broken = false;
private boolean ssl;
private SSLSocketFactory sslSocketFactory;
private SSLParameters sslParameters;
private HostnameVerifier hostnameVerifier;
public Connection() {
}
public Connection(final String host) {
this.host = host;
}
public Connection(final String host, final int port) {
this.host = host;
this.port = port;
}
public Connection(final String host, final int port, final boolean ssl) {
this.host = host;
this.port = port;
this.ssl = ssl;
}
public Connection(final String host, final int port, final boolean ssl,
SSLSocketFactory sslSocketFactory, SSLParameters sslParameters,
HostnameVerifier hostnameVerifier) {
this.host = host;
this.port = port;
this.ssl = ssl;
this.sslSocketFactory = sslSocketFactory;
this.sslParameters = sslParameters;
this.hostnameVerifier = hostnameVerifier;
}
.................................................................
}
可以看到创建Jedis对象的时候并没有进行真正的网络连接,那么什么时候才执行的呢?
/**
* 获取特定键对应的值.如果键不存在,会返回null.如果存储在该关键字上的值不是一个字符串,
将会返回错误,因为get只能处理字符串类型。
*
* 时间复杂度: O(1)
*
* @param key
* @return Bulk reply
*/
public String get(final String key)
{
checkIsInMultiOrPipeline();
client.sendCommand(Protocol.Command.GET, key);
return client.getBulkReply();
}
上述方法是Jedis对象当中的一个普通方法,client对象最终会调用sendCommand方法来发送协议查询key所对应的value数据。
sendCommand方法是继承自Connection的,
public void sendCommand(final ProtocolCommand cmd, final String... args) {
final byte[][] bargs = new byte[args.length][];
for (int i = 0; i < args.length; i++) {
bargs[i] = SafeEncoder.encode(args[i]);
}
sendCommand(cmd, bargs);
}
public void sendCommand(final ProtocolCommand cmd) {
sendCommand(cmd, EMPTY_ARGS);
}
public void sendCommand(final ProtocolCommand cmd, final byte[]... args) {
try {
connect();
Protocol.sendCommand(outputStream, cmd, args);
} catch (JedisConnectionException ex) {
/*
* When client send request which formed by invalid protocol, Redis send back error message
* before close connection. We try to read it to provide reason of failure.
*/
try {
String errorMessage = Protocol.readErrorLineIfPossible(inputStream);
if (errorMessage != null && errorMessage.length() > 0) {
ex = new JedisConnectionException(errorMessage, ex.getCause());
}
} catch (Exception e) {
/*
* Catch any IOException or JedisConnectionException occurred from InputStream#read and just
* ignore. This approach is safe because reading error message is optional and connection
* will eventually be closed.
*/
}
// Any other exceptions related to connection?
broken = true;
throw ex;
}
}
public String getHost() {
return host;
}
public void setHost(final String host) {
this.host = host;
}
public int getPort() {
return port;
}
public void setPort(final int port) {
this.port = port;
}
public void connect() {
if (!isConnected()) {
try {
socket = new Socket();
// ->@wjw_add
socket.setReuseAddress(true);
socket.setKeepAlive(true); // Will monitor the TCP connection is
// valid
socket.setTcpNoDelay(true); // Socket buffer Whetherclosed, to
// ensure timely delivery of data
socket.setSoLinger(true, 0); // Control calls close () method,
// the underlying socket is closed
// immediately
// <-@wjw_add
socket.connect(new InetSocketAddress(host, port), connectionTimeout);
socket.setSoTimeout(soTimeout);
if (ssl) {
if (null == sslSocketFactory) {
sslSocketFactory = (SSLSocketFactory)SSLSocketFactory.getDefault();
}
socket = sslSocketFactory.createSocket(socket, host, port, true);
if (null != sslParameters) {
((SSLSocket) socket).setSSLParameters(sslParameters);
}
if ((null != hostnameVerifier) &&
(!hostnameVerifier.verify(host, ((SSLSocket) socket).getSession()))) {
String message = String.format(
"The connection to '%s' failed ssl/tls hostname verification.", host);
throw new JedisConnectionException(message);
}
}
outputStream = new RedisOutputStream(socket.getOutputStream());
inputStream = new RedisInputStream(socket.getInputStream());
} catch (IOException ex) {
broken = true;
throw new JedisConnectionException("Failed connecting to host "
+ host + ":" + port, ex);
}
}
}
@Override
public void close() {
disconnect();
}
public void disconnect() {
if (isConnected()) {
try {
outputStream.flush();
socket.close();
} catch (IOException ex) {
broken = true;
throw new JedisConnectionException(ex);
} finally {
IOUtils.closeQuietly(socket);
}
}
}
我们可以看到是在使用的时候才真正执行网络连接的。
---------
但是如果我们是采用JedisPool的形式来获取Jedis对象,那么其实在获取Jedis对象的时候就进行了网络连接操作;