やってみるよ!
Springは3.1.1.RELEASE、SpringDataRedisは1.0.0.RELEASEを使用。
Webアプリの最低限の構成を作ってpom.xmlに以下を追加。
<dependency> <groupId>org.springframework.data</groupId> <artifactId>spring-data-redis</artifactId> <version>1.0.0.RELEASE</version> </dependency>
これでspring-data-commons-coreとかJedisとかも依存解決されます。
以下によるとコネクタはJedis、JRedis、RJCに対応してるみたいだけど、デフォルトがJedisみたい。
http://www.springsource.org/spring-data/redis(Featuresのところ)
次はアプリから使えるようにするために最低限の設定をします。
<bean id="jedisConnectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory" p:host-name="localhost" p:port="6379"/> <bean id="stringRedisTemplate" class="org.springframework.data.redis.core.StringRedisTemplate" p:connection-factory-ref="jedisConnectionFactory"/> <bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate" p:connection-factory-ref="jedisConnectionFactory"/>
よくある感じの。MongoでいうところのMongoDBFactoryとMongoTemplate的な。
StringRedisTemplateはキーと値の両方がStringのときに使用、それ以外はRedisTemplteを使うってイメージだと思う。多分。きっと。深く読んでない。
これを使って早速しょっぱいアプリを作ります。
とりあえずset/get/delを試したいのでそれを処理するコントローラさんをざっくり作ります。
サービスクラス分けろとか野暮なことはいいっこなしです。
@Controller @Scope("prototype") public class RedisStrController { @Autowired private StringRedisTemplate stringRedisTemplate; // String用のTemplate @RequestMapping(value="/redisstr/get", method=RequestMethod.GET) public String get(@RequestParam(value="key", required=true) String key,Model model) { // キーを指定してredisから値を取得 String result = stringRedisTemplate.opsForValue().get(key); model.addAttribute("result",result); return "redisstr/get_end"; } @RequestMapping(value="/redisstr/set", method=RequestMethod.GET) public String set(@RequestParam(value="key", required=true) String key, @RequestParam(value="value", required=true) String value, Model model) { // キーと値を指定してredisにセット stringRedisTemplate.opsForValue().set(key, value); return "redisstr/set_end"; } @RequestMapping(value="/redisstr/del", method=RequestMethod.GET) public String del(@RequestParam(value="key", required=true) String key,Model model) { // キーを指定してredisから削除 stringRedisTemplate.delete(key); return "redisstr/del_end"; } }
色々省いてますけど、setはkeyとvalueを受け取ってredisにセット、get/delはkeyだけ受け取って処理します。
とりあえずデータを入れないと始まらないのでsetを叩いてみます。
「/redisstr/set?key=testkey&value=hoge」にアクセスしてredisを確認。
redis 127.0.0.1:6379> keys * 1) "testkey" redis 127.0.0.1:6379> get testkey "hoge"
いけている。get/delも正しく動くことが確認できました。
次は適当なクラスをぶちこむためにまたコントローラを作ります。
@Controller @Scope("prototype") public class RedisController { @Autowired private RedisTemplate<String, TestDto> redisTemplate; // String以外用のTemplate @RequestMapping(value="/redis/get", method=RequestMethod.GET) public String get(@RequestParam(value="key", required=true) String key,Model model) { // キーを指定してredisから値を取得 TestDto dto = redisTemplate.opsForValue().get(key); model.addAttribute("dto",dto); return "redis/get_end"; } @RequestMapping(value="/redis/set", method=RequestMethod.GET) public String set( @RequestParam(value="key", required=true) String key, @RequestParam(value="value", required=true) String value, Model model) { TestDto dto = new TestDto(); dto.setKey(key); dto.setValue(value); dto.setCreateDate(new Date()); // キーと値を指定してredisにセット redisTemplate.opsForValue().set(key, dto); return "redis/set_end"; } @RequestMapping(value="/redis/del", method=RequestMethod.GET) public String del( @RequestParam(value="key", required=true) String key, Model model) { // キーを指定してredisから削除 redisTemplate.delete(key); return "redis/del_end"; } }
うむ。
さっきと違うのは使うTemplateと値がString以外ってところです。
Templateは前述のRedisTemplateを使います。
宣言するときにキーと値の型を指定してやる必要があるので、今回はキーにString、値に自作クラスを指定してます。
自作クラスは以下のかんじ。中身は別に何でもよかった。
public class TestDto implements Serializable { private static final long serialVersionUID = 6013601409727347724L; private String key; private String value; private Date createDate; (アクセサ略) }
シリアライズを忘れなければ何でも。
準備が出来たので「/redis/set?key=dtotest1&value=hogehoge」を叩いてredisを確認。
redis 127.0.0.1:6379> get dtotest1 (nil)
!?
えっ。あれ。えっ。
落ち着くんだ…『素数』を数えて落ち着くんだ…。
助けてkeysさん!
redis 127.0.0.1:6379> keys * 1) "\xac\xed\x00\x05t\x00\bdtotest1"
ああ…ああ…。
なんかキーがシリアライズされてるくさい雰囲気です…。
一応取得はできる。
redis 127.0.0.1:6379> get "\xac\xed\x00\x05t\x00\bdtotest1" "\xac\xed\x00\x05sr\x00*com.tm8r.TestDtoSt\x9a\x9e\xe7\x96<\x0c\x02\x00\x03L\x00\ncreateDatet\x00\x10Ljava/util/Date;L\x00\x03keyt\x00\x12Ljava/lang/String;L\x00\x05valueq\x00~\x00\x02xpsr\x00\x0ejava.util.Datehj\x81\x01KYt\x19\x03\x00\x00xpw\b\x00\x00\x016^\xe9\x83\bxt\x00\bdtotest1t\x00\bhogehoge"
同じアプリ使ってやる分には問題ないんですけど、なんか後で困る気がするのでなんとかします。
調べた感じだとTemplateのKeySerializerをいじってやればよさそう。
ちょっくら設定を変更してみます。
<bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate" p:connection-factory-ref="jedisConnectionFactory" p:key-serializer-ref="stringKeySerializer"/> <bean id ="stringKeySerializer" class="org.springframework.data.redis.serializer.StringRedisSerializer"/>
StringRedisSerializerを定義し、RedisTemplateのkeySerializerにセットしてみました。
リトライしてredis確認…!
redis 127.0.0.1:6379> keys * 1) "dtotest1" redis 127.0.0.1:6379> get dtotest1 "\xac\xed\x00\x05sr\x00*com.tm8r.TestDtoSt\x9a\x9e\xe7\x96<\x0c\x02\x00\x03L\x00\ncreateDatet\x00\x10Ljava/util/Date;L\x00\x03keyt\x00\x12Ljava/lang/String;L\x00\x05valueq\x00~\x00\x02xpsr\x00\x0ejava.util.Datehj\x81\x01KYt\x19\x03\x00\x00xpw\b\x00\x00\x016^\xf0LBxt\x00\bdtotest1t\x00\bhogehoge"
ヤター!デキタヨー!
次こそはなんかリストとかセットとかそのへんを。