Spring Boot with Redis

Spring Boot簡介

Spring Boot是為了簡化Spring開發(fā)而生毛雇,從Spring 3.x開始,Spring社區(qū)的發(fā)展方向就是弱化xml配置文件而加大注解的戲份掂僵。最近召開的SpringOne2GX2015大會上顯示:Spring Boot已經(jīng)是Spring社區(qū)中增長最迅速的框架,前三名是:Spring Framework,Spring Boot和Spring Security大磺,這個應(yīng)該是未來的趨勢贡歧。

我學(xué)習(xí)Spring Boot滩租,是因?yàn)橥ㄟ^cli工具,spring boot開始往flask(python)利朵、express(nodejs)等web框架發(fā)展和靠近律想,并且Spring Boot幾乎不需要寫xml配置文件。感興趣的同學(xué)可以根據(jù)spring boot quick start這篇文章中的例子嘗試下绍弟。

學(xué)習(xí)新的技術(shù)最佳途徑是看官方文檔技即,現(xiàn)在Spring boot的release版本是1.3.0-RELEASE,相應(yīng)的參考文檔是Spring Boot Reference Guide(1.3.0-REALEASE)樟遣,如果有絕對英文比較吃力的同學(xué)而叼,可以參考中文版Spring Boot參考指南。在前段時間閱讀一篇技術(shù)文章豹悬,介紹如何閱讀ios技術(shù)文檔葵陵,我從中也有所收獲,那就是我們應(yīng)該重視spring.io上的guides部分——Getting Started Guides屿衅,這部分都是一些針對特定問題的demo埃难,值得學(xué)習(xí)。

Spring Boot的項(xiàng)目結(jié)構(gòu)

com
 +- example
     +- myproject
         +- Application.java
         |
         +- domain
         |   +- Customer.java
         |   +- CustomerRepository.java
         |
         +- service
         |   +- CustomerService.java
         |
         +- web
             +- CustomerController.java

如上所示,Spring boot項(xiàng)目的結(jié)構(gòu)劃分為web->service->domain涡尘,其中domain文件夾可類比與業(yè)務(wù)模型和數(shù)據(jù)存儲忍弛,即xxxBean和Dao層;service層是業(yè)務(wù)邏輯層考抄,web是控制器细疚。比較特別的是,這種類型的項(xiàng)目有自己的入口川梅,即主類疯兼,一般命名為Application.java。Application.java不僅提供入口功能贫途,還提供一些底層服務(wù)吧彪,例如緩存、項(xiàng)目配置等等丢早。

例子介紹

本文的例子是取自我的side project之中姨裸,日報(report)的查詢,試圖利用Redis作為緩存怨酝,優(yōu)化查詢效率傀缩。

知識點(diǎn)解析

1. 自定義配置

Spring Boot允許外化配置,這樣你可以在不同的環(huán)境下使用相同的代碼农猬。你可以使用properties文件赡艰、yaml文件,環(huán)境變量和命令行參數(shù)來外化配置斤葱。使用@Value注解慷垮,可以直接將屬性值注入到你的beans中。
Spring Boot使用一個非常特別的PropertySource來允許對值進(jìn)行合理的覆蓋揍堕,按照優(yōu)先考慮的順序排位如下:

1. 命令行參數(shù)
2. 來自java:comp/env的JNDI屬性
3. Java系統(tǒng)屬性(System.getProperties())
4. 操作系統(tǒng)環(huán)境變量
5. 只有在random.*里包含的屬性會產(chǎn)生一個RandomValuePropertySource
6. 在打包的jar外的應(yīng)用程序配置文件(application.properties,包含YAML和profile變量)
7. 在打包的jar內(nèi)的應(yīng)用程序配置文件(application.properties,包含YAML和profile變量)
8. 在@Configuration類上的@PropertySource注解
9. 默認(rèn)屬性(使用SpringApplication.setDefaultProperties指定)

使用場景:可以將一個application.properties打包在Jar內(nèi)换帜,用來提供一個合理的默認(rèn)name值;當(dāng)運(yùn)行在生產(chǎn)環(huán)境時鹤啡,可以在Jar外提供一個application.properties文件來覆蓋name屬性惯驼;對于一次性的測試,可以使用特病的命令行開關(guān)啟動递瑰,而不需要重復(fù)打包jar包祟牲。

具體的例子操作過程如下:

  • 新建配置文件(application.properties)
spring.redis.database=0
spring.redis.host=localhost
spring.redis.password= # Login password of the redis server.
spring.redis.pool.max-active=8
spring.redis.pool.max-idle=8
spring.redis.pool.max-wait=-1
spring.redis.pool.min-idle=0
spring.redis.port=6379
spring.redis.sentinel.master= # Name of Redis server.
spring.redis.sentinel.nodes= # Comma-separated list of host:port pairs.
spring.redis.timeout=0
  • 使用@PropertySource引入配置文件
@Configuration
@PropertySource(value = "classpath:/redis.properties")
@EnableCaching
public class CacheConfig extends CachingConfigurerSupport {
    ......
}
  • 使用@Value引用屬性值
@Configuration
@PropertySource(value = "classpath:/redis.properties")
@EnableCaching
public class CacheConfig extends CachingConfigurerSupport {
    @Value("${spring.redis.host}")
    private String host;
    @Value("${spring.redis.port}")
    private int port;
    @Value("${spring.redis.timeout}")
    private int timeout;
    ......
}

2. redis使用

  • 添加pom配置
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-redis</artifactId>
</dependency>
  • 編寫CacheConfig
