Spring Boot with Redis

Spring Boot簡(jiǎn)介

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

我學(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),如果有絕對(duì)英文比較吃力的同學(xué),可以參考中文版Spring Boot參考指南。在前段時(shí)間閱讀一篇技術(shù)文章,介紹如何閱讀ios技術(shù)文檔,我從中也有所收獲,那就是我們應(yīng)該重視spring.io上的guides部分——Getting Started Guides,這部分都是一些針對(duì)特定問題的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ù)存儲(chǔ),即xxxBean和Dao層;service層是業(yè)務(wù)邏輯層,web是控制器。比較特別的是,這種類型的項(xiàng)目有自己的入口,即主類,一般命名為Application.java。Application.java不僅提供入口功能,還提供一些底層服務(wù),例如緩存、項(xiàng)目配置等等。

例子介紹

本文的例子是取自我的side project之中,日?qǐng)?bào)(report)的查詢,試圖利用Redis作為緩存,優(yōu)化查詢效率。

知識(shí)點(diǎn)解析

1. 自定義配置

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

1. 命令行參數(shù)
2. 來自java:comp/env的JNDI屬性
3. Java系統(tǒng)屬性(System.getProperties())
4. 操作系統(tǒng)環(huán)境變量
5. 只有在random.*里包含的屬性會(huì)產(chǎn)生一個(gè)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指定)

使用場(chǎng)景:可以將一個(gè)application.properties打包在Jar內(nèi),用來提供一個(gè)合理的默認(rèn)name值;當(dāng)運(yùn)行在生產(chǎn)環(huán)境時(shí),可以在Jar外提供一個(gè)application.properties文件來覆蓋name屬性;對(duì)于一次性的測(cè)試,可以使用特病的命令行開關(guān)啟動(dòng),而不需要重復(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è)置連接超時(shí)時(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超時(shí)時(shí)間
        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);
    }
}
  • 啟動(dòng)緩存,使用@Cacheable注解在需要緩存的接口上即可
@Service
public class ReportService {
    @Cacheable(value = "reportcache", keyGenerator = "wiselyKeyGenerator")
    public ReportBean getReport(Long id, String date, String content, String title) {
        System.out.println("無緩存的時(shí)候調(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)

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


javaadu
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容