• 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="${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=''/>
            </div>
            <div >
                密码:<input class="password" type="password" id="password" name="password" value=""/>
            </div>
            <div><input type="button" value="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="/pages/"></property>
            <property name="suffix" value=".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 = "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

  • 相关阅读:
    判断ImageIcon创建成功
    Node中的explorer views的双击事件
    Oracle数据类型
    Sql三种行转列
    数据库迁移
    并发采集同一站点被封的解决方案
    .net获取版本号的三种方法
    List转DataSet
    Orcale自增长主键
    python学习笔记数字和表达式
  • 原文地址:https://www.cnblogs.com/zhengbn/p/4140549.html
Copyright © 2020-2023  润新知