小东子的个人技术专栏

重点关注Android、Java、智能硬件、JavaEE、react-native,Swift,微信小程序


  • 首页

  • 归档

  • 标签
小东子的个人技术专栏

微信小程序初体验-列表的上拉加载和下拉刷新的实现

发表于 2017-01-14   |   字数统计: 823(字)   |   阅读时长: 4(分)

微信小程序可谓是9月21号之后最火的一个名词了,一经出现真是轰炸了整个开发人员,当然很多App开发人员有了一个担心,微信小程序的到来会不会让移动端App颠覆,让移动端的程序员失业,身为一个Android开发者我是不相信的,即使有,那也是需要个一两年的过度和打磨才能实现的吧。

不管微信小程序是否能颠覆当今的移动开发格局,我们都要积极向上的心态去接收,去学习。不排斥新技术,所以,心动不如行动,赶紧先搭建一个微信小程序开发工具。那么接下来就让我们来开始学习列表的上拉加载和下拉刷新的实现吧(通过聚合数据平台获取微信新闻)。

1.介绍几个组件

1.1 scroll-view 组件

这里写图片描述

注意:使用竖向滚动时,需要给一个固定高度,通过 WXSS 设置 height。

1.2 image组件

这里写图片描述

注意:mode有12种模式,其中3种是缩放模式,9种是裁剪模式。

1.3 Icon组件

这里写图片描述

iconType: [
‘success’, ‘info’, ‘warn’, ‘waiting’, ‘safe_success’, ‘safe_warn’,
‘success_circle’, ‘success_no_circle’, ‘waiting_circle’, ‘circle’, ‘download’,
‘info_circle’, ‘cancel’, ‘search’, ‘clear’
]

2.列表的上拉加载和下拉刷新的实现

2.1先来张效果图

这里写图片描述

2.2逻辑很简单,直接上代码

2.2.1 detail.wxml 布局文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<loading hidden="{{hidden}}" bindchange="loadingChange">
加载中...
</loading>
<scroll-view scroll-y="true" style="height: 100%;" bindscrolltolower="loadMore" bindscrolltoupper="refesh">
<view wx:if="{{hasRefesh}}" style="display: flex;flex-direction: row;align-items: center;align-self: center;justify-content: center;">
<icon type="waiting" size="45"/><text>刷新中...</text></view>
<view wx:else style="display:none" ><text></text></view>
<view class="lll" wx:for="{{list}}" wx:for-item="item" bindtap="bindViewTap"
data-title="{{item.title}}" >
<image style=" width: 50px;height: 50px;margin: 20rpx;" src="{{item.firstImg}}" ></image>
<view class="eee" >
<view style="margin:5px;font-size:8px"> 标题:{{item.title}}</view>
<view style="margin:5px;color:red;font-size:6px"> 来源:{{item.source}}</view>
</view>
</view>
<view class="tips1">
<view wx:if="{{hasMore}}" style="display: flex;flex-direction: row;align-items: center;align-self: center;justify-content: center;">
<icon type="waiting" size="45"/><text>玩命的加载中...</text></view>
<view wx:else><text>没有更多内容了</text></view>
</view>
</scroll-view>

2.2.2 detail.js逻辑代码文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
var network_util = require('../../utils/network_util.js');
var json_util = require('../../utils/json_util.js');
Page({
data:{
// text:"这是一个页面"
list:[],
dd:'',
hidden:false,
page: 1,
size: 20,
hasMore:true,
hasRefesh:false
},
onLoad:function(options){
var that = this;
var url = 'http://v.juhe.cn/weixin/query?key=f16af393a63364b729fd81ed9fdd4b7d&pno=1&ps=10';
network_util._get(url,
function(res){
that.setData({
list:res.data.result.list,
hidden: true,
});
},function(res){
console.log(res);
});
},
onReady:function(){
// 页面渲染完成
},
onShow:function(){
// 页面显示
},
onHide:function(){
// 页面隐藏
},
onUnload:function(){
// 页面关闭
},
//点击事件处理
bindViewTap: function(e) {
console.log(e.currentTarget.dataset.title);
},
//加载更多
loadMore: function(e) {
var that = this;
that.setData({
hasRefesh:true,});
if (!this.data.hasMore) return
var url = 'http://v.juhe.cn/weixin/query?key=f16af393a63364b729fd81ed9fdd4b7d&pno='+(++that.data.page)+'&ps=10';
network_util._get(url,
function(res){
that.setData({
list: that.data.list.concat(res.data.result.list),
hidden: true,
hasRefesh:false,
});
},function(res){
console.log(res);
})
},
//刷新处理
refesh: function(e) {
var that = this;
that.setData({
hasRefesh:true,
});
var url = 'http://v.juhe.cn/weixin/query?key=f16af393a63364b729fd81ed9fdd4b7d&pno=1&ps=10';
network_util._get(url,
function(res){
that.setData({
list:res.data.result.list,
hidden: true,
page:1,
hasRefesh:false,
});
},function(res){
console.log(res);
})
},
})