@Configuration
@PropertySource(value = "classpath:/redis.properties")
@EnableCaching
public class CacheConfig extends CachingConfigurerSupport {
    @Value("${spring.redis.host}")
    private String host;
    @Value("${spring.redis.port}")
    private int port;
    @Value("${spring.redis.timeout}")
    private int timeout;
    @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();
            }
        };
    }
    @Bean
    public JedisConnectionFactory redisConnectionFactory() {
        JedisConnectionFactory factory = new JedisConnectionFactory();
        factory.setHostName(host);
        factory.setPort(port);
        factory.setTimeout(timeout); //設(shè)置連接超時時間
        return factory;
    }
    @Bean
    public CacheManager cacheManager(RedisTemplate redisTemplate) {
        RedisCacheManager cacheManager = new RedisCacheManager(redisTemplate);
        // Number of seconds before expiration. Defaults to unlimited (0)
        cacheManager.setDefaultExpiration(10); //設(shè)置key-value超時時間
        return cacheManager;
    }
    @Bean
    public RedisTemplate<String, String> redisTemplate(RedisConnectionFactory factory) {
        StringRedisTemplate template = new StringRedisTemplate(factory);
        setSerializer(template); //設(shè)置序列化工具,這樣ReportBean不需要實(shí)現(xiàn)Serializable接口
        template.afterPropertiesSet();
        return template;
    }
    private void setSerializer(StringRedisTemplate template) {
        Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
        ObjectMapper om = new ObjectMapper();
        om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        jackson2JsonRedisSerializer.setObjectMapper(om);
        template.setValueSerializer(jackson2JsonRedisSerializer);
    }
}
  • 啟動緩存抖部,使用@Cacheable注解在需要緩存的接口上即可
@Service
public class ReportService {
    @Cacheable(value = "reportcache", keyGenerator = "wiselyKeyGenerator")
    public ReportBean getReport(Long id, String date, String content, String title) {
        System.out.println("無緩存的時候調(diào)用這里---數(shù)據(jù)庫查詢");
        return new ReportBean(id, date, content, title);
    }
}

參考資料

  1. spring boot quick start
  2. Spring Boot參考指南
  3. Spring Boot Reference Guide(1.3.0-REALEASE)
  4. Getting Started Guides
  5. Caching Data in Spring Using Redis
  6. Spring boot使用Redis做緩存
  7. redis設(shè)計(jì)與實(shí)現(xiàn)

本號專注于后端技術(shù)说贝、JVM問題排查和優(yōu)化、Java面試題慎颗、個人成長和自我管理等主題乡恕,為讀者提供一線開發(fā)者的工作和成長經(jīng)驗(yàn)言询,期待你能在這里有所收獲。


javaadu
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末傲宜,一起剝皮案震驚了整個濱河市运杭,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌函卒,老刑警劉巖辆憔,帶你破解...
    沈念sama閱讀 221,430評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異报嵌,居然都是意外死亡虱咧,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,406評論 3 398
  • 文/潘曉璐 我一進(jìn)店門锚国,熙熙樓的掌柜王于貴愁眉苦臉地迎上來腕巡,“玉大人,你說我怎么就攤上這事血筑∫荼ⅲ” “怎么了?”我有些...
    開封第一講書人閱讀 167,834評論 0 360
  • 文/不壞的土叔 我叫張陵云挟,是天一觀的道長。 經(jīng)常有香客問我转质,道長园欣,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,543評論 1 296
  • 正文 為了忘掉前任休蟹,我火速辦了婚禮沸枯,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘赂弓。我一直安慰自己绑榴,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,547評論 6 397
  • 文/花漫 我一把揭開白布盈魁。 她就那樣靜靜地躺著翔怎,像睡著了一般。 火紅的嫁衣襯著肌膚如雪杨耙。 梳的紋絲不亂的頭發(fā)上赤套,一...
    開封第一講書人閱讀 52,196評論 1 308
  • 那天,我揣著相機(jī)與錄音珊膜,去河邊找鬼容握。 笑死,一個胖子當(dāng)著我的面吹牛车柠,可吹牛的內(nèi)容都是我干的剔氏。 我是一名探鬼主播塑猖,決...
    沈念sama閱讀 40,776評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼谈跛!你這毒婦竟也來了羊苟?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,671評論 0 276
  • 序言:老撾萬榮一對情侶失蹤币旧,失蹤者是張志新(化名)和其女友劉穎践险,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體吹菱,經(jīng)...
    沈念sama閱讀 46,221評論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡巍虫,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,303評論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了鳍刷。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片占遥。...
    茶點(diǎn)故事閱讀 40,444評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖输瓜,靈堂內(nèi)的尸體忽然破棺而出瓦胎,到底是詐尸還是另有隱情,我是刑警寧澤尤揣,帶...
    沈念sama閱讀 36,134評論 5 350
  • 正文 年R本政府宣布搔啊,位于F島的核電站,受9級特大地震影響北戏,放射性物質(zhì)發(fā)生泄漏负芋。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,810評論 3 333
  • 文/蒙蒙 一嗜愈、第九天 我趴在偏房一處隱蔽的房頂上張望旧蛾。 院中可真熱鬧,春花似錦蠕嫁、人聲如沸锨天。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,285評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽病袄。三九已至,卻和暖如春赘阀,著一層夾襖步出監(jiān)牢的瞬間陪拘,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,399評論 1 272
  • 我被黑心中介騙來泰國打工纤壁, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留左刽,地道東北人。 一個月前我還...
    沈念sama閱讀 48,837評論 3 376
  • 正文 我出身青樓酌媒,卻偏偏與公主長得像欠痴,于是被迫代替她去往敵國和親迄靠。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,455評論 2 359

推薦閱讀更多精彩內(nèi)容