admin 1 жил өмнө
parent
commit
9bfaf4d867

+ 65 - 0
memcachedSpringBoot/pom.xml

@@ -0,0 +1,65 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+
+    <groupId>org.example</groupId>
+    <artifactId>memcachedSpringBoot</artifactId>
+    <version>1.0-SNAPSHOT</version>
+
+    <properties>
+        <maven.compiler.source>8</maven.compiler.source>
+        <maven.compiler.target>8</maven.compiler.target>
+        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+    </properties>
+    <parent>
+        <groupId>org.springframework.boot</groupId>
+        <artifactId>spring-boot-starter-parent</artifactId>
+        <version>2.2.2.RELEASE</version>
+    </parent>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-web</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-test</artifactId>
+            <scope>test</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>com.alibaba</groupId>
+            <artifactId>fastjson</artifactId>
+            <version>2.0.7</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.projectlombok</groupId>
+            <artifactId>lombok</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>net.spy</groupId>
+            <artifactId>spymemcached</artifactId>
+            <version>2.12.3</version>
+        </dependency>
+
+    </dependencies>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-compiler-plugin</artifactId>
+                <configuration>
+                    <source>1.8</source>
+                    <target>1.8</target>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+</project>

+ 11 - 0
memcachedSpringBoot/src/main/java/org/example/Main.java

@@ -0,0 +1,11 @@
+package org.example;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+public class Main {
+    public static void main(String[] args){
+        SpringApplication.run(Main.class, args);
+    }
+}

+ 31 - 0
memcachedSpringBoot/src/main/java/org/example/MemcacheConfig.java