最后的效果:
这里写图片描述

关于新闻的详情实现,后面在实现,由于还不知道怎么加载h5页面。谢谢你学习,有问题直接QQ(1561281670)交流。

代码地址:https://github.com/lidong1665/WeiXinProject

小东子的个人技术专栏

Redis的安装、部署、主从配置

发表于 2017-01-12   |   字数统计: 860(字)   |   阅读时长: 3(分)

1. Redis的简介

Redis是一个开源的,先进的 key-value 存储可用于构建高性能,可扩展的 Web 应用程序的解决方案。

Redis官方网网站是:http://www.redis.io/,如下:
这里写图片描述

Redis 有三个主要使其有别于其它很多竞争对手的特点:
Redis是完全在内存中保存数据的数据库,使用磁盘只是为了持久性目的;
Redis相比许多键值数据存储系统有相对丰富的数据类型;
Redis可以将数据复制到任意数量的从服务器中;

2. Redis优点

  • 异常快速 : Redis是非常快的,每秒可以执行大约110000设置操作,81000个/每秒的读取操作。
  • 支持丰富的数据类型 : Redis支持最大多数开发人员已经知道如列表,集合,可排序集合,哈希等数据类型。这使得在应用中很容易解决的各种问题,因为我们知道哪些问题处理使用哪种数据类型更好解决。

  • 操作都是原子的 : 所有 Redis 的操作都是原子,从而确保当两个客户同时访问 Redis 服务器得到的是更新后的值(最新值)。

  • MultiUtility工具:Redis是一个多功能实用工具,可以在很多如:缓存,消息传递队列中使用(Redis原生支持发布/订阅),在应用程序中,如:Web应用程序session,网站页面点击数等任何短暂的数据,最新的100条评论等;

    3.Redis环境

    要在 Ubuntu 上安装 Redis,打开终端,然后输入以下命令:
1
2
$sudo apt-get update
$sudo apt-get install redis-server

这将在您的计算机上安装Redis
启动 Redis

1
$redis-server

查看 redis 是否还在运行

1
$redis-cli

这将打开一个 Redis 提示符,如下图所示:

1
redis 127.0.0.1:6379>

在上面的提示信息中:127.0.0.1 是本机的IP地址,6379是 Redis 服务器运行的端口。现在输入 PING 命令,如下图所示:

1
2
redis 127.0.0.1:6379> ping
PONG

这说明现在你已经成功地在计算机上安装了 Redis。
在Ubuntu上安装Redis桌面管理器
要在Ubuntu 上安装 Redis桌面管理,可以从 http://redisdesktop.com/download 下载包并安装它。
Redis 桌面管理器会给你用户界面来管理 Redis 键和数据。
这里写图片描述

4. Redis的主从配置(以window为例)

在window中安装redis服务器,然后将文件复制一份,如下图:

这里写图片描述

修改文件夹名称分别为主服务器为Redis-master,从服务器为Redis - slave,
时候为修改从服务器redis.windows.conf文件中的端口prot为6380,在6380的redis.windows.conf中指定 是6379的slave,如:

1
2
#配置6379主服务器配置一个从服务器6380
slaveof 127.0.0.1 6379

这样Redis的一主一从就配置好了。接下来启动两个主从服务器:

4.1. 启动Redis-master:

1
redis-server.exe redis.windows.conf

这里写图片描述

4.2. 启动Redis - slave:

1
redis-server.exe redis.windows.conf

这里写图片描述

4.3 连接主Redis-master服务并保存数据:

1
2
3
4
5
6
C:\Program Files\Redis-master>redis-cli.exe
127.0.0.1:6379> set test1 text_1
OK
127.0.0.1:6379> get test1
"text_1"
127.0.0.1:6379>

4.4.连接主Redis - slave服务查看数据:

