首页 > 代码库 > springMVC整合jedis+redis,以注解形式使用

springMVC整合jedis+redis,以注解形式使用

前两天写过 springMVC+memcached 的整合,我从这个基础上改造一下,把redis和springmvc整合到一起。

和memcached一样,redis也有java专用的客户端,官网推荐使用的是:jedis。

看了一部分资料,大家推荐使用 spring-data-redis (spring在jedis的基础上又包装了一层),但是实际中感觉写起来有点麻烦,不如原生态的jedis好用。

所以我利用spring的构造注入做了一个springmvc整合jedis的例子。

 

先了解下redis吧,这些资料袋都是从网上看到的:

Redis使用c语言编写,面向“键/值”对类型数据的分布式NoSql数据库系统。目前提供五中数据类型    string(字符串)    list(链表)    Hash(哈希)    set(集合)    zset(sorted set 有序集合),有2中编码类型:ziplist,skiplist,当zset中数据较多时,将会被重构为skiplist。    默认端口6379

 redis-server.exe:服务端
 redis-check-dump.exe:本地数据库检查
 redis-check-aof.exe:更新日志检查
 redis-benchmark.exe:性能测试,用以模拟同时由N个客户端发送M个 SETs/GETs 查询.
 redis-cli.exe: 这个是客户端,服务端开启后,客户端就可以输入各种命令测试了

先写一个Test类,测一下redis的基本数据类型和jedis的一些常用方法。以下的测试方法也都是从网上看到的,只不过为了验证是否准确以及jar包版本的问题,我自己亲自敲了一遍。

注意jedis是redis的一个客户端,是个jar包,不要搞混了……

