国产片侵犯亲女视频播放_亚洲精品二区_在线免费国产视频_欧美精品一区二区三区在线_少妇久久久_在线观看av不卡

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|JavaScript|易語言|

服務器之家 - 編程語言 - Java教程 - 集成Spring Redis緩存的實現(xiàn)

集成Spring Redis緩存的實現(xiàn)

2021-06-24 10:20isea533 Java教程

今天小編就為大家分享一篇關于集成Spring Redis緩存的實現(xiàn),小編覺得內容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧

這里的緩存主要是用于 service 層的,所以下面的配置,都是針對 service 模塊的。

本文來自內部分享,對特殊信息進行了簡單處理。

本文都是在以緩存來講 redis 的使用,實際上 redis 不僅僅用于緩存,本身還是 nosql 數(shù)據(jù)庫,大家可以自己查找學習 redis 的常用場景。

一、添加依賴

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<!--緩存-->
<dependency>
 <groupid>org.springframework</groupid>
 <artifactid>spring-context-support</artifactid>
 <version>4.3.14.release</version>
</dependency>
<!--redis-->
<dependency>
 <groupid>org.springframework.data</groupid>
 <artifactid>spring-data-redis</artifactid>
 <version>1.8.10.release</version>
</dependency>
<dependency>
 <groupid>org.apache.commons</groupid>
 <artifactid>commons-pool2</artifactid>
 <version>2.4.3</version>
</dependency>
<dependency>
 <groupid>redis.clients</groupid>
 <artifactid>jedis</artifactid>
 <version>2.9.0</version>
</dependency>

二、配置

增加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
<?xml version="1.0" encoding="utf-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/xmlschema-instance"
xmlns:cache="http://www.springframework.org/schema/cache"
xmlns:util="http://www.springframework.org/schema/util"
xsi:schemalocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/cache
http://www.springframework.org/schema/cache/spring-cache.xsd
http://www.springframework.org/schema/util
http://www.springframework.org/schema/util/spring-util.xsd">
  <bean id="jedispoolconfig" class="redis.clients.jedis.jedispoolconfig">
    <property name="maxidle" value="${redis.pool.maxidle}"/>
    <property name="maxtotal" value="${redis.pool.maxtotal}"/>
    <property name="maxwaitmillis" value="${redis.pool.maxwaitmillis}"/>
    <property name="testonborrow" value="${redis.pool.testonborrow}"/>
    <property name="testonreturn" value="${redis.pool.testonreturn}"/>
  </bean>
  <bean id="jedisconnectionfactory" class="org.springframework.data.redis.connection.jedis.jedisconnectionfactory">
    <property name="hostname" value="${redis.master.ip}"/>
    <property name="port" value="${redis.master.port}"/>
    <property name="poolconfig" ref="jedispoolconfig"/>
  </bean>
  <bean id="rediskeyserializer" class="org.springframework.data.redis.serializer.stringredisserializer"/>
  <bean id="redisvalueserializer" class="org.springframework.data.redis.serializer.jdkserializationredisserializer"/>
  <bean id="redistemplate" class="org.springframework.data.redis.core.redistemplate">
    <property name="connectionfactory" ref="jedisconnectionfactory"/>
    <property name="keyserializer" ref="rediskeyserializer"/>
    <property name="hashkeyserializer" ref="rediskeyserializer"/>
    <property name="valueserializer" ref="redisvalueserializer"/>
    <property name="hashvalueserializer" ref="redisvalueserializer"/>
  </bean>
  <!--在 redis.properties 配置緩存詳細信息-->
  <util:properties id="redisexpires" location="classpath*:meta-inf/spring/redis.properties"/>
  <bean id="cachemanager" class="org.springframework.data.redis.cache.rediscachemanager">
    <constructor-arg index="0" ref="redistemplate"/>
    <!--默認緩存 10 分鐘-->
    <property name="defaultexpiration" value="600"/>
    <property name="useprefix" value="true"/>
    <property name="expires" ref="redisexpires"/>
  </bean>
  <!--啟用 cache 注解-->
  <cache:annotation-driven cache-manager="cachemanager" proxy-target-class="true"/>