1
2
3
4
C:\Program Files\Redis - slave>redis-cli.exe
127.0.0.1:6379> get test1
"text_1"
127.0.0.1:6379>

4.5 用Redis Desktop Manager查看数据

这里写图片描述

总结:Redis简单使用就这么多,谢谢的的阅读。

小东子的个人技术专栏

Zookeeper 安装和部署

发表于 2017-01-12   |   字数统计: 2,545(字)   |   阅读时长: 10(分)

1. Zookeeper 简介

ZooKeeper是一个分布式的,开放源码的分布式应用程序协调服务,是Google的Chubby一个开源的实现,是Hadoop和Hbase的重要组件。它是一个为分布式应用提供一致性服务的软件,提供的功能包括:配置维护、域名服务、分布式同步、组服务等。

ZooKeeper的目标就是封装好复杂易出错的关键服务,将简单易用的接口和性能高效、功能稳定的系统提供给用户。
ZooKeeper包含一个简单的原语集, 提供Java和C的接口。
ZooKeeper代码版本中,提供了分布式独享锁、选举、队列的接口,代码在zookeeper-3.4.8\src\recipes。其中分布锁和队列有Java和C两个版本,选举只有Java版本。

2. Zookeeper原理

ZooKeeper是以Fast Paxos算法为基础的,Paxos 算法存在活锁的问题,即当有多个proposer交错提交时,有可能互相排斥导致没有一个proposer能提交成功,而Fast Paxos作了一些优化,通过选举产生一个leader (领导者),只有leader才能提交proposer,具体算法可见Fast Paxos。因此,要想弄懂ZooKeeper首先得对Fast Paxos有所了解。
ZooKeeper的基本运转流程:
1、选举Leader。
2、同步数据。
3、选举Leader过程中算法有很多,但要达到的选举标准是一致的。
4、Leader要具有最高的zxid。
5、集群中大多数的机器得到响应并follow选出的Leader。[3]

3. Zookeeper特点

在Zookeeper中,znode是一个跟Unix文件系统路径相似的节点,可以往这个节点存储或获取数据。如果在创建znode时Flag设置为EPHEMERAL,那么当创建这个znode的节点和Zookeeper失去连接后,这个znode将不再存在在Zookeeper里,Zookeeper使用Watcher察觉事件信息。当客户端接收到事件信息,比如连接超时、节点数据改变、子节点改变,可以调用相应的行为来处理数据。Zookeeper的Wiki页面展示了如何使用Zookeeper来处理事件通知,队列,优先队列,锁,共享锁,可撤销的共享锁,两阶段提交。

那么Zookeeper能做什么事情呢,简单的例子:假设我们有20个搜索引擎的服务器(每个负责总索引中的一部分的搜索任务)和一个总服务器(负责向这20个搜索引擎的服务器发出搜索请求并合并结果集),一个备用的总服务器(负责当总服务器宕机时替换总服务器),一个web的cgi(向总服务器发出搜索请求)。搜索引擎的服务器中的15个服务器提供搜索服务,5个服务器正在生成索引。这20个搜索引擎的服务器经常要让正在提供搜索服务的服务器停止提供服务开始生成索引,或生成索引的服务器已经把索引生成完成可以提供搜索服务了。使用Zookeeper可以保证总服务器自动感知有多少提供搜索引擎的服务器并向这些服务器发出搜索请求,当总服务器宕机时自动启用备用的总服务器。

4. Zookeeper的下载

可以从 https://zookeeper.apache.org/releases.html 下载ZooKeeper,目前最新的稳定版本为 3.4.8 版本,用户可以自行选择一个速度较快的镜像来下载即可。

5. Zookeeper的目录结构

下载并解压ZooKeeper软件压缩包后,可以看到zk包含以下的文件和目录:

这里写图片描述

这里写图片描述
ZooKeeper软件的文件和目录

  • bin目录
    zk的可执行脚本目录,包括zk服务进程,zk客户端,等脚本。其中,.sh是Linux环境下的脚本,.cmd是Windows环境下的脚本。
  • lib目录
    zk依赖的包。
  • libexec目录
    一些用于操作zk的工具包。

    5.单机模式

ZooKeeper的安装包括单机模式安装,以及集群模式安装。

