在搭建基于IDEA的springboot+Redis环境时,深入了解springboot框架的相关机制,了解何时用配置文件,何时利用注解,尽可能清晰、完备的总结相关核心问题。
话不多少,进入主题。
1、搭建springboot+redis的方式有两种,它们分别如下:
方式一:基于RedisTemplate类 ,redisTemplate是springdate提供的管理redis的工具,springboot可以直接注入。
需要安装依赖:
<!-- springboot整合redis --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency>
方式二:基于jedis ,Jedis是Redis官方推荐的面向Java的操作Redis的客户端,jedis不需要注入直接调用就可以,如果想注入到spring中的话,需要创建jedis配置文件,配置文件的作用是在项目启动的时候将jedis注入,接着我们就可以在其他类中获取到JedisPool类的信息。
需要安装的依赖:
<!-- redis --> <dependency> <groupId>redis.clients</groupId> <artifactId>jedis</artifactId> </dependency>
本项目采用的方式是基于方法二,即利于jedis,通过创建jedis配置文件的方式,注入jedisPool类信息。
2、项目架构如下所示:
3、从项目正常启动开始说明各个文件的作用以及相关配置说明
a》pom.xml内容 主要是添加redis jar
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!-- redis --> <dependency> <groupId>redis.clients</groupId> <artifactId>jedis</artifactId> </dependency> <!-- Log4J --> <!-- https://mvnrepository.com/artifact/log4j/log4j --> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.17</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies>
b》本项目还是采用的springboot的默认配置文件--application.properties,配置文件里面主要配置的是tomcat的端口(默认是8080,本项目改成9999,如果tomcat的端口默认是8080,就不需要增加server.port的配置了),以及redis的相关配置。
注意:springboot的版本不同,相应redis的配置也不同。redis的pool属性在springboot版本1.4后,该属性就被封装到jedis中了。本项目springboot的版本是2.0.4,因此配置如下:
server.port=9999 #redis spring.redis.hostName=132.232.28.164 spring.redis.port=6379 #springboot版本为2.0.2RELEASE中的RedisProperties配置文件类,从图中可知pool属性则被封装到了内部静态类Jedis和Lettuce中去了 spring.redis.jedis.pool.max-active=8 # 连接池最大阻塞等待时间(使用负值表示没有限制) spring.redis.jedis.pool.max-wait=-1 # 连接池中的最大空闲连接 spring.redis.jedis.pool.max-idle=8 # 连接池中的最小空闲连接 spring.redis.jedis.pool.min-idle=0 # 连接超时时间(毫秒) spring.redis.timeout=0
c》jedis的配置类config-->RedisConfig.java
正面最开始介绍的,jedis不需要注入直接调用就可以,如果想注入到spring中的话,需要创建jedis配置文件,配置文件的作用是在项目启动的时候将jedis注入,接着我们就可以在其他类中获取到JedisPool类的信息。
RedisConfig.java内容如下:
package com.xz.spring_redis.config; import org.apache.log4j.Logger; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.PropertySource; import org.springframework.stereotype.Component; import redis.clients.jedis.JedisPool; import redis.clients.jedis.JedisPoolConfig; /** * * @author vic * @desc redis config bean * */ @Component//spring boot1.5以上版本@ConfigurationProperties取消location注解后的替代方案 cannot resolve method location 与@EnableConfigurationProperties是替代关系 //没有使用@Component或@Confinguration,因此此对象不会注册到Spring容器中,需要@EnableConfigurationProperties @PropertySource("classpath:application.properties")//使用@PropertySource来指定自定义的资源目录 @ConfigurationProperties(prefix = "spring.redis") //读取application.properties文件中以“spring.redis”开头的变量值。 public class RedisConfig { private static Logger logger = Logger.getLogger(RedisConfig.class); private String hostName; private int port; //private String password; private int timeout; //@Bean //此处注入JedisPoolConfig对象没有意义,不需要 public JedisPoolConfig getRedisConfig(){ JedisPoolConfig config = new JedisPoolConfig(); return config; } @Bean//@Bean注解将一个配置类的方法的返回值定义为一个bean,注册到spring里面 public JedisPool getJedisPool(){ JedisPoolConfig config = getRedisConfig(); JedisPool pool = new JedisPool(config,hostName,port); logger.info("init JredisPool ..."); return pool; } public String getHostName() { return hostName; } public void setHostName(String hostName) { this.hostName = hostName; } public int getPort() { return port; } public void setPort(int port) { this.port = port; } public int getTimeout() { return timeout; } public void setTimeout(int timeout) { this.timeout = timeout; } }
首先理解
1、这个配置类的目的就是往spring里面注册JedisPool实例,方便其他地方Autowired JedisPool对象;
2、配置类中几个注解的意思:
@ConfigurationProperties:
1、@ConfigurationProperties(prefix = "spring.redis") //读取application.properties文件中以“spring.redis”开头的变量值。
2、@ConfigurationProperties和@value都是将外部属性注入到对象
3、@ConfigurationProperties很方便使用。 比用@value注解好吗? 在特定的方案中是的,这只是一个选择问题
@PropertySource:
@PropertySource("classpath:application.properties")//使用@PropertySource来指定自定义的资源目录
@Component注解意思:
将类定义为一个bean的注解。比如 @Component,@Service,@Controller,@Repository
@EnableConfigurationProperties:
1、如果没有 @Component,@Service,@Controller,@Repository这几个注解,则可以通过@EnableConfigurationProperties,来定义为bean 。
2、@EnableConfigurationProperties //开启属性注入,有此注解就可以通过@autowired注入, 是配合@ConfigurationProperties使用的。如果没有@EnableConfigurationProperties,则使用@ConfigurationProperties注解的class上面还需要添加@Component(@Component的包装注解,譬如@Configuration、@Service也可以。但本质还是注解@Component)。
3、@EnableAutoConfiguration在Spring boot中是启动自动配置的(Auto-configuration tries to be as intelligent as possible and will back-away as you define more of your own configuration.)。
redis配置类中目的都是通过@ConfigurationProperties使用外部配置填充Bean属性的几种方法,即通过获取application.properties里面的变量值来填充配置类中的Bean属性。
具体有如下几种方式:
方式1 : @ConfigurationProperties + @Component 注解到bean定义类上
方式2 : @ConfigurationProperties + @Bean注解在配置类的bean定义方法上
方式3 : @ConfigurationProperties注解到普通类然后通过@EnableConfigurationProperties定义为bean
资料来源:https://blog.csdn.net/andy_zhang2007/article/details/78761651
重点讲解下方式二,因为本项目用的方式就是这种,具体讲解如下:
@Component :说明该类是bean
@PropertySource("classpath:application.properties"):指定springboot配置文件的路径
@ConfigurationProperties(prefix = "spring.redis") :从springboot默认配置文件(application.properties)文件中读取变量值,然后赋值给hostname,port,timeout三个变量(当然可以读取更多变量)
//@Bean //此处注入JedisPoolConfig对象没有意义,不需要 public JedisPoolConfig getRedisConfig(){ JedisPoolConfig config = new JedisPoolConfig(); return config; } @Bean//@Bean注解将一个配置类的方法的返回值定义为一个bean,注册到spring里面 public JedisPool getJedisPool(){ JedisPoolConfig config = getRedisConfig(); JedisPool pool = new JedisPool(config,hostName,port); logger.info("init JredisPool ..."); return pool; }
@bean注解放置在配置类中方法面前,就是说明这个方法返回的对象定义为一个bean,注册到spring 里面,这样做的好处是避免二次加载application.xml文件。(资料:https://www.cnblogs.com/s648667069/p/6489557.html,很重要!!!)例如getJedisPool方法返回的是一个jedispool对象,注册为bean,后面service层里面可以直接
@Autowired
private JedisPool jedisPool;
但是getRedisConfig方法就没必要加上@bean注解,因为后面不需要自动注入这个对象。
d》service层 --->RedisService.java和RedisServiceImpl.java
RedisService.java:接口类,定义redis的一些方法
package com.xz.spring_redis.service; import redis.clients.jedis.Jedis; public interface RedisService { public Jedis getResource(); public void returnResource(Jedis jedis); public void set(String key, String value); public String get(String key); }
RedisServiceImpl.java:实现类,实现redis的一些方法
package com.xz.spring_redis.service; import org.apache.log4j.Logger; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import redis.clients.jedis.Jedis; import redis.clients.jedis.JedisPool; /** * * @desc resdis service * */ @Service public class RedisServiceImpl implements RedisService { private static Logger logger = Logger.getLogger(RedisServiceImpl.class); @Autowired private JedisPool jedisPool; //jedisPool不属于springboot框架支持的redis类,所以需要自行注入到spring中。通过配置类RedisConfig类注入的 @Override public Jedis getResource() { return jedisPool.getResource(); } @SuppressWarnings("deprecation") @Override public void returnResource(Jedis jedis) { if(jedis != null){ jedisPool.returnResourceObject(jedis); } } @Override public void set(String key, String value) { Jedis jedis=null; try{ jedis = getResource(); jedis.set(key, value); logger.info("Redis set success - " + key + ", value:" + value); } catch (Exception e) { e.printStackTrace(); logger.error("Redis set error: "+ e.getMessage() +" - " + key + ", value:" + value); }finally{ returnResource(jedis); } } @Override public String get(String key) { String result = null; Jedis jedis=null; try{ jedis = getResource(); result = jedis.get(key); logger.info("Redis get success - " + key + ", value:" + result); } catch (Exception e) { e.printStackTrace(); logger.error("Redis set error: "+ e.getMessage() +" - " + key + ", value:" + result); }finally{ returnResource(jedis); } return result; } }
e》controller--》DemoController.java,能Autowired RedisService的原因是该类上加入了@service注解,表示为bean
package com.xz.spring_redis.controller; import com.xz.spring_redis.model.ResponseModal; import com.xz.spring_redis.service.RedisService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; @RestController public class DemoController { @Autowired private RedisService redisService; @RequestMapping("/redis/set") public ResponseModal redisSet(@RequestParam("value")String value){ redisService.set("name", value); return new ResponseModal(200, true, "success", null); } @RequestMapping("/redis/get") public ResponseModal redisGet(){ String name = redisService.get("name"); return new ResponseModal(200, true,"success",name); } }
f》model 都是与视图相关的数据,定义消息返回格式
Model.java
package com.xz.spring_redis.model; public class Modal { public Modal() { super(); } public Modal(int code, boolean success, String message) { super(); this.code = code; this.success = success; this.message = message; } private int code; private boolean success; private String message; public int getCode() { return code; } public void setCode(int code) { this.code = code; } public boolean isSuccess() { return success; } public void setSuccess(boolean success) { this.success = success; } public String getMessage() { return message; } public void setMessage(String message) { this.message = message; } }
ResponseModal.java
package com.xz.spring_redis.model; import java.io.Serializable; public class ResponseModal extends Modal implements Serializable{ private static final long serialVersionUID = 1L; public ResponseModal(){ super(); } public ResponseModal(int code,boolean success,String message){ super(code,success,message); } public ResponseModal(int code,boolean success,String message,Object obj){ super(code,success,message); this.response = obj; } private Object response; public Object getResponse() { return response; } public void setResponse(Object response) { this.response = response; } }
g》启动类 没有进行任何修改(因为service层,controller层里面都添加了@service和@controller注解,所以不需要添加@EnableConfigurationProperties,另外因为不涉及到dao层或mapper层的操作,所以没有用到@MapperScanner注解扫描mapper包)
package com.xz.spring_redis; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class SpringRedisApplication { public static void main(String[] args) { SpringApplication.run(SpringRedisApplication.class, args); } }
4、至此项目要点讲解完毕。总结一下:
1)关于redis的maven配置问题,有两种方式:
方式一:基于RedisTemplate类 ,redisTemplate是springdate提供的管理redis的工具,springboot可以直接注入。
方式二:基于jedis ,Jedis是Redis官方推荐的面向Java的操作Redis的客户端,jedis不需要注入直接调用就可以,如果想注入到spring中的话,需要创建jedis配置文件,配置文件的作用是在项目启动的时候将jedis注入,接着我们就可以在其他类中获取到JedisPool类的信息。
(2)application.properties配置中,springboot的版本不同,相应redis的配置也不同。redis的pool属性在springboot版本1.4后,该属性就被封装到jedis中了。
(3)几种注解的意思
@ConfigurationProperties:
1、@ConfigurationProperties(prefix = "spring.redis") //读取application.properties文件中以“spring.redis”开头的变量值。 2、@ConfigurationProperties和@value都是将外部属性注入到对象
3、@ConfigurationProperties很方便使用。 比用@value注解好吗? 在特定的方案中是的,这只是一个选择问题
@PropertySource:
@PropertySource("classpath:application.properties")//使用@PropertySource来指定自定义的资源目录
@Component注解意思:
将类定义为一个bean的注解。比如 @Component,@Service,@Controller,@Repository
@EnableConfigurationProperties:
1、如果没有 @Component,@Service,@Controller,@Repository这几个注解,则可以通过@EnableConfigurationProperties,来定义为bean 。
2、@EnableConfigurationProperties //开启属性注入,有此注解就可以通过@autowired注入, 是配合@ConfigurationProperties使用的。如果没有@EnableConfigurationProperties,则使用@ConfigurationProperties注解的class上面还需要添加@Component(@Component的包装注解,譬如@Configuration、@Service也可以。但本质还是注解@Component)。
3、@EnableAutoConfiguration在Spring boot中是启动自动配置的(Auto-configuration tries to be as intelligent as possible and will back-away as you define more of your own configuration.)。
(4)配置类中@bean放在方法面前的作用
就是说明这个方法返回的对象定义为一个bean,注册到spring 里面,这样做的好处是避免二次加载application.xml文件。
(资料:https://www.cnblogs.com/s648667069/p/6489557.html,很重要!!!)
例如getJedisPool方法返回的是一个jedispool对象,注册为bean,后面service层里面可以直接。