由于项目的业务需要,这两天折腾了一下Spring-redis配置,有了前面用Spring托管hibernate的经验,这次可以说是顺风顺水,大概说一下流程。

ubuntu 安装 redis

sudo apt install redis-server

安装后在/etc/redis目录下可以找到redis.conf文件,直接搜索PASSWORD可以找到设置密码的地方,出于安全考虑我设置了一个。默认端口6379通常不用改,之后用ubuntu默认开启服务的方法就可以运行redis。

此后可以用ubuntu的包管理方法启动redis,此处不表。

项目需要加载的库文件

        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-pool2</artifactId>
            <version>2.4.2</version>
        </dependency>
        <dependency>
            <groupId>redis.clients</groupId>
            <artifactId>jedis</artifactId>
            <version>2.9.0</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.data</groupId>
            <artifactId>spring-data-commons</artifactId>
            <version>1.13.3.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.data</groupId>
            <artifactId>spring-data-redis</artifactId>
            <version>1.8.3.RELEASE</version>
        </dependency>

网上的资料通常只有jedis和spring-data-redis,实际上没有另外两个你的项目是跑不起来的。

添加配置

在spring的配置文件中能够添加如下字段,之后我会分开解。

  <bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig">
        <property name="maxIdle" value="300" />
        <property name="maxTotal" value="1024" />
        <property name="maxWaitMillis" value="1000" />
        <property name="testOnBorrow" value="true" />
    </bean>

    <bean id="jedisConnectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory">
        <property name="hostName" value="localhost"/>
        <property name="port" value="6379"/>
        <property name="poolConfig" ref="jedisPoolConfig"/>
        <property name="usePool" value="true"/>
        <property name="password" value="hahaschool"/>
    </bean>

    <bean id="stringRedisSerializer" class="org.springframework.data.redis.serializer.StringRedisSerializer"/>

    <bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate">
        <property name="connectionFactory" ref="jedisConnectionFactory" />
        <property name="keySerializer" ref="stringRedisSerializer"/>
        <property name="hashKeySerializer" ref="stringRedisSerializer"/>
        <property name="enableTransactionSupport" value="true" />
    </bean>
  • jedisPoolConfig是redis的连接池配置,设置了jedis的一些基本信息。
  • jedisConnectionFactory配置了地址,端口号,密码,连接池等信息,类似于hibernate的主配置文件。
  • stringRedisSerializer是配置redis的序列化方法,也可以选择jdbc的序列化方法。
  • redisTemplate和hibernateTemplate类似,是Spring控制redis的方法,也是核心所在,它的参数主要是序列化选项。对于redis而言,其事务比hibernate的事务配起来更方便,直接在这里配置了不需要其他改动。

例子,用redis缓存实现token

TokenDao

@Repository
public class TokenDao {
    private final RedisTemplate<String, String> redisTemplate;
    private final static long validTime=60;

    @Autowired
    public TokenDao(RedisTemplate redisTemplate) {
        this.redisTemplate = redisTemplate;
    }
    
    public void put(String token, String name){
        redisTemplate.boundValueOps(token).set(name,validTime,TimeUnit.MINUTES);
    }

    public String get(String token) {
        return redisTemplate.opsForValue().get(token);
    }

    public void delete(String token){
        redisTemplate.delete(token);
    }
}

TokenService

@Service
public class TokenService {
    private final TokenDao tokenDao;

    @Autowired
    public TokenService(TokenDao tokenDao) {
        this.tokenDao = tokenDao;
    }

    public String generateToken(String accoutNumber){
        String token= UUID.randomUUID().toString().replace("-","");
        tokenDao.put(token,accoutNumber);
        return token;
    }

    public String getAccountNumber(String token){
        return tokenDao.get(token);
    }

    public void delete(String token){
        tokenDao.delete(token);
    }
}

RestHelloController

@RestController
@CrossOrigin
@RequestMapping(value = "api")
public class RestHelloController {
    private final HelloService helloService;
    private final TokenService tokenService;

    @Autowired
    public RestHelloController(HelloService helloService, TokenService tokenService) {
        this.helloService = helloService;
        this.tokenService = tokenService;
    }

    @RequestMapping("token/{name}")
    public String token(@PathVariable String name){
        return tokenService.generateToken(name);
    }
    @RequestMapping("name/{name}/{message}")
    public void add(@PathVariable String name,@PathVariable String message){
        helloService.add(name,message);
    }
    @RequestMapping("{token}")
    public String get(@PathVariable String token){
        return helloService.showMessage(tokenService.getName(token));
    }
}

boundValueOps相对于opsForValue,会有检查token是否被使用的操作,进而更新token的消亡时间。运行好Redis,mysql,tomcat后,在浏览器输入:

http://localhost:8080/api/name/Xiaoming/Good

创建了用户Xiaoming和他的信息。

输入
http://localhost:8080/api/token/Xiaoming

返回一条token,我这边是dad0724ead8a4d7a98564ab316cf37fd

之后输入
http://localhost:8080/api/dad0724ead8a4d7a98564ab316cf37fd

会显示出信息Good。