单机模式较简单,是指只部署一个zk进程,客户端直接与该zk进程进行通信。
在开发测试环境下,通过来说没有较多的物理资源,因此我们常使用单机模式。当然在单台物理机上也可以部署集群模式,但这会增加单台物理机的资源消耗。故在开发环境中,我们一般使用单机模式。

5.1 运行配置

在etc/zookeeper/目录下提供了zoo.cfg,打开zoo.cfg,可以看到默认的一些配置。

tickTime
时长单位为毫秒,为zk使用的基本时间度量单位。例如,1 tickTime是客户端与zk服务端的心跳时间,2 tickTime是客户端会话的超时时间。
tickTime的默认值为2000毫秒,更低的tickTime值可以更快地发现超时问题,但也会导致更高的网络流量(心跳消息)和更高的CPU使用率(会话的跟踪处理)。

1
tickTime=2000

clientPort
zk服务进程监听的TCP端口,默认情况下,服务端会监听2181端口。

1
clientPort=2181

dataDir
无默认配置,必须配置,用于配置存储快照文件的目录。如果没有配置dataLogDir,那么事务日志也会存储在此目录。

1
2
dataDir=/usr/local/var/run/zookeeper/data
dataLogDir=/usr/local/var/run/zookeeper/logs

5.2 启动

在mac环境下,将zookeeper的bin目录配置到环境变量中,直接执行命令

1
zkServer start

这个命令使得zk服务进程在后台进行。

这里写图片描述
如果想在前台中运行以便查看服务器进程的输出日志,可以通过以下命令运行:

1
zkServer start-foreground

这里写图片描述

执行此命令,可以看到大量详细信息的输出,以便允许查看服务器发生了什么。

5.3 连接

如果是连接同一台主机上的zk进程,那么直接运行bin/目录下的zkCli.cmd(Windows环境下)或者zkCli.sh(mac环境下),即可连接上zk。
直接执行zkCli.cmd或者zkCli.sh命令默认以主机号 127.0.0.1,端口号 2181 来连接zk,如果要连接不同机器上的zk,可以使用 -server 参数,例如:

1
zkCli -server 192.168.0.1:2181

这里写图片描述

6.集群模式

单机模式的zk进程虽然便于开发与测试,但并不适合在生产环境使用。在生产环境下,我们需要使用集群模式来对zk进行部署。

注意
在集群模式下,建议至少部署3个zk进程,或者部署奇数个zk进程。如果只部署2个zk进程,当其中一个zk进程挂掉后,剩下的一个进程并不能构成一个quorum的大多数。因此,部署2个进程甚至比单机模式更不可靠,因为2个进程其中一个不可用的可能性比一个进程不可用的可能性还大。

6. 1 运行配置

在集群模式下,所有的zk进程可以使用相同的配置文件(是指各个zk进程部署在不同的机器上面),例如如下配置:

1
2
3
4
5
6
7
tickTime=2000
dataDir=/home/lidong/zookeeper
clientPort=2181
initLimit=5
syncLimit=2
server.1=192.168.0.105:2888:3888
server.2=192.168.0.108:2888:3888

initLimit
ZooKeeper集群模式下包含多个zk进程,其中一个进程为leader,余下的进程为follower。
当follower最初与leader建立连接时,它们之间会传输相当多的数据,尤其是follower的数据落后leader很多。initLimit配置follower与leader之间建立连接后进行同步的最长时间。
syncLimit
配置follower和leader之间发送消息,请求和应答的最大时间长度。
tickTime
tickTime则是上述两个超时配置的基本单位,例如对于initLimit,其配置值为5,说明其超时时间为 2000ms * 5 = 10秒。
server.id=host:port1:port2
其中id为一个数字,表示zk进程的id,这个id也是dataDir目录下myid文件的内容。
host是该zk进程所在的IP地址,port1表示follower和leader交换消息所使用的端口,port2表示选举leader所使用的端口。
dataDir
其配置的含义跟单机模式下的含义类似,不同的是集群模式下还有一个myid文件。myid文件的内容只有一行,且内容只能为1 - 255之间的数字,这个数字亦即上面介绍server.id中的id,表示zk进程的id。
注意
如果仅为了测试部署集群模式而在同一台机器上部署zk进程,server.id=host:port1:port2配置中的port参数必须不同。但是,为了减少机器宕机的风险,强烈建议在部署集群模式时,将zk进程部署不同的物理机器上面。

6. 2启动

