Spring Boot是爲了簡化Spring開發而生,從Spring 3.x開始,Spring社區的發展方向就是弱化xml配置文件而加大註解的戲份。最近召開的SpringOne2GX2015大會上顯示:Spring Boot已是Spring社區中增加最迅速的框架,前三名是:Spring Framework,Spring Boot和Spring Security,這個應該是將來的趨勢。html
我學習Spring Boot,是由於經過cli工具,spring boot開始往flask(python)、express(nodejs)等web框架發展和靠近,而且Spring Boot幾乎不須要寫xml配置文件。感興趣的同窗能夠根據spring boot quick start這篇文章中的例子嘗試下。java
學習新的技術最佳途徑是看官方文檔,如今Spring boot的release版本是1.3.0-RELEASE,相應的參考文檔是Spring Boot Reference Guide(1.3.0-REALEASE),若是有絕對英文比較吃力的同窗,能夠參考中文版Spring Boot參考指南。在前段時間閱讀一篇技術文章,介紹如何閱讀ios技術文檔,我從中也有所收穫,那就是咱們應該重視spring.io上的guides部分——Getting Started Guides,這部分都是一些針對特定問題的demo,值得學習。node
com +- example +- myproject +- Application.java | +- domain | +- Customer.java | +- CustomerRepository.java | +- service | +- CustomerService.java | +- web +- CustomerController.java
如上所示,Spring boot項目的結構劃分爲web->service->domain,其中domain文件夾可類比與業務模型和數據存儲,即xxxBean和Dao層;service層是業務邏輯層,web是控制器。比較特別的是,這種類型的項目有本身的入口,即主類,通常命名爲Application.java。Application.java不只提供入口功能,還提供一些底層服務,例如緩存、項目配置等等。python
本文的例子是取自個人side project之中,日報(report)的查詢,試圖利用Redis做爲緩存,優化查詢效率。ios
Spring Boot容許外化配置,這樣你能夠在不一樣的環境下使用相同的代碼。你可使用properties文件、yaml文件,環境變量和命令行參數來外化配置。使用@Value註解,能夠直接將屬性值注入到你的beans中。
Spring Boot使用一個很是特別的PropertySource來容許對值進行合理的覆蓋,按照優先考慮的順序排位以下:git
1. 命令行參數 2. 來自java:comp/env的JNDI屬性 3. Java系統屬性(System.getProperties()) 4. 操做系統環境變量 5. 只有在random.*裏包含的屬性會產生一個RandomValuePropertySource 6. 在打包的jar外的應用程序配置文件(application.properties,包含YAML和profile變量) 7. 在打包的jar內的應用程序配置文件(application.properties,包含YAML和profile變量) 8. 在@Configuration類上的@PropertySource註解 9. 默認屬性(使用SpringApplication.setDefaultProperties指定)
使用場景:能夠將一個application.properties打包在Jar內,用來提供一個合理的默認name值;當運行在生產環境時,能夠在Jar外提供一個application.properties文件來覆蓋name屬性;對於一次性的測試,可使用特病的命令行開關啓動,而不須要重複打包jar包。web
具體的例子操做過程以下:redis
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
@Configuration @PropertySource(value = "classpath:/redis.properties") @EnableCaching public class CacheConfig extends CachingConfigurerSupport { ...... }
@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; ...... }
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-redis</artifactId> </dependency>
@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); //設置鏈接超時時間 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); //設置key-value超時時間 return cacheManager; } @Bean public RedisTemplate<String, String> redisTemplate(RedisConnectionFactory factory) { StringRedisTemplate template = new StringRedisTemplate(factory); setSerializer(template); //設置序列化工具,這樣ReportBean不須要實現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); } }
@Service public class ReportService { @Cacheable(value = "reportcache", keyGenerator = "wiselyKeyGenerator") public ReportBean getReport(Long id, String date, String content, String title) { System.out.println("無緩存的時候調用這裏---數據庫查詢"); return new ReportBean(id, date, content, title); } }