</beans>

在 src/main/resources/ 下面如果沒有meta-inf/spring/ 目錄就創(chuàng)建一個,然后增加 redis.properties 配置,示例如下:

?
1
2
3
4
5
6
# 緩存名=有效時間
halfhour=1800
onehour=3600
oneday=86400
websession=1800
user=1800

除了上面配置外,在系統(tǒng)的 application.properties 中還需要提供下面幾個配置:

?
1
2
3
4
5
6
7
8
9
# redis 連接配置
redis.master.ip=10.10.10.100
redis.master.port=6379
# redis 連接池配置
redis.pool.maxidle=200
redis.pool.maxtotal=1024
redis.pool.maxwaitmillis=1000
redis.pool.testonborrow=true
redis.pool.testonreturn=true

三、通過注解方式使用緩存

示例中,redis.propreties 配置如下:

?
1
2
3
4
# 數(shù)據(jù)庫定義,緩存 30
databasedef=2592000
# 數(shù)據(jù)庫元數(shù)據(jù),緩存 1 小時
databasemeta=3600

這個示例在數(shù)據(jù)庫服務上配置的,數(shù)據(jù)庫服務中,查詢次數(shù)遠遠大于新增、修改、刪除的次數(shù),非常適合使用緩存。

1. 緩存數(shù)據(jù) @cacheable

?
1
2
3
4
5
@override
@cacheable(value = "databasedef", key = "'all'")
public list<databasedefinitionvo> selectall() {
 return databasedefinitiondao.selectallvo();
}

特別注意:所有這些注解中,key 的值是 spel 表達式,必須按照 spel 要求來寫。上面這個例子中,直接定義返回值的 key 是 all 字符串,需要加上單引號' 括起來,下面還有其他用法。

在例子中,下面的方法也使用了這個注解:

?
1
2
3
4
5
6
7
8
@override
@cacheable(value = "databasedef", key = "#id.tostring()")
public databasedefinition selectbyprimarykey(long id) {
  assert.notnull(id, "數(shù)據(jù)庫 id 不能為空!");
  databasedefinition definition = databasedefinitiondao.selectbyprimarykey(id);
  assert.notnull(definition, "數(shù)據(jù)庫定義不存在!");
  return definition;
}

在上面注解中,key 中的 #id 指的是參數(shù)中的 id,在 idea 中會有自動提示。.tostring() 是調用 id 的方法,在系統(tǒng)中規(guī)定了 key 必須是字符串類型,所以當類型是 long 的時候,需要轉換。

使用緩存的目的就是為了減少上面兩個方法調用時減少和數(shù)據(jù)庫的交互,減小數(shù)據(jù)庫的壓力,這是兩個主要的緩存數(shù)據(jù)的方法,下面的幾個操作都和上面這兩個方法有一定的關系。

重點:這里以及下面幾個注解中,都指定了 value = "databasedef",這里的意思是說,要使用前面配置中的 databasedef 對應的配置,也就是會緩存 30天。

2. 更新緩存 @cacheput

?
1
2
3
4
5
6
7
@override
@cacheput(value = "databasedef", key = "#result.id.tostring()")
public databasedefinition save(databasedefinition definition, currentuser usermodel)
   throws serviceexception {
 //代碼
 return definition;
}

更新緩存的方法需要注意的是返回值,在上面 save 方法中,有可能是新增,有可能是更新,不管是那個操作,當操作完成后,上面注解會根據(jù) key 的值生成 key,然后將方法的返回值作為 value 保存到緩存中。

這里 key 的寫法中 #result 指代返回值,.id 是返回值的屬性,.tostring() 是調用 id 屬性的方法,在系統(tǒng)中規(guī)定了 key 必須是字符串類型,所以當類型是 long 的時候,需要轉換。

這個方法上加的緩存還有問題,當新增或者更新后,通過 selectall() 返回的值已經(jīng)發(fā)生了變化,但是這里沒有清除 all 的緩存值,會導致 selectall() 出現(xiàn)臟數(shù)據(jù),下面會通過 @caching 注解改造這里。