假如我们打算在两台不同的机器 192.168.0.105(windows),192.168.0.108(mac os)上各部署一个zk进程,以构成一个zk集群。
两个zk进程均使用相同的 zoo.cfg 配置:
192.168.0.105(windows)
tickTime=2000
dataDir=D:/zookeeper
clientPort=2181
initLimit=5
syncLimit=2
server.1=192.168.0.105:2888:3888
server.2=192.168.0.108:2888:3888
这里写图片描述

192.168.0.100(mac os)
tickTime=2000
dataDir=/home/lidong/zookeeper
clientPort=2181
initLimit=5
syncLimit=2
server.1=192.168.0.105:2888:3888
server.2=192.168.0.108:2888:3888

这里写图片描述
在window主机器dataDir目录( D:/zookeeper目录)下,分别生成一个myid文件,其内容分别为1,2。
在Mac os主机器dataDir目录( /home/lidong/zookeeper)下,分别生成一个myid文件,其内容分别为1,2。
然后分别在这两台机器上启动zk进程,这样我们便将zk集群启动了起来。

6. 3连接

可以使用以下命令来连接一个zk集群:

1
zkCli -server 192.168.0.105:2181,192.168.0.108:2181

成功连接后,可以看到如下输出:

1
2
3
4
5
6
7
8
Connecting to 192.168.0.105:2181,192.168.0.108:2181
Welcome to ZooKeeper!
JLine support is enabled
WATCHER::
WatchedEvent state:SyncConnected type:None path:null
[zk: 192.168.0.105:2181,192.168.0.108:2181(CONNECTED) 0]

从日志输出可以看到,客户端连接的是192.168.0.108:2181进程,客户端已成功连接上zk集群。

注意:连接到那个集群是随机的。

小东子的个人技术专栏

dubbo2.5-spring4-mybastis3.2-springmvc4-mongodb3.4-redis3.2整合(六)Spring中Redis的缓存的使用

发表于 2017-01-12   |   字数统计: 1,456(字)   |   阅读时长: 7(分)

前面已经写了四篇关于dubbo2.5-spring4-mybastis3.2-springmvc4-mongodb3.4-redis3.2整合的文章:

  1. dubbo2.5-spring4-mybastis3.2-springmvc4-mongodb3.4-redis3.2整合(一)Dubbo的使用

  2. dubbo2.5-spring4-mybastis3.2-springmvc4-mongodb3.4-redis3.2整合(二)之 JDBC连接池、监控组件 Druid

  3. dubbo2.5-spring4-mybastis3.2-springmvc4-mongodb3.4-redis3.2整合(三)使用Spring AOP实现mysql的读写分离

  4. dubbo2.5-spring4-mybastis3.2-springmvc4-mongodb3.4-redis3.2整合(四)Spring AOP中使用log4j实现http请求日志入mongodb

  5. dubbo2.5-spring4-mybastis3.2-springmvc4-mongodb3.4-redis3.2整合(五)Spring中spring-data-redis的使用

    接着上一篇文章,今天来写一篇关于Spring-data-redis在Spring中的缓存的使用

缓存(Caching)可以存储经常会用到的信息,这样每次需要的时候,这些信息都可以立即可用的。尽管Spring自身并没有实现缓存的解决方案,但是他对缓存功能提供了声明式的支持,能够与各种流行的缓存进行集成。几天主要介绍的是redis的缓存的支持。

1. Spring中启用对缓存管理的支持

Spring中对缓存管理器的支持有两种方式:

  • 注解驱动的缓存
  • XML声明的缓存

1.1 注解驱动的缓存

使用Spring的缓存抽象时,最为通用的方式就是在方法上添加@Cacheable和@CacheEvict注解。

在往bean添加缓存注解之前,必须要启用Spring对注解驱动的支持。如果我们使用java配置的话,那么可以在其中一个配置上添加@EnableCaching,这样的话就能启动注解驱动的缓存。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
package com.lidong.util;
import java.lang.reflect.Method;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.interceptor.KeyGenerator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.core.RedisTemplate;
@Configuration
@EnableCaching
public class CachingConfig extends CachingConfigurerSupport{
@Bean
public KeyGenerator wiselyKeyGenerator(){
return new KeyGenerator() {
@Override
public Object generate(Object target, Method method,
Object... params) {
StringBuilder sb = new StringBuilder();
sb.append(target.getClass().getName());
sb.append(method.getName());
for (Object obj : params) {
sb.append(obj.toString());
}
return sb.toString();
}
};
}
/**
* 声明缓存管理器
* @param redisTemplate
* @return
*/
@Bean
public CacheManager cacheManager(RedisTemplate<String, Object> redisTemplate) {
return new RedisCacheManager(redisTemplate);
}
}