@@ -0,0 +1,31 @@
+package org.example;
+
+import net.spy.memcached.MemcachedClient;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+import java.io.IOException;
+import java.net.InetSocketAddress;
+
+@Configuration
+public class MemcacheConfig {
+
+    @Value("${memcache.ip}")
+    private String ip;
+
+    @Value("${memcache.port}")
+    private int port;
+
+
+    @Bean
+    public MemcachedClient getClient() {
+        MemcachedClient memcachedClient = null;
+        try {
+            memcachedClient  = new MemcachedClient(new InetSocketAddress(ip, port));
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+        return memcachedClient;
+    }
+}

+ 327 - 0
memcachedSpringBoot/src/main/java/org/example/MemcacheController.java

@@ -0,0 +1,327 @@
+package org.example;
+
+import net.spy.memcached.MemcachedClient;
+import net.spy.memcached.internal.OperationFuture;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import net.spy.memcached.CASResponse;
+import net.spy.memcached.CASValue;
+
+@RestController
+public class MemcacheController {
+
+    @Autowired
+    private MemcachedClient memcachedClient;
+
+
+    @RequestMapping("/getAndset")
+    public void getAndset() {
+
+        //设置缓存   过期时间单位为秒, 0表示永远不过期
+        OperationFuture<Boolean> flag = memcachedClient.set("zhongguo", 5, "beijing");
+
+        Object data;
+        data= memcachedClient.get("zhongguo");
+        System.out.println("第一次取出数据:"+data);  //beijing
+
+        try {
+            //让  key  过期
+            Thread.sleep(5000);
+        } catch (InterruptedException e) {
+            e.printStackTrace();
+        }
+        data = memcachedClient.get("zhongguo");
+        System.out.println("第二次取出数据:"+data); //null
+
+    }
+
+    /**
+     * Memcached add 命令用于将 value(数据值) 存储在指定的 key(键) 中。
+     *
+     * 如果 add 的 key 已经存在,则不会更新数据(过期的 key 会更新),之前的值将仍然保持相同,并且您将获得响应 NOT_STORED。
+     */
+    @RequestMapping("/add")
+    public void add() {
+
+        //设置缓存   过期时间单位为秒, 0表示永远不过期
+        OperationFuture<Boolean> flag = memcachedClient.set("zhongguo", 5, "shanghai");
+
+        System.out.println(flag);
+
+        Object data;
+        data= memcachedClient.get("zhongguo");
+        System.out.println("第一次取出数据:"+data);
+
+        memcachedClient.add("zhongguo",5, "2"); // 进行 Add操作
+
+        data = memcachedClient.get("zhongguo");
+        System.out.println("第二次取出数据:"+data);// 之前的值未过期,新值不生效
+
+        try {
+            //让  key  过期
+            Thread.sleep(5000);
+        } catch (InterruptedException e) {
+            e.printStackTrace();
+        }
+
+        memcachedClient.add("zhongguo",5, "2"); // 再进行 Add操作
+
+        System.out.println("第三次取出数据:"+memcachedClient.get("zhongguo"));  //取出值为2
+
+    }
+
+    /**
+     * replace 命令用于替换已存在的 key(键) 的 value(数据值)。
+     *
+     * 如果 key 不存在,则替换失败,并且您将获得响应 NOT_STORED。
+     */
+    @RequestMapping("/replace")
+    public void replace() {
+
+        //设置缓存   过期时间单位为秒, 0表示永远不过期
+        OperationFuture<Boolean> flag = memcachedClient.set("zhongguo", 5, "shanghai");
+
+        System.out.println(flag);
+
+        Object data;
+        data= memcachedClient.get("zhongguo");
+        System.out.println("第一次取出数据:"+data);
+
+        memcachedClient.replace("zhongguo",5, "2"); // 进行 replace 操作
+
+        data = memcachedClient.get("zhongguo");
+        System.out.println("第二次取出数据:"+data);// 值更新为 2
+
+        try {
+            //让  key  过期
+            Thread.sleep(6000);
+        } catch (InterruptedException e) {
+            e.printStackTrace();
+        }
+
+        memcachedClient.replace("zhongguo",5, "shanghai"); // 再进行 replace 操作
+
+        System.out.println("第三次取出数据:"+memcachedClient.get("zhongguo"));  //key 为空, 取出结果为 null
+
+    }
+
+    /**
+     * append 命令用于向已存在 key(键) 的 value(数据值) 后面追加数据
+     */
+    @RequestMapping("/append")
+    public void append() {
+
+        //设置缓存   过期时间单位为秒, 0表示永远不过期
+        OperationFuture<Boolean> flag = memcachedClient.set("zhongguo", 5, "shanghai");
+
+        System.out.println(flag);
+
+        Object data;
+        data= memcachedClient.get("zhongguo");
+        System.out.println("第一次取出数据:"+data);
+
+        memcachedClient.append("zhongguo","2"); // 进行 append 操作
+
+        data = memcachedClient.get("zhongguo");
+        System.out.println("第二次取出数据:"+data);// 值更新为 shanghai2
+
+        try {
+            //让  key  过期
+            Thread.sleep(6000);
+        } catch (InterruptedException e) {
+            e.printStackTrace();
+        }
+
+        memcachedClient.append("zhongguo","shanghai"); // 再进行 append 操作
+
+        System.out.println("第三次取出数据:"+memcachedClient.get("zhongguo"));  //key 为空, 取出结果为 null
+
+    }
+
+
+    /**
+     * prepend  命令用于向已存在 key(键) 的 value(数据值) 后面追加数据
+     */
+    @RequestMapping("/prepend")
+    public void prepend() {
+
+        //设置缓存   过期时间单位为秒, 0表示永远不过期
+        OperationFuture<Boolean> flag = memcachedClient.set("zhongguo", 5, "shanghai");
+
+        System.out.println(flag);
+
+        Object data;
+        data= memcachedClient.get("zhongguo");
+        System.out.println("第一次取出数据:"+data);
+
+        memcachedClient.prepend("zhongguo","2"); // 进行 prepend 操作
+
+        data = memcachedClient.get("zhongguo");
+        System.out.println("第二次取出数据:"+data);// 值更新为 2shanghai
+
+        try {
+            //让  key  过期
+            Thread.sleep(6000);
+        } catch (InterruptedException e) {
+            e.printStackTrace();
+        }
+
+        memcachedClient.prepend("zhongguo","shanghai"); // 再进行 prepend 操作
+
+        System.out.println("第三次取出数据:"+memcachedClient.get("zhongguo"));  //key 为空, 取出结果为 null
+
+    }
+
+
+    /**
+     * CAS(Check-And-Set 或 Compare-And-Swap) 命令用于执行一个"检查并设置"的操作
+     *
+     * 它仅在当前客户端最后一次取值后,该key 对应的值没有被其他客户端修改的情况下, 才能够将值写入。
+     *
+     * 检查是通过cas_token参数进行的, 这个参数是Memcach指定给已经存在的元素的一个唯一的64位值。
+     */
+    @RequestMapping("/cas")
+    public void cas() {
+
+        //设置缓存   过期时间单位为秒, 0表示永远不过期
+        OperationFuture<Boolean> flag = memcachedClient.set("zhongguo", 5, "shanghai");
+
+        System.out.println(flag);
+
+        Object data;
+        data= memcachedClient.get("zhongguo");
+        System.out.println("第一次取出数据:"+data);
+
+        //通过 gets 获取 CAS token (令牌)
+        CASValue casValue = memcachedClient.gets("zhongguo");
+
+        System.out.println("CAS token --  : " + casValue);  //{CasValue 20/shanghai}
+
+        //使用cas方法来更新数据
+        CASResponse casResponse = memcachedClient.cas("zhongguo",casValue.getCas(),5,"2");
+
+        System.out.println("CAS 响应信息 :"+casResponse);// OK
+
+
+        data = memcachedClient.get("zhongguo");
+        System.out.println("第二次取出数据:"+data);  // 2
+
+
+        try {
+            //让  key  过期
+            Thread.sleep(6000);
+        } catch (InterruptedException e) {
+            e.printStackTrace();
+        }
+
+        //通过 gets 获取 CAS token (令牌)
+        CASValue casValue2 = memcachedClient.gets("zhongguo");
+
+        System.out.println("CAS token --  : " + casValue2);  //null
+
+        //使用cas方法来更新数据
+        CASResponse casResponse2 = memcachedClient.cas("zhongguo",casValue.getCas(),5,"2");
+
+        System.out.println("CAS 响应信息 :"+casResponse2);// NOT_FOUND
+
+        data = memcachedClient.get("zhongguo");
+        System.out.println("第三次取出数据:"+data);  // null
+
+    }
+
+    /**
+     * delete 命令用于删除已存在的 key(键)。
+     */
+    @RequestMapping("/delete")
+    public void delete() {
+
+        //设置缓存   过期时间单位为秒, 0表示永远不过期
+        OperationFuture<Boolean> flag = memcachedClient.set("zhongguo", 5, "shanghai");
+
+        System.out.println(flag);
+
+        Object data;
+        data = memcachedClient.get("zhongguo");
+        System.out.println("第一次取出数据:" + data); //shanghai
+
+        OperationFuture<Boolean> zhongguo = memcachedClient.delete("zhongguo");
+
+        System.out.println(zhongguo.getStatus()); //{OperationStatus success=true:  DELETED}
+
+        data = memcachedClient.get("zhongguo");
+        System.out.println("第二次取出数据:" + data); //null
+
+        //没有 key 的情况下
+        OperationFuture<Boolean> zhongguo2 = memcachedClient.delete("zhongguo");
+
+        System.out.println(zhongguo2.getStatus()); //{OperationStatus success=false:  NOT_FOUND}
+
+    }
+
+    /**
+     * Memcached incr 与 decr 命令用于对已存在的 key(键) 的数字值进行自增或自减操作。
+     *
+     * incr 与 decr 命令操作的数据必须是十进制的32位无符号整数。
+     *
+     * 如果 key 不存在返回 NOT_FOUND,如果键的值不为数字,则返回 CLIENT_ERROR,其他错误返回 ERROR。
+     */
+    @RequestMapping("/incrOrDecr")
+    public void incrOrDecr() {
+
+        //设置缓存   过期时间单位为秒, 0表示永远不过期
+        OperationFuture<Boolean> flag = memcachedClient.set("zhongguo", 5, "1000");
+
+        System.out.println(flag);
+
+        Object data;
+        data = memcachedClient.get("zhongguo");
+        System.out.println("第一次取出数据:" + data); // 1000
+
+        long incr = memcachedClient.incr("zhongguo", 100);
+
+        System.out.println("取出 incr 之后的数据:" + memcachedClient.get("zhongguo")); // 1100
+
+        long decr = memcachedClient.decr("zhongguo", 100);
+
+        System.out.println("取出 decr 之后的数据:" + memcachedClient.get("zhongguo")); // 1000
+
+
+        memcachedClient.append("zhongguo","shanghai");
+
+        System.out.println("取出 append 之后的数据:" + memcachedClient.get("zhongguo")); //  1000shanghai
+
+
+        //ERROR net.spy.memcached.protocol.ascii.MutatorOperationImpl:  Error:  CLIENT_ERROR cannot increment or decrement non-numeric value
+        long incr2 = memcachedClient.incr("zhongguo", 100);
+        System.out.println("取出 incr 之后的数据:" + memcachedClient.get("zhongguo")); //  1000shanghai
+
+
+        //ERROR net.spy.memcached.protocol.ascii.MutatorOperationImpl:  Error:  CLIENT_ERROR cannot increment or decrement non-numeric value
+        long decr2 = memcachedClient.decr("zhongguo", 100);
+        System.out.println("取出 decr 之后的数据:" + memcachedClient.get("zhongguo"));//  1000shanghai
+
+
+        try {
+            //让  key  过期
+            Thread.sleep(6000);
+        } catch (InterruptedException e) {
+            e.printStackTrace();
+        }
+
+        //key 过期后 未报错  但返回 的都是 -1
+
+        long incr3 = memcachedClient.incr("zhongguo", 100);
+
+        System.out.println(incr3); //  -1
+        System.out.println("取出 incr 之后的数据:" + memcachedClient.get("zhongguo")); //  null
+
+
+        long decr3 = memcachedClient.decr("zhongguo", 100);
+
+        System.out.println(decr3); //  -1
+        System.out.println("取出 decr 之后的数据:" + memcachedClient.get("zhongguo"));//  null
+
+    }
+
+}

+ 2 - 0
memcachedSpringBoot/src/main/resources/application.properties

@@ -0,0 +1,2 @@
+memcache.ip=127.0.0.1
+memcache.port=11211

+ 40 - 0
memcachedSpringBoot/src/test/java/MemcachedTest.java

@@ -0,0 +1,40 @@
+import net.spy.memcached.MemcachedClient;
+import org.example.Main;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+
+import java.io.IOException;
+import java.net.InetSocketAddress;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
+
+@SpringBootTest(classes = Main.class)
+public class MemcachedTest {
+
+    @Autowired
+    MemcachedClient memcachedClient;
+    @Test
+    void test() throws IOException, ExecutionException, InterruptedException {
+
+
+        //设置缓存   过期时间单位为秒, 0表示永远不过期
+        Future future = memcachedClient.set("yk", 5, "yukun");
+
+        Object data;
+
+        System.out.println("************* :  "+future.get());//返回状态 true or false
+        data= memcachedClient.get("yk");
+        System.out.println("第一次取出数据:"+data);
+
+        try {
+            Thread.sleep(5000);
+        } catch (InterruptedException e) {
+            e.printStackTrace();
+        }
+        data = memcachedClient.get("yk");
+        System.out.println("第二次取出数据:"+data);
+
+        memcachedClient.shutdown();
+    }
+}