3. 清除緩存 @cacheevict

?
1
2
3
4
5
6
7
8
9
@override
@cacheevict(value = "databasedef", key = "#id.tostring()")
public void deletebyprimarykey(long id) throws serviceexception {
 databasedefinition definition = selectbyprimarykey(id);
 if (definition.getloadstate().equals(databasedefinition.loadstate.up)) {
  throw new serviceexception("請先卸載數(shù)據(jù)庫!");
 }
 databasedefinitiondao.deletebyprimarykey(id);
}

在上面新增或者修改的時候根據(jù) id 緩存或者更新了緩存數(shù)據(jù),這里當刪除數(shù)據(jù)的時候,還需要清空對應的緩存數(shù)據(jù)。

在上面注解中,key 中的 #id 指的是參數(shù)中的 id,在 idea 中會有自動提示。

這個方法上加的緩存還有問題,當刪除后,通過 selectall() 返回的值已經(jīng)發(fā)生了變化,但是這里沒有清除 all 的緩存值,會導致 selectall() 出現(xiàn)臟數(shù)據(jù),下面會通過 @caching 注解改造這里。

4. 組合使用 @caching

上面兩個注解中,都提到了臟數(shù)據(jù),通過 @caching 注解可以解決這個問題。

先修改第二個注解,來解決 save 時的臟數(shù)據(jù):

?
1
2
3
4
5
6
7
8
@override
@caching(put = @cacheput(value = "databasedef", key = "#result.id.tostring()"),
     evict = @cacheevict(value = "databasedef", key = "'all'"))
public databasedefinition save(databasedefinition definition, currentuser usermodel)
   throws serviceexception {
 //其他代碼
 return definition;
}

前面說明,新增或者修改的時候,all 緩存中的數(shù)據(jù)已經(jīng)不對了,因此這里在 put 的同時,使用 evict 將 'all' 中的數(shù)據(jù)清除,這就保證了 selelctall 下次調用時,會重新從庫中讀取數(shù)據(jù)。

對上面的刪除方法,也進行類似的修改:

?
1
2
3
4
5
6
7
8
9
10
11
12
@override
@caching(evict = {
  @cacheevict(value = "databasedef", key = "#id.tostring()"),
  @cacheevict(value = "databasedef", key = "'all'")
})
public void deletebyprimarykey(long id) throws serviceexception {
 databasedefinition definition = selectbyprimarykey(id);
 if (definition.getloadstate().equals(databasedefinition.loadstate.up)) {
  throw new serviceexception("請先卸載數(shù)據(jù)庫!");
 }
 databasedefinitiondao.deletebyprimarykey(id);
}

注意這里的 evict 是個數(shù)組,里面配置了兩個清除緩存的配置。

5. 全局配置 @cacheconfig

在上面所有例子中,都指定了 value = "databasedef",實際上可以通過在類上使用 @cacheconfig 注解配置當前類中的 cachenames 值,配置后,如果和類上的 value 一樣就不需要在每個注解單獨配置。只有不同時再去指定,方法上的 value 值優(yōu)先級更高。