1.2 XML声明的缓存

如果以XML的方式配置应用的话,那么可以是使用Spring cache命名空间的

1
<cache:annotation-driven/>

元素来启动注解驱动的缓存。

1
2
3
4
5
6
7
8
9
10
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://www.springframework.org/schema/beans" xmlns:cache="http://www.springframework.org/schema/cache" xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/cache http://www.springframework.org/schema/cache/spring-cache-4.0.xsd">
<!--启用缓存-->
<cache:annotation-driven/>
<!--声明缓存管理器-->
<bean id="org.springframework.data.redis.cache.RedisCacheManager"/>
</beans>

2. Spring中配置缓存管理器

Spring 3.1内置了五个缓存管理器

  • SimpleCacheManager
  • NoOpCacheManager
  • ConcrrentMapCacheManager
  • CompositeCacheManager
  • EhCacheCacheManager

Spring 3.2引入了另外的一个缓存管理器,这个缓存管理器可以在基于JCache(JSR-107)的缓存提供商之中。除了核心的Spring框架,Spring data又提供了两个缓存管理器。

  • RedisCacheManager 来自于Spring-data-redis项目
  • GemfireCacheManager 来自于Spring-data-GemFire项目

所以我们选择缓存管理器时候,取决于使用底层缓存供应商。

3. Spring中配置Redis缓存管理器

缓存的条目不过就是一个键值对(key-vlaue),其中key描述了产生value的操作和参数。因此你,Redis作为key-value存储,非常适合于做缓存。
Redis可以用来为spring缓存抽象机制存储缓存条目,Spring-data-redis提供了RedisCacheManager,这是CacheManager的一个实现。RedisCacheManager 会与一个Redis服务器协作,并且通过RedisTemplate将缓存条目存储到Redis中。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
@Configuration
@EnableCaching
public class RedisCachingConfig extends CachingConfigurerSupport{
@Bean
public KeyGenerator wiselyKeyGenerator(){
return new KeyGenerator() {
@Override
public Object generate(Object target, Method method,
Object... params) {
StringBuilder sb = new StringBuilder();
sb.append(target.getClass().getName());
sb.append(method.getName());
for (Object obj : params) {
sb.append(obj.toString());
}
return sb.toString();
}
};
}
/**
* 声明缓存管理器RedisCacheManager
* @param redisTemplate
* @return
*/
@Bean
public CacheManager cacheManager(RedisTemplate<String, Object> redisTemplate) {
return new RedisCacheManager(redisTemplate);
}
}

4. 为方法添加注解以支持缓存

Spring 的缓存抽象在很大程度上是围绕切面的构建的。在Spring中启用缓存时,会创建一个切面,它触发一个或更多的Spring的缓存注解。

Spring中提供了四个注解来声明缓存规则

  • @Cacheable 声明Spring在调用方法之前,首先应该在缓存中查找方法的返回值。如果这个值能够找到,就会返回存储的值,否则的话,这个方法就会被调用,返回值会放在缓存之中。
  • @CachePut 表明Spring应该将方法的返回值放到缓存中,在方法的调用前并不会检查缓存,方法始终都会被调用
  • @CacheEvict表明Spring应该在缓存中清除一个或多个条目
  • @Caching 这是一个分组的注解,能够同时应用多个其他的缓存注解

在Service层缓存数据的数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
package com.lidong.core.user.service;
import java.util.List;
import javax.annotation.Resource;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import com.lidong.api.service.user.IUserService;
import com.lidong.core.user.dao.IUserDao;
import com.lidong.model.user.User;
@Service("userService")
public class UserServiceImp implements IUserService {
@Resource
IUserDao mIUserDao;
@Override
public String sayHello(String name) {
return "Hello " + name;
}
@Cacheable(value={"getUserById"})
@Override
public User getUserById(int userId) {
return mIUserDao.selectByPrimaryKey(userId);
}
@Override
public User getUserByUsername(String username) {
return mIUserDao.selectByPrimaryUsername(username);
}
@CacheEvict(value={"getAllUser"},allEntries=true)
@Override
public void addUser(User user) {
mIUserDao.insert(user);
}
@Cacheable(value={"getAllUser"})
@Override
public List<User> getAllUser() {
return mIUserDao.selectAllUsers();
}
@CacheEvict(value={"getAllUser","getUserById"},allEntries=true)
@Override
public int delUserById(Integer userId) {
return mIUserDao.deleteByPrimaryKey(userId);
}
@CacheEvict(value={"getAllUser","getUserById"},allEntries=true)
@Override
public int updateUser(User user) {
return mIUserDao.updateByPrimaryKey(user);
}
}

数据缓存成功

这里写图片描述

再次获取用户列表的时候;直接从缓存中读取用户的列表。

注意:缓存java对象时必须实现Serilaizable接口,因为Spring会将对象先序列化之后再存入到Redis中。

代码地址

小东子的个人技术专栏

dubbo2.5-spring4-mybastis3.2-springmvc4-mongodb3.4-redis3.2整合(五)Spring中spring-data-redis的使用

发表于 2017-01-12   |   字数统计: 1,314(字)   |   阅读时长: 6(分)

前面已经写了四篇关于dubbo2.5-spring4-mybastis3.2-springmvc4-mongodb3.4-redis3.2整合的文章:

  1. dubbo2.5-spring4-mybastis3.2-springmvc4-mongodb3.4-redis3.2整合(一)Dubbo的使用
  2. dubbo2.5-spring4-mybastis3.2-springmvc4-mongodb3.4-redis3.2整合(二)之 JDBC连接池、监控组件 Druid
  3. dubbo2.5-spring4-mybastis3.2-springmvc4-mongodb3.4-redis3.2整合(三)使用Spring AOP实现mysql的读写分离
  4. dubbo2.5-spring4-mybastis3.2-springmvc4-mongodb3.4-redis3.2整合(四)Spring AOP中使用log4j实现http请求日志入mongodb

今天继续写一篇关于Spring中spring-data-redis的使用。

Redis是一种特殊的类型的数据库,它被称为一种key-value存储。key-value存储保存的是键值对。实际上,key-value存储于哈希Map有很大的相似。
spring data是一种面向模板的数据访问,能够在使用Redis的时候,为我们提供了帮助。于是就有了spring-data-redis。

1. spring-data-redis的简介

spring-data-redis包含了多个模板实现,用来完成Redis数据库的存取功能。创建spring-data-redis模板之前,我们首先需要一个Redis连接工厂,spring-data-redis提供了四个连接工厂供我们选择。

2.spring-data-redis所需要依赖

1
2
3
4
5
6
7
8
9
10
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>2.8.0</version>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-redis</artifactId>
<version>1.6.2.RELEASE</version>
</dependency>

3. spring-data-redis的使用

3.1 连接到Redis

Redis连接工厂会生成到Redis数据库服务器的连接。spring-data-redis为四种Redis客户端实现了连接工厂:

  • JedisConnectionFactory
  • JredisConnectionFactory
  • LettuceConnectionFactory
  • SrpConnectionFactory

    具体选择哪一种取决于自己。

(1)创建redis.properties:

1
2
3
4
5
6
7
8
9
10
11
maxTotal=8
#最大空闲时间
maxIdle=8
#最短空闲时间
minIdle=0
#最大的等待时间
maxWaitMillis=6000
#Redis的连接地址
hostR=127.0.0.1
#端口
portR=6379

(2)创建spring-redis.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:rabbit="http://www.springframework.org/schema/rabbit"
xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/rabbit
http://www.springframework.org/schema/rabbit/spring-rabbit-1.2.xsd">
<!-- 引入redis.properties配置文件-->
<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location" value="classpath:redis.properties" /> </bean>
<!-- redis连接池的配置 -->
<bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig">
<property name="maxTotal" value="${maxTotal}" />
<property name="maxIdle" value="${maxIdle}" />
<property name="minIdle" value="${minIdle}" />
<property name="maxWaitMillis" value="10000" />
<property name="minEvictableIdleTimeMillis" value="300000"></property>
<property name="numTestsPerEvictionRun" value="3"></property>
<property name="timeBetweenEvictionRunsMillis" value="60000"></property>
</bean>
<!-- 工厂类配置 -->
<bean id="jedisConnectionFactory"
class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory">
<property name="hostName" value="${hostR}" />
<property name="port" value="${portR}" />
<property name="poolConfig" ref="jedisPoolConfig" />
<property name="timeout" value="15000"></property>
<property name="usePool" value="true"></property>
</bean>
<!-- redisTemplate配置 -->
<bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate">
<property name="connectionFactory" ref="jedisConnectionFactory" />
<property name="keySerializer">
<bean
class="org.springframework.data.redis.serializer.StringRedisSerializer" />
</property>
<property name="valueSerializer">
<bean
class="org.springframework.data.redis.serializer.JdkSerializationRedisSerializer" />
</property>
<property name="enableTransactionSupport" value="true" />
</bean>
</beans>