public class Test {    public static void main(String[] args) {//        Jedis js = new Jedis("127.0.0.1", 6379);        //        js.set("key001", "redis001");//        String val = js.get("key001");//        System.out.println(val);//        js.del("key001");        /**************************测试Redis的数据类型**************************/                /**         * list         *///        js.rpush("list1", "aaaaaaaaaaaaaaaaaaaaaa");//        js.rpush("list1", "bbbbbbbbbbbbbbbbbbbbbb");//        js.rpush("list1", "ccccccccccccccccccccc");//        js.rpush("list1", "dddddddddddddd");//        List<String> vals = js.lrange("list1", 0, -1);//        for (int i = 0; i < vals.size(); i++) {//            System.out.println(vals.get(i));//        }                /**         * set 无须唯一         *///        js.sadd("s1", "顺序3");//        js.sadd("s1", "a");//        js.sadd("s1", "b");//        js.sadd("s1", "1");//        js.sadd("s1", "蛤蛤蛤");//        js.sadd("s1", "2");//        js.sadd("s1", "so waht?");//        js.sadd("s1", "%^");//        js.sadd("s1", "顺序1");//        js.sadd("s1", "乱码吗?");//        js.sadd("s1", "顺序2");//        Set<String> s = js.smembers("s1");//        for (String string : s) {//            System.out.println(s);//        }//        js.srem("s1", "蛤蛤蛤");                        /**         * zset(sorted set 有序集合)          * 有2中编码类型:ziplist,skiplist,当zset中数据较多时,将会被重构为skiplist         */    //        js.zadd("zs", 92, "张三1");//        js.zadd("zs", 93, "张三7");//        js.zadd("zs", 94, "张三5");//        js.zadd("zs", 87, "张三9");//        js.zadd("zs", 66, "张三");//        js.zadd("zs", 19, "张三0");//        Set<String> sets = js.zrange("zs", 0, -1);//        for (String string : sets) {//            System.out.println(sets);//        }                        /**         * Hash         *///        Map m = new HashMap();//        m.put("1", "t");//        m.put("2", "ttt");//        m.put("username", "老王");//        m.put("password", "123456");//        m.put("age", "79");//        m.put("sex", "man");//        js.hmset("m", m);    //        List<String> v = js.hmget("m", new String[]{"username","age"});//        List<String> v1 = js.hmget("m", "sex");//        System.out.println(v);//        System.out.println(v1);//        js.hdel("m", "username");//删除map中的某一个键的键值对                /**************************事务控制**************************/                /**         * 事务方式(Transactions)         * 他主要目的是保障,一个client发起的事务中的命令可以连续的执行,而中间不会插入其他client的命令。         *          * 我们调用jedis.watch(…)方法来监控key,如果调用后key值发生变化,则整个事务会执行失败。         * 另外,事务中某个操作失败,并不会回滚其他操作。这一点需要注意。         * 还有,我们可以使用discard()方法来取消事务。         *///        Jedis js1 = new Jedis("127.0.0.1", 6379);//        long s = System.currentTimeMillis();//        Transaction tx = js1.multi();//        for (int i = 0; i < 99999; i++) {//            tx.set("keyttt"+i, "valttt"+i);//        }//        List<Object> res= tx.exec();//        long e = System.currentTimeMillis();//        System.out.println((e-s)/1000.0+"秒");        //System.out.println(res);//        js1.disconnect();        /**************************管道**************************/        /**         * 管道(Pipelining)         * 有时,我们需要采用异步方式,一次发送多个指令,不同步等待其返回结果。         * 这样可以取得非常好的执行效率。这就是管道         *///        Jedis js2 = new Jedis("127.0.0.1", 6379);//        long s = System.currentTimeMillis();//        Pipeline pe = js2.pipelined();//        for (int i = 0; i < 9999; i++) {//            pe.set("keya"+i, "valuea"+i);//        }//        List<Object> l = pe.syncAndReturnAll();//        long e = System.currentTimeMillis();//        System.out.println((e-s)/1000.0+"秒");//        js2.disconnect();                /**************************管道中调用事务**************************/                /**         * 管道中调用事务         * 在用法上看,管道中包含了事务         */        //        Jedis js3 = new Jedis("127.0.0.1", 6379);//        long s = System.currentTimeMillis();//        Pipeline pe = js3.pipelined();//        pe.multi();//        for (int i = 0; i < 9999; i++) {//            pe.set("keybb"+i, "valuebb"+i);//        }//        pe.exec();//        List<Object> l = pe.syncAndReturnAll();//        long e = System.currentTimeMillis();//        System.out.println((e-s)/1000.0+"秒");//        js3.disconnect();                        /**************************分布式直连同步调用**************************/                    /**         * 分布式直连同步调用         * 线程不安全的,不建议在线程池中使用直连         *///        List<JedisShardInfo> shards = Arrays.asList(//                new JedisShardInfo("localhost",6379),//                new JedisShardInfo("localhost",6380));//        ShardedJedis sharding = new ShardedJedis(shards);//        long start = System.currentTimeMillis();//        for (int i = 0; i < 100000; i++) {//            String result = sharding.set("sn" + i, "n" + i);//        }//        long end = System.currentTimeMillis();//        System.out.println("Simple@Sharing SET: " + ((end - start)/1000.0) + " seconds");//        sharding.disconnect();                /**************************分布式直连同步调用**************************/                    /**         * 分布式直连异步调用         * 线程不安全的,不建议在线程池中使用直连         */        //         List<JedisShardInfo> shards = Arrays.asList(//                    new JedisShardInfo("localhost",6379),//                    new JedisShardInfo("localhost",6380));//            ShardedJedis sharding = new ShardedJedis(shards);//            ShardedJedisPipeline pipeline = sharding.pipelined();//            long start = System.currentTimeMillis();//            for (int i = 0; i < 100000; i++) {//                pipeline.set("sp" + i, "p" + i);//            }//            List<Object> results = pipeline.syncAndReturnAll();//            long end = System.currentTimeMillis();//            System.out.println("Pipelined@Sharing SET: " + ((end - start)/1000.0) + " seconds");//            sharding.disconnect();                            /**************************分布式连接池同步调用**************************/                    /**             * 同步方式             *///            List<JedisShardInfo> shards = Arrays.asList(//                    new JedisShardInfo("localhost",6379),//                    new JedisShardInfo("localhost",6380));////            ShardedJedisPool pool = new ShardedJedisPool(new JedisPoolConfig(), shards);////            ShardedJedis one = pool.getResource();////            long start = System.currentTimeMillis();//            for (int i = 0; i < 100000; i++) {//                String result = one.set("spn" + i, "n" + i);//            }//            long end = System.currentTimeMillis();//            pool.returnResource(one);//            System.out.println("Simple@Pool SET: " + ((end - start)/1000.0) + " seconds");////            pool.destroy();        //                /**************************分布式连接池异步调用**************************/                /**         * 异步方式         */        //         List<JedisShardInfo> shards = Arrays.asList(//                    new JedisShardInfo("localhost",6379),//                    new JedisShardInfo("localhost",6380));////        ShardedJedisPool pool = new ShardedJedisPool(new JedisPoolConfig(), shards);////        ShardedJedis one = pool.getResource();////        ShardedJedisPipeline pipeline = one.pipelined();////        long start = System.currentTimeMillis();//        for (int i = 0; i < 100000; i++) {//            pipeline.set("sppn" + i, "n" + i);//        }//        List<Object> results = pipeline.syncAndReturnAll();//        long end = System.currentTimeMillis();//        pool.returnResource(one);//        System.out.println("Pipelined@Pool SET: " + ((end - start)/1000.0) + " seconds");//        pool.destroy();/**************************其他**************************/            /**         * 清空所有         *///        js.flushAll();                /**         * 销毁链接         *///        js.disconnect();}
View Code

 

开始贴代码了,springMVC整合jedis

web.xml

<?xml version="1.0" encoding="UTF-8"?><web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5">  <display-name>SpringMVC-Redis</display-name>  <!-- 引入 spring -->  <listener>      <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>  </listener>   <context-param>      <param-name>contextConfigLocation</param-name>      <param-value>classpath*:/applicationContext*.xml</param-value>  </context-param>    <!-- 引入 springMVC -->  <servlet>      <servlet-name>springMVC</servlet-name>      <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>      <init-param>          <param-name>contextConfigLocation</param-name>          <param-value>classpath*:/spring-servlet-config.xml</param-value>      </init-param>  </servlet>    <servlet-mapping>      <servlet-name>springMVC</servlet-name>      <url-pattern>/</url-pattern>  </servlet-mapping>    <!-- 编码 UTF-8 -->  <filter>      <filter-name>SpringMVC-Redis-Encoding</filter-name>      <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>      <init-param>          <param-name>encoding</param-name>          <param-value>UTF-8</param-value>      </init-param>      <init-param>      <param-name>forceEncoding</param-name>      <param-value>true</param-value>      </init-param>  </filter>  <filter-mapping>      <filter-name>SpringMVC-Redis-Encoding</filter-name>      <url-pattern>/*</url-pattern>  </filter-mapping>  </web-app>
View Code

 

index.jsp

<%@ page language="java" contentType="text/html; charset=utf-8"    pageEncoding="utf-8"%><!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"><html><head><script type="text/javascript" src="http://www.mamicode.com/${pageContext.request.contextPath }/js/jquery/jquery-1.8.0.min.js"></script><meta http-equiv="Content-Type" content="text/html; charset=utf-8"><title>index 2</title></head><body>    <div><font color="red" size="10px">${returnMsg}</font></div>    <form action="${pageContext.request.contextPath }/TestRequest/test" method="post" name="loginForm" id="loginForm">        <div>            用户名:<input class="username" type="text" id="username" name="username"  value=http://www.mamicode.com/‘‘/>"color: #000000;">            密码:<input class="password" type="password" id="password" name="password" value=""/>        </div>        <div><input type="button" value="http://www.mamicode.com/submit" onclick="login()" /></div>    </form> <script type="text/javascript">        function login(){        var username = $("#username").val();        var password = $("#password").val();        $("#loginForm").submit();    }    document.onkeydown=function(event){         e = event ? event :(window.event ? window.event : null);         if(e.keyCode==13){             login();        }     }     </script></body></html>
View Code

 

spring-servlet-config.xml

<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans"      xmlns:mvc="http://www.springframework.org/schema/mvc"      xmlns:context="http://www.springframework.org/schema/context"      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"      xsi:schemaLocation="http://www.springframework.org/schema/beans      http://www.springframework.org/schema/beans/spring-beans-3.1.xsd      http://www.springframework.org/schema/context       http://www.springframework.org/schema/context/spring-context-3.1.xsd      http://www.springframework.org/schema/mvc      http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd">          <!-- 使用@Controllers前配置 -->    <mvc:annotation-driven />                    <!-- 容器加载时 自动扫描所有注解 -->    <context:component-scan base-package="com.test" use-default-filters="false">        <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller" />        <context:include-filter type="annotation" expression="org.springframework.stereotype.Service" />        <context:include-filter type="annotation" expression="org.springframework.stereotype.Repository" />        <context:include-filter type="annotation" expression="org.springframework.stereotype.Component" />    </context:component-scan>               <!-- 配置静态资源  -->        <mvc:resources mapping="/js/**" location="/js/" />      <mvc:resources mapping="/image/**" location="/image/" />     <mvc:resources mapping="/css/**" location="/css/" />               <!-- 使用jsp作为视图 -->    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">        <property name="viewClass">            <value>org.springframework.web.servlet.view.JstlView</value>        </property>        <!-- 目标路径返回到pages下 使用jsp作为视图 -->        <property name="prefix" value="http://www.mamicode.com/pages/"></property>        <property name="suffix" value="http://www.mamicode.com/.jsp"></property>    </bean>            <!-- 异常处理 -->    <bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">            <property name="exceptionMappings">                <props>                    <prop key="org.apache.shiro.authz.UnauthorizedException">error/403</prop>                </props>            </property>        </bean>    </beans>
View Code

 

先把这些贴上来是因为这些文件内容都和上篇博文”springMVC+memcached “的一模一样

 

applicationContext.xml

利用spring的构造注入,把集群参数传入RedisInitBean中,并且在项目启动的时候加载RedisInitBean的有参构造方法

<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans"    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"    xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"    xsi:schemaLocation="http://www.springframework.org/schema/beans       http://www.springframework.org/schema/beans/spring-beans-3.1.xsd      http://www.springframework.org/schema/context       http://www.springframework.org/schema/context/spring-context-3.1.xsd      http://www.springframework.org/schema/aop       http://www.springframework.org/schema/aop/spring-aop-3.1.xsd      http://www.springframework.org/schema/tx       http://www.springframework.org/schema/tx/spring-tx-3.1.xsd">        <bean id="RedisInitBean" class="com.test.test.RedisInitBean" >        <!-- IP:Port -->        <constructor-arg index="0" type="List">            <list>                <value>127.0.0.1:6379</value>                <value>192.168.3.27:6380</value>            </list>        </constructor-arg>            <!-- maxWaitMillis -->        <constructor-arg index="1" type="long">            <value>1000</value>        </constructor-arg>            <!-- MaxIdle -->            <constructor-arg index="2" type="int">            <value>200</value>        </constructor-arg>            <!-- testOnBorrow -->        <constructor-arg index="3" type="Boolean">            <value>true</value>        </constructor-arg>            </bean>    </beans>
View Code

 

RedisInitBean.java

这里面要说一下,使用的是 分布式连接池 异步调用!

package com.test.test;import java.util.Arrays;import java.util.List;import redis.clients.jedis.JedisPoolConfig;import redis.clients.jedis.JedisShardInfo;import redis.clients.jedis.ShardedJedis;import redis.clients.jedis.ShardedJedisPool;public class RedisInitBean {        private List Host;    private long maxWaitMillis;    private int MaxIdle;    private Boolean testOnBorrow;    private static List<JedisShardInfo> shards ;    private static ShardedJedisPool pool;    private static ShardedJedis jedis;        public RedisInitBean(List host, long maxWaitMillis, int maxIdle,            Boolean testOnBorrow) {        super();        Host = host;        this.maxWaitMillis = maxWaitMillis;        MaxIdle = maxIdle;        this.testOnBorrow = testOnBorrow;        if(host.size()!=0){            for (int i = 0; i < host.size(); i++) {                        String h[] = ((String) host.get(i)).split(":");                     shards = Arrays.asList(new JedisShardInfo(h[0].trim(),Integer.parseInt(h[1].trim())));                System.out.println(shards);            }        }else{            System.out.println("请检查Redis配置,host项为必填项!格式[IP:PORT]");        }        pool = new ShardedJedisPool(new JedisPoolConfig(), shards);        jedis = pool.getResource();        }        public synchronized ShardedJedis getSingletonInstance(){        return jedis;    }        public synchronized static void returnResource(){        pool.returnResource(jedis);    }        public synchronized static void destroy(){        pool.destroy();    }    }
View Code

 

TestRequest.java

刚才我们写的index.jsp中,提交了表单后浏览器会发起请求,spring拦截请求后会找到注解匹配的类中的方法,TestRequest就是了。

package com.test.web;import java.util.List;import javax.servlet.http.HttpSession;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Controller;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RequestParam;import org.springframework.web.servlet.ModelAndView;import redis.clients.jedis.ShardedJedis;import redis.clients.jedis.ShardedJedisPipeline;import com.test.test.RedisInitBean;@Controller@RequestMapping("/TestRequest")public class TestRequest {    @Autowired    private RedisInitBean rib;        @RequestMapping("/test")    public ModelAndView test(@RequestParam(value = "http://www.mamicode.com/username") final String userid,            @RequestParam(value = "password") final String passwd, HttpSession session){                ModelAndView m = new ModelAndView();        m.setViewName("../index");            ShardedJedis jedis = rib.getSingletonInstance();        ShardedJedisPipeline pipeline = jedis.pipelined();        long start = System.currentTimeMillis();        for (int i = 0; i < 99999; i++) {            pipeline.set("zhenbn" + i, "n" + i);              }        List<Object> results = pipeline.syncAndReturnAll();        long end = System.currentTimeMillis();        rib.returnResource();        rib.destroy();        System.out.println("分布式连接池异步调用耗时: " + ((end - start)/1000.0) + " 秒");        try {            Thread.sleep(5000);//睡5秒,然后打印jedis返回的结果        } catch (InterruptedException e) {            e.printStackTrace();        }        System.out.println("返回结果:"+results);        m.addObject("returnMsg","么么哒!");            return m;    }}
View Code

 

存完之后,我们可以取一下试试,看看到底有没有存进去。

看,取到了吧~

使用jedis的时候要注意配合commons-pool2.jar使用,否则会报错的。

原因是 JedisPoolConfig extends GenericObjectPoolConfig,

而GenericObjectPoolConfig则是:

BaseObjectPoolConfig则是:

 

jar包下载:http://pan.baidu.com/s/1jGBVJds

springMVC整合jedis+redis,以注解形式使用