?
1
2
3
4
@service
@cacheconfig(cachenames = "databasedef")
public class databasedefinitionserviceimpl implements
     databasedefinitionservice, databasesqlexecuteservice, applicationlistener {

有了上面配置后,其他緩存名字相同的地方可以簡化,例如刪除方法修改后如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
@override
@caching(evict = {
  @cacheevict(key = "#id.tostring()"),
  @cacheevict(key = "'all'")
})
public void deletebyprimarykey(long id) throws serviceexception {
 databasedefinition definition = selectbyprimarykey(id);
 if (definition.getloadstate().equals(databasedefinition.loadstate.up)) {
  throw new serviceexception("請先卸載數(shù)據(jù)庫!");
 }
 databasedefinitiondao.deletebyprimarykey(id);
}

其他例子

除了上面針對 databasedef 的緩存外,還有 databasemeta 的配置:

?
1
2
3
4
5
6
7
8
9
10
11
12
@override
@cacheable(value = "databasemeta", key = "#databaseid.tostring()")
public list<tablevo> selecttablesbydatabaseid(long databaseid)
  throws exception {
 //代碼
}
@override
@cacheable(value = "databasemeta", key = "#databaseid + '_' + #tablename")
public tablevo selecttablebydatabaseidandtablename(long databaseid, string tablename)
  throws exception {
 //代碼
}

這兩個方法是獲取數(shù)據(jù)庫元數(shù)據(jù)的,只有修改數(shù)據(jù)庫表的時候才會變化,因此不存在清除緩存的情況,但是萬一修改表后,想要新的元數(shù)據(jù),該怎么辦?

因此增加了一個空的方法來清空數(shù)據(jù),方法如下:

?
1
2
3
4
@override
@cacheevict(value = "databasemeta", allentries = true)
public void cleantablescache() {
}

這里指定了 databasemeta,通過 allentries = true 清空所有 key 的緩存。通過這個方法可以保證在有需要的時候清空所有元數(shù)據(jù)的緩存。

實際上如果想要更精確的清除,可以傳入要清除的 databaseid 和 tablename 來更精確的清除。

增加緩存后的效果

調用 selecttablesbydatabaseid 多次時,輸出的日志如下:

info  c.n.d.u.dynamicdatasource - 當前數(shù)據(jù)源:默認數(shù)據(jù)源
debug c.n.d.datascopecontextproviderfilter - 服務調用返回前清除數(shù)據(jù)權限信息
info  c.n.d.u.dynamicdatasource - 當前數(shù)據(jù)源:默認數(shù)據(jù)源
debug c.n.d.d.d.selectbyprimarykey - ==>  preparing: select xxx (隱藏完整 sql)
debug c.n.d.d.d.selectbyprimarykey - ==> parameters: 1(long)
debug c.n.d.d.d.selectbyprimarykey - <==      total: 1
info  c.n.d.u.dynamicdatasource - 當前數(shù)據(jù)源:10.10.10.130/datareporting
debug c.n.d.datascopecontextproviderfilter - 服務調用返回前清除數(shù)據(jù)權限信息
info  c.n.d.u.dynamicdatasource - 當前數(shù)據(jù)源:默認數(shù)據(jù)源
debug c.n.d.datascopecontextproviderfilter - 服務調用返回前清除數(shù)據(jù)權限信息
info  c.n.d.u.dynamicdatasource - 當前數(shù)據(jù)源:默認數(shù)據(jù)源
debug c.n.d.datascopecontextproviderfilter - 服務調用返回前清除數(shù)據(jù)權限信息

從日志可以看出來,只有第一次進行了數(shù)據(jù)庫查詢,后續(xù)通過日志看不到數(shù)據(jù)庫操作。

調用清空緩存后,會再次查詢數(shù)據(jù)庫。

初次調用時,web請求花了 700多ms,后面再次調用時,平均不到 30 ms,這就是緩存最明顯的作用。

連接到 redis 服務后,查看所有 key,結果如下:

redis@redissvr:~$ redis-cli 
127.0.0.1:6379> keys *
1) "databasemeta:1"
2) "databasedef:all"
127.0.0.1:6379>

緩存中的數(shù)據(jù)都有 value 前綴,上面緩存了 all 和 id 為 1 的數(shù)據(jù)。

緩存注解是一種最簡單的緩存方式,但是需要配合 value 屬性的配置來使用,許多時候我們可能需要更精確的控制緩存,此時可以使用 redistemplate 來控制。

四、通過 redistemplate 使用緩存

有關這部分的詳細用法可以從網(wǎng)上搜索相關內容進行學習,這里列舉一個簡單的例子。

針對前面的 selectall 我們換一種方式進行緩存。

首先注入下面的接口:

?
1
2
@resource(name = "redistemplate")
private valueoperations<string, list> valueoper;