以上是我配置的jedisPoolConfig,jedisConnectionFactory,redisTemplate。

3.2 使用RedisTemplate

Redis连接工厂会生成到Redis key-value存储的连接(以RedisConnection的形式。)借助RedisConnection,可以存储和读取数据。

spring-redis-data以模板的形式提供了较好等级的数据访问方案。实际上,spring-data-redis提供了两个模板:

  • RedisTemplate
  • StringRedisTemplate

其中RedisTemplate使用两个类型进行了参数。第一个参数是key的类型,第二个参数是value的类型,而StringRedisTemplate是RedisTemplate的扩展,只关注String类型,也就是key和vlaue都是String类型。

3.2.1 RedisTemplate使用简单值

假设我们想通过RedisTemplate 保存User,其中key是users属性的值。借助opsForValue()方法完成该功能:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class UserRedisDaoImp extends AbstractBaseRedisTemplete<User>
implements IUserRedisDao {
@Override
public User findById(String key) {
return (User) redisTemplate.opsForValue().get(key);
}
@Override
public void saveUser(String key,User user) {
redisTemplate.opsForValue().set(key, user);
}
}
3.2.2 RedisTemplate使用List值

使用List类型的value与之类似,只需要使用opForList()方法,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
package com.lidong.core.user.dao;
import java.util.List;
import com.lidong.model.user.User;
import com.lidong.util.AbstractBaseRedisTemplete;
public class UserRedisDaoImp extends AbstractBaseRedisTemplete<User>
implements IUserRedisDao {
@Override
public List<User> getUserList(String key,long start,long end) {
return redisTemplate.opsForList().range(key, 0, end);
}
@Override
public Long addUserToUserList(String key, User user) {
return redisTemplate.opsForList().leftPush(key, user);
}
}
3.2.3 RedisTemplate使用Set值

除了使用List类型和value类型,我们还可以使用opForSet()的方法操作Set,最为常用的的就是向Set中添加一个元素:

1
2
3
4
@Override
public void saveUser(String key,User user) {
redisTemplate.opsForSet().add(key, user);
}

在我们有多个Set,并对这些Set集合进行差、交、并的操作。

1
2
3
4
5
Set<User> difference = redisTemplate.opsForSet().difference("users1", "users2");
Set<User> union = redisTemplate.opsForSet().union("users1", "users2");
Set<User> intersect = redisTemplate.opsForSet().intersect("users1", "users2");
//我还可以移除Set中的元素
Long remove = redisTemplate.opsForSet().remove("user1", user);
3.2.4 RedisTemplete绑定到某个key上

我们可以将Value、List、Set等可以绑定到指定的key上。这些用个的不太多,但是也简单。这里就不具体写了。

3.2.5 构造AbstractBaseRedisTemplete
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
package com.lidong.util;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.data.redis.core.RedisTemplate;
/**
* 基础的RedisTemplete
* @author lidong
* @param <T>
* @date 2017-1-5
*/
public abstract class AbstractBaseRedisTemplete<T> implements
ApplicationContextAware {
protected RedisTemplate<String,T> redisTemplate;
/**
* @Description RedisTemplate
* @param redisTemplate
*/
public void setRedisTemplate(RedisTemplate<String,T> redisTemplate) {
this.redisTemplate = redisTemplate;
}
@Override
public void setApplicationContext(ApplicationContext applicationContext)
throws BeansException {
@SuppressWarnings("unchecked")
RedisTemplate<String,T> redisTemplate = applicationContext.getBean(
"redisTemplate", RedisTemplate.class);
setRedisTemplate(redisTemplate);
}
}

Spring-Data-Redis的使用基本最常用 的就是这三种类型value类型、List类型、Set类型。

代码地址

1…678…10
李东

李东

细节决定成败,点滴铸就辉煌

46 文章
18 标签
© 2017 李东
由 Hexo 强力驱动
主题 - NexT.Pisces