修改 selectall 方法如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
@override
//@cacheable(key = "'all'")
public list<databasedefinitionvo> selectall() {
 list<databasedefinitionvo> vos = valueoper.get("databasedef:all");
 if(vos != null){
  return vos;
 }
 vos = databasedefinitiondao.selectallvo();
 //緩存 1 小時
 valueoper.set("databasedef:all", vos, 1, timeunit.hours);
 return vos;
}

首先通過valueoper.get("databasedef:all") 嘗試獲取緩存信息,如果存在就直接返回。

如果不存在,就查詢數(shù)據(jù)庫,然后將查詢結果通過 set 進行緩存。

特別注意: 上面的 key,寫的是 "databasedef:all",也就是前綴需要自己加上,如果直接寫成 all,在 redis 中的 key 就是 all,不會自動增加前綴。

如果沒有前綴,那么當不同系統(tǒng)都使用 all 時,數(shù)據(jù)就會混亂!

五、redis 服務器配置注意事項

內網(wǎng)使用的服務器,特殊配置如下:

?
1
2
3
4
5
6
# by default protected mode is enabled. you should disable it only if
# you are sure you want clients from other hosts to connect to redis
# even if no authentication is configured, nor a specific set of interfaces
# are explicitly listed using the "bind" directive.
# protected-mode yes
protected-mode no

關閉了保護模式。

?
1
2
3
4
# if you are sure you want your instance to listen to all the interfaces
# just comment the following line.
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# bind 127.0.0.1

注釋了綁定的 ip,這樣可以讓所有電腦訪問 redis。

總結

以上就是這篇文章的全部內容了,希望本文的內容對大家的學習或者工作具有一定的參考學習價值,謝謝大家對服務器之家的支持。如果你想了解更多相關內容請查看下面相關鏈接

原文鏈接:https://blog.csdn.net/isea533/article/details/84563949

延伸 · 閱讀

精彩推薦
Weibo Article 1 Weibo Article 2 Weibo Article 3 Weibo Article 4 Weibo Article 5 Weibo Article 6 Weibo Article 7 Weibo Article 8 Weibo Article 9 Weibo Article 10 Weibo Article 11 Weibo Article 12 Weibo Article 13 Weibo Article 14 Weibo Article 15 Weibo Article 16 Weibo Article 17 Weibo Article 18 Weibo Article 19 Weibo Article 20 Weibo Article 21 Weibo Article 22 Weibo Article 23 Weibo Article 24 Weibo Article 25 Weibo Article 26 Weibo Article 27 Weibo Article 28 Weibo Article 29 Weibo Article 30 Weibo Article 31 Weibo Article 32 Weibo Article 33 Weibo Article 34 Weibo Article 35 Weibo Article 36 Weibo Article 37 Weibo Article 38 Weibo Article 39 Weibo Article 40
主站蜘蛛池模板: 国产成人福利在线 | 91精选| 亚洲精品一区二区三区精华液 | www.日韩视频 | 91.成人天堂一区 | 在线免费观看视频 | 在线免费色视频 | 欧美中文字幕一区 | 久久99精品国产自在现线 | 午夜精品福利在线观看 | 精品视频一区二区三区在线观看 | 国产精品久久av | 久久伊| 91久久久久久 | 中文在线a在线 | 日韩欧美国产一区二区 | 亚洲视频综合网 | 九月激情网 | 日韩综合在线 | 国产精品一码二码三码在线 | 狠狠艹| av中文字幕在线观看 | 欧美日韩国产一区二区三区 | 欧美午夜视频 | 黄色小视频免费 | 久久精品久久久久久 | 久久久久国产精品 | 久久九九 | 亚洲久草| 精品日韩一区二区三区 | 伊人婷婷| 欧美在线一区二区 | 91精品国产91久久综合 | 精品国产一区二区三区性色av | 亚洲精品乱码久久久久久金桔影视 | 久在线视频 | 国产精品自产拍在线观看 | 6080yy午夜一二三区久久 | 中文字幕高清视频 | 精品在线一区 | 亚洲精品视频在线播放 |