{"id":1965,"date":"2023-04-01T10:29:38","date_gmt":"2023-04-01T02:29:38","guid":{"rendered":"https:\/\/www.appblog.cn\/?p=1965"},"modified":"2023-04-22T08:34:58","modified_gmt":"2023-04-22T00:34:58","slug":"spring-boot-spring-cloud-implement-redisson-distributed-locks","status":"publish","type":"post","link":"https:\/\/www.appblog.cn\/index.php\/2023\/04\/01\/spring-boot-spring-cloud-implement-redisson-distributed-locks\/","title":{"rendered":"Spring Boot &#038; Spring Cloud \u5b9e\u73b0 Redisson \u5206\u5e03\u5f0f\u9501"},"content":{"rendered":"<h2>Spring Boot \u63a5\u5165 redisson \u5206\u5e03\u5f0f\u9501<\/h2>\n<h3>\u4e3a\u4ec0\u4e48\u8981\u4f7f\u7528\u5206\u5e03\u5f0f\u9501?<\/h3>\n<p>\u5728\u5206\u5e03\u5f0f\u573a\u666f\u4e0b\u4e3a\u4e86\u4fdd\u8bc1\u6570\u636e\u6700\u7ec8\u4e00\u81f4\u6027\u3002\u5728\u5355\u8fdb\u7a0b\u7684\u7cfb\u7edf\u4e2d\uff0c\u5b58\u5728\u591a\u4e2a\u7ebf\u7a0b\u53ef\u4ee5\u540c\u65f6\u6539\u53d8\u67d0\u4e2a\u53d8\u91cf\uff08\u53ef\u53d8\u5171\u4eab\u53d8\u91cf\uff09\u65f6\uff0c\u5c31\u9700\u8981\u5bf9\u53d8\u91cf\u6216\u4ee3\u7801\u5757\u505a\u540c\u6b65(lock\u2014synchronized)\uff0c\u4f7f\u5176\u5728\u4fee\u6539\u8fd9\u79cd\u53d8\u91cf\u65f6\u80fd\u591f\u7ebf\u6027\u6267\u884c\u6d88\u9664\u5e76\u53d1\u4fee\u6539\u53d8\u91cf\u3002\u4f46\u5206\u5e03\u5f0f\u7cfb\u7edf\u662f\u591a\u90e8\u7f72\u3001\u591a\u8fdb\u7a0b\u7684\uff0c\u5f00\u53d1\u8bed\u8a00\u63d0\u4f9b\u7684\u5e76\u53d1\u5904\u7406API\u5728\u6b64\u573a\u666f\u4e0b\u5c31\u65e0\u80fd\u4e3a\u529b\u4e86\u3002<\/p>\n<p><!-- more --><\/p>\n<h3>\u5206\u5e03\u5f0f\u9501\u7684\u4f7f\u7528\u573a\u666f<\/h3>\n<p>\u7535\u5546\u7f51\u7ad9\u7528\u4e0b\u5355\u64cd\u4f5c\u65f6\u9700\u8981\u4f7f\u7528\uff0c\u79d2\u6740\u6d3b\u52a8\u66f4\u662f\u5982\u6b64\uff0c\u5426\u5219\u4f1a\u51fa\u73b0\u8d85\u5356\uff08\u5e93\u5b58100\uff0c\u79d2\u6740\u6d3b\u52a8\u65f6\u5e93\u5b58\u53d8\u8d1f\u6570\u4e86\uff09\u73b0\u8c61<\/p>\n<h3>\u5206\u5e03\u5f0f\u9501\u7684\u5b9e\u73b0\u65b9\u5f0f<\/h3>\n<p>\u5927\u6982\u6709\u4e09\u79cd\uff1a1.\u57fa\u4e8e\u5173\u7cfb\u578b\u6570\u636e\u5e93\uff0c2.\u57fa\u4e8e\u7f13\u5b58\uff0c3.\u57fa\u4e8ezookeeper<br \/>\n\u5927\u90e8\u5206\u7f51\u7ad9\u4f7f\u7528\u7684\u662f\u57fa\u4e8e\u7f13\u5b58\u7684\uff0c\u6709\u66f4\u597d\u7684\u6027\u80fd\uff0c\u800c\u7f13\u5b58\u4e00\u822c\u662f\u4ee5\u96c6\u7fa4\u65b9\u5f0f\u90e8\u7f72\uff0c\u4fdd\u8bc1\u4e86\u9ad8\u53ef\u7528\u6027<\/p>\n<h3>\u57fa\u4e8e\u7f13\u5b58redis\uff0c\u4f7f\u7528\u5f00\u6e90 redisson \u5b9e\u73b0\u5206\u5e03\u5f0f\u9501<\/h3>\n<p>redisson: <a target=\"_blank\" rel=\"noopener\" href=\"https:\/\/github.com\/redisson\/redisson\">https:\/\/github.com\/redisson\/redisson<\/a><\/p>\n<p>\uff081\uff09\u65b0\u5efaSpring Boot\u9879\u76ee\uff0c\u5f15\u5165\u4f9d\u8d56\uff1aredisson\u4f9d\u8d56 netty\u3001jackson-core\u3001jackson-databind<\/p>\n<pre><code class=\"language-xml\">&lt;dependency&gt;\n    &lt;groupId&gt;org.springframework.boot&lt;\/groupId&gt;\n    &lt;artifactId&gt;spring-boot-starter-data-redis&lt;\/artifactId&gt;\n&lt;\/dependency&gt;\n&lt;!--start redis distributed lock--&gt;\n&lt;!-- https:\/\/mvnrepository.com\/artifact\/org.redisson\/redisson --&gt;\n&lt;dependency&gt;\n    &lt;groupId&gt;org.redisson&lt;\/groupId&gt;\n    &lt;artifactId&gt;redisson&lt;\/artifactId&gt;\n    &lt;version&gt;3.6.5&lt;\/version&gt;\n&lt;\/dependency&gt;\n&lt;dependency&gt;\n    &lt;groupId&gt;io.netty&lt;\/groupId&gt;\n    &lt;artifactId&gt;netty-all&lt;\/artifactId&gt;\n    &lt;version&gt;4.1.25.Final&lt;\/version&gt;\n&lt;\/dependency&gt;\n&lt;dependency&gt;\n    &lt;groupId&gt;com.fasterxml.jackson.core&lt;\/groupId&gt;\n    &lt;artifactId&gt;jackson-core&lt;\/artifactId&gt;\n    &lt;version&gt;2.9.0&lt;\/version&gt;\n&lt;\/dependency&gt;\n&lt;dependency&gt;\n    &lt;groupId&gt;com.fasterxml.jackson.core&lt;\/groupId&gt;\n    &lt;artifactId&gt;jackson-databind&lt;\/artifactId&gt;\n    &lt;version&gt;2.9.0&lt;\/version&gt;\n&lt;\/dependency&gt;\n&lt;!--end redis distributed lock--&gt;<\/code><\/pre>\n<p>\uff082\uff09\u5728\u542f\u52a8\u7c7b\u4e2d\u6ce8\u5165 redisson \u7684bean\uff0c\u53ef\u4ee5\u5728\u914d\u7f6e\u6587\u4ef6\u4e2d\u6dfb\u52a0redis\u7684\u8fde\u63a5\u5730\u5740\u3001\u53c2\u6570\uff0c\u7136\u540e\u5728\u4ee3\u7801\u4e2d\u5f15\u5165\u914d\u7f6e\u6587\u4ef6<\/p>\n<pre><code class=\"language-java\">@SpringBootApplication\npublic class RedissonApplication {\n\n    public static void main(String[] args) {\n        SpringApplication.run(RedissonApplication.class, args);\n    }\n\n    @Bean\n    Redisson redissonSentinel() {\n        \/\/\u652f\u6301\u5355\u673a\uff0c\u4e3b\u4ece\uff0c\u54e8\u5175\uff0c\u96c6\u7fa4\u7b49\u6a21\u5f0f\n        \/\/\u6b64\u4e3a\u54e8\u5175\u6a21\u5f0f\n        Config config = new Config();\n        config.useSentinelServers()\n                .setMasterName(&quot;mymaster&quot;)\n                .addSentinelAddress(&quot;redis:\/\/192.168.1.1:26379&quot;)\n                .setPassword(&quot;123456&quot;);\n        return (Redisson) Redisson.create(config);\n    }\n}<\/code><\/pre>\n<p>\uff083\uff09\u5230\u6b64\uff0c\u5c31\u5b8c\u6210\u4e86\uff0c\u662f\u4e0d\u662f\u5f88\u7b80\u5355\u3002\u6a21\u62df\u79d2\u6740\u573a\u666f\uff0c\u6709\u4e00\u4e2a\u5546\u54c1aaa\uff0c\u5e93\u5b58100\u4e2a\uff0c2\u4e2a\u5e76\u53d1\u8bf7\u6c42110\u6b21\uff0c\u6bcf\u8bf7\u6c42\u4e00\u6b21\u5e93\u5b58\u51cf1\uff0c\u770b\u6700\u540e\u5546\u54c1\u6570\u6709\u6ca1\u6709\u53d8\u4e3a\u8d1f\u6570<\/p>\n<p>\uff084\uff09\u5728redis\u4e2d\uff0c\u8bbe\u7f6e\u4e00\u4e2a\u5e93\u5b58\u6570\u91cf\u4e3a100<\/p>\n<pre><code class=\"language-java\">@Test\npublic void test() throws Exception {\n    \/\/\u8bbe\u7f6e\u4e00\u4e2akey\uff0caaa\u5546\u54c1\u7684\u5e93\u5b58\u6570\u91cf\u4e3a100\n    stringRedisTemplate.opsForValue().set(&quot;aaa&quot;, &quot;100&quot;);\n    Assert.assertEquals(&quot;100&quot;, stringRedisTemplate.opsForValue().get(&quot;aaa&quot;));\n}<\/code><\/pre>\n<p>\uff085\uff09\u628a\u9879\u76ee\u590d\u5236\u4e00\u4efd\uff0c2\u4e2a\u9879\u76ee\uff0c\u5206\u522b\u4f7f\u7528\u4e0b\u9762\u7684\u6d4b\u8bd5\u65b9\u6cd5\uff0c\u540c\u65f6\u542f\u52a8\uff0c\u56e0\u5e93\u5b58\u4e3a100\uff0c\u6bcf\u6b21\u8bf7\u6c42\u5e93\u5b58\u51cf1\uff0c\u542f\u52a82\u4e2a\u6d4b\u8bd5\u65b9\u6cd5\u5404\u5faa\u73af60\u6b21\uff0c\u603b\u8ba1120\u6b21\u8bf7\u6c42\uff0c\u770b\u5e93\u5b58\u6253\u5370\u7ed3\u679c\u4f1a\u4e0d\u4f1a\u53d8\u8d1f\u6570<\/p>\n<pre><code class=\"language-java\">String lockKey = &quot;testRedisson&quot;;\/\/\u5206\u5e03\u5f0f\u9501\u7684key\n@Test\npublic void testDistributed() {\n    \/\/\u6267\u884c\u7684\u4e1a\u52a1\u4ee3\u7801\n    for (int i=0; i &lt; 60; i++) {\n        RLock lock = redisson.getLock(lockKey);\n        lock.lock(60, TimeUnit.SECONDS); \/\/\u8bbe\u7f6e60\u79d2\u81ea\u52a8\u91ca\u653e\u9501\uff08\u9ed8\u8ba4\u662f30\u79d2\u81ea\u52a8\u8fc7\u671f\uff09\n        int stock = Integer.parseInt(stringRedisTemplate.opsForValue().get(&quot;aaa&quot;).toString());\n        if (stock &gt; 0) {\n            stringRedisTemplate.opsForValue().set(&quot;aaa&quot;, (stock-1)+&quot;&quot;);\n            System.out.println(&quot;lockkey:&quot; + lockKey + &quot;,stock:&quot; + (stock-1));\n        }\n        lock.unlock(); \/\/\u91ca\u653e\u9501\n    }\n}<\/code><\/pre>\n<p>\u6d4b\u8bd5\u7ed3\u679c\uff1a\u6b63\u786e\uff0credis\u7684\u503c\u6ca1\u6709\u53d8\u8d1f\u6570\uff0c\u8bf4\u660e\u88ab\u9501\u4f4f\u4e86<\/p>\n<h2>Spring Cloud \u5b9e\u73b0 redisson \u5206\u5e03\u5f0f\u9501<\/h2>\n<h3>\u9700\u6c42\u80cc\u666f<\/h3>\n<p>\u542f\u52a8Redis\uff0c6379\u7aef\u53e3\uff0cSpring Cloud\u5fae\u670d\u52a1\uff0c\u6a21\u62df\u79d2\u6740\u62a2\u8d2d\u573a\u666f\uff0c100\u5e93\u5b58\uff0c\u7528jmeter\u6d4b\u8bd5\uff0c\u8d77300\u4e2a\u7ebf\u7a0b\u5e76\u53d1\u8bf7\u6c422\u6b21\uff0c\u603b\u8ba1600\u4e2a\u8bf7\u6c42\u6570\uff0c\u6700\u540e\u67e5\u770b\u5e93\u5b58\u662f\u5426\u4e3a\u8d1f\u6570\uff0c\u8bc1\u660e\u5206\u5e03\u5f0f\u9501\u662f\u5426\u9501\u4f4f\u4e86\u5e93\u5b58\u3002<\/p>\n<ul>\n<li>\u6ce8\u518c\u4e2d\u5fc3 10025\u7aef\u53e3<\/li>\n<li>\u6d88\u8d39\u8005\u670d\u52a1 9700\u7aef\u53e3<\/li>\n<li>\u79d2\u6740\u670d\u52a1 8081\u30018082\uff0c\u542f\u52a82\u4e2a\u670d\u52a1<\/li>\n<\/ul>\n<p>\u6d4b\u8bd5\u6d41\u7a0b\u5982\u4e0b\uff1a<\/p>\n<ol>\n<li>\u542f\u52a8\u6ce8\u518c\u4e2d\u5fc3\uff0c\u6d88\u8d39\u8005\u670d\u52a1\u4e0e\u79d2\u6740\u670d\u52a1\u90fd\u6ce8\u518c\u5230\u6ce8\u518c\u4e2d\u5fc3<\/li>\n<li>\u542f\u52a8\u6d88\u8d39\u8005\u670d\u52a1\uff0c\u901a\u8fc7feign \u4ee5\u8d1f\u8f7d\u5747\u8861\u65b9\u5f0f\u8c03\u7528\u79d2\u6740\u670d\u52a1<\/li>\n<li>\u542f\u52a8\u79d2\u6740\u670d\u52a1\uff0c\u8bf7\u6c42\u79d2\u6740\u670d\u52a1\u65f6\uff0c\u4fee\u6539\u5546\u54c1\u5e93\u5b58\uff0c\u5546\u54c1\u5e93\u5b58\u5b58\u50a8\u5728redis\u4e2d\uff0c\u9ed8\u8ba4100<\/li>\n<\/ol>\n<p>\u901a\u8fc7jmeter\u6267\u884chttp\u8bf7\u6c42\uff0c\u6a21\u62df\u7528\u6237\u62a2\u8d2d\u3002\u67e5\u770b\u7ed3\u679c\uff0c\u4ecejmeter\u4e0a\u53ef\u4ee5\u770b\u5230\u6709600\u4e2a\u8bf7\u6c42\uff0c\u670913\u4e2a\u5931\u8d25\u4e86\u3002\u518d\u770bredis\u4e2d\u7684\u5e93\u5b58\u4e3a0\uff0c\u8bf4\u660e\u9501\u4f4f\u4e86\uff0c\u6ca1\u6709\u53d1\u751f\u8d85\u5356\u73b0\u8c61\u3002\u603b\u5171\u6d4b\u8bd5\u4e86\u591a\u6b21\uff0c\u8d34\u51fa\u6709\u4ee3\u8868\u6027\u7684\uff1a<\/p>\n<ul>\n<li>1\u79d2\u5185\u542f\u52a8 200\u7ebf\u7a0b\uff0c\u5faa\u73af\u8bf7\u6c422\u6b21\uff0c\u603b\u8ba1400\u8bf7\u6c42\uff0c\u6210\u529f\u4e86\u51e0\u5341\u4e2a\u8bf7\u6c42\uff0c\u5176\u4f59\u8bf7\u6c42\u88abhystrix\u964d\u7ea7\u8fd4\u56de<\/li>\n<li>2\u79d2\u5185\u542f\u52a8 300\u7ebf\u7a0b\uff0c\u5faa\u73af\u8bf7\u6c422\u6b21\uff0c\u603b\u8ba1600\u8bf7\u6c42\uff0c\u8bf7\u6c42\u5168\u90e8\u6210\u529f\uff0c\u5e93\u5b58\u4e3a0<\/li>\n<li>3\u79d2\u5185\u542f\u52a8 500\u7ebf\u7a0b\uff0c\u5faa\u73af\u8bf7\u6c422\u6b21\uff0c\u603b\u8ba11000\u8bf7\u6c42\uff0c\u8bf7\u6c42\u5168\u90e8\u6210\u529f\uff0c\u5e93\u5b58\u4e3a0<\/li>\n<li>5\u79d2\u5185\u542f\u52a8 1000\u7ebf\u7a0b\uff0c\u5faa\u73af\u8bf7\u6c422\u6b21\uff0c\u603b\u8ba12000\u8bf7\u6c42\uff0c\u8bf7\u6c42\u5168\u90e8\u6210\u529f\uff0c\u5e93\u5b58\u4e3a0<\/li>\n<\/ul>\n<p>\u8bf4\u660e\u57281\u79d2\u5185\u542f\u52a8200\u4e2a\u7ebf\u7a0b\u5e76\u53d1\u8bf7\u6c42\uff0c\u7a0b\u5e8f\u65e0\u6cd5\u5904\u7406\u8fc7\u6765<\/p>\n<h3>\u79d2\u6740\u5b9e\u73b0<\/h3>\n<p>\uff081\uff09\u79d2\u6740\u670d\u52a1\u4e3b\u8981\u4f9d\u8d56\u4e86<code>redisson<\/code>\u4e0e<code>netty<\/code>\uff0c\u5176\u4ed6\u90fd\u662f\u5fae\u670d\u52a1\u5f00\u53d1\u9700\u5f15\u5165\u7684<\/p>\n<pre><code class=\"language-xml\">&lt;dependency&gt;\n    &lt;groupId&gt;org.springframework.cloud&lt;\/groupId&gt;\n    &lt;artifactId&gt;spring-cloud-starter-netflix-eureka-client&lt;\/artifactId&gt;\n&lt;\/dependency&gt;\n&lt;!--web \u6a21\u5757--&gt;\n&lt;dependency&gt;\n    &lt;groupId&gt;org.springframework.boot&lt;\/groupId&gt;\n    &lt;artifactId&gt;spring-boot-starter-web&lt;\/artifactId&gt;\n&lt;\/dependency&gt;\n&lt;dependency&gt;\n    &lt;groupId&gt;org.springframework.boot&lt;\/groupId&gt;\n    &lt;artifactId&gt;spring-boot-starter-data-redis&lt;\/artifactId&gt;\n&lt;\/dependency&gt;\n&lt;dependency&gt;\n    &lt;groupId&gt;org.redisson&lt;\/groupId&gt;\n    &lt;artifactId&gt;redisson&lt;\/artifactId&gt;\n    &lt;version&gt;3.6.5&lt;\/version&gt;\n&lt;\/dependency&gt;\n&lt;dependency&gt;\n    &lt;groupId&gt;io.netty&lt;\/groupId&gt;\n    &lt;artifactId&gt;netty-all&lt;\/artifactId&gt;\n    &lt;version&gt;4.1.25.Final&lt;\/version&gt;\n&lt;\/dependency&gt;<\/code><\/pre>\n<p>\uff082\uff09\u542f\u52a8\u4e3b\u7c7b\u7684\u4ee3\u7801\u5982\u4e0b\uff1a<\/p>\n<pre><code class=\"language-java\">@EnableDiscoveryClient\n@SpringBootApplication\npublic class DistributedLockApplication {\n\n    public static void main(String[] args) {\n        SpringApplication.run(DistributedLockApplication.class, args);\n    }\n\n    \/\/\u6dfb\u52a0redisson\u7684bean\n    @Bean\n    public Redisson redisson() {\n        Config config = new Config();\n        \/\/\u6b64\u793a\u4f8b\u662f\u5355\u5e93\u7684\uff0c\u53ef\u4ee5\u662f\u4e3b\u4ece\u3001sentinel\u3001\u96c6\u7fa4\u7b49\u6a21\u5f0f\n        config.useSingleServer().setAddress(&quot;redis:\/\/localhost:6379&quot;);\n        return (Redisson)Redisson.create(config);\n    }\n}<\/code><\/pre>\n<p>\uff083\uff09\u7136\u540e\u662f\u63d0\u4f9b\u79d2\u6740\u529f\u80fd\u7684\u63a7\u5236\u5668<\/p>\n<pre><code class=\"language-java\">@RestController\npublic class IndexController {\n    private static String commodityCount = &quot;commodityCount&quot;;  \/\/\u5546\u54c1key\n    private static String lockKey = &quot;testRedisson&quot;;  \/\/\u5206\u5e03\u5f0f\u9501\u7684key\n    @Autowired private StringRedisTemplate redisTemplate;\n    @Autowired private Redisson redisson;\n\n    \/**\n     * \u67e5\u8be2\u662f\u5426\u5065\u5eb7\n     * @return\n     *\/\n    @RequestMapping(value = &quot;\/health&quot;, method = RequestMethod.GET)\n    public String health() {\n        return &quot;health&quot;;\n    }\n\n    \/**\n     * \u8bbe\u7f6e\u5546\u54c1\u6570\u91cf\u4e3a100\u4e2a\n     * @param value\n     * @return\n     *\/\n    @RequestMapping(&quot;\/setValue&quot;)\n    public String setValue(int value) {\n        redisTemplate.opsForValue().set(commodityCount, value + &quot;&quot;);\n        return &quot;success&quot;;\n    }\n\n    \/**\n     * \u6a21\u62df\u79d2\u6740\u62a2\u8d2d\uff0c\u5e76\u53d1200\u4e2a\u8bf7\u6c42\u8fc7\u6765\uff0c\u67e5\u770b\u662f\u5426\u51fa\u73b0\u8d85\u5356\n     * @return\n     *\/\n    @RequestMapping(&quot;\/spike&quot;)\n    public String spike() {\n        String flag = &quot;success&quot;;\n        RLock lock = redisson.getLock(lockKey);\n        try {\n            \/\/lock.lockAsync(5 , TimeUnit.SECONDS);\n            \/\/lock.lock(5, TimeUnit.SECONDS); \/\/\u8bbe\u7f6e60\u79d2\u81ea\u52a8\u91ca\u653e\u9501\uff08\u9ed8\u8ba4\u662f30\u79d2\u81ea\u52a8\u8fc7\u671f\uff09\n            Future&lt;Boolean&gt; res = lock.tryLockAsync(100, 5, TimeUnit.SECONDS);\n            boolean result = res.get();\n            System.out.println(&quot;result:&quot; + result);\n            if (result) {\n                int stock = Integer.parseInt(redisTemplate.opsForValue().get(commodityCount).toString());\n                if (stock &gt; 0) {\n                    redisTemplate.opsForValue().set(commodityCount, (stock-1)+&quot;&quot;);\n                } else {\n                    flag = &quot;fail&quot;;\n                }\n            }\n        } catch (Exception e) {\n            e.printStackTrace();\n        } finally {\n            lock.unlock(); \/\/\u91ca\u653e\u9501\n        }\n        return flag;\n    }\n}<\/code><\/pre>\n","protected":false},"excerpt":{"rendered":"<p>Spring Boot \u63a5\u5165 redisson \u5206\u5e03\u5f0f\u9501 \u4e3a\u4ec0\u4e48\u8981\u4f7f\u7528\u5206\u5e03\u5f0f\u9501? \u5728\u5206\u5e03\u5f0f\u573a\u666f\u4e0b\u4e3a\u4e86\u4fdd\u8bc1\u6570\u636e\u6700 [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[101],"tags":[105,104],"class_list":["post-1965","post","type-post","status-publish","format-standard","hentry","category-distributed","tag-redisson","tag-104"],"_links":{"self":[{"href":"https:\/\/www.appblog.cn\/index.php\/wp-json\/wp\/v2\/posts\/1965","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.appblog.cn\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.appblog.cn\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.appblog.cn\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.appblog.cn\/index.php\/wp-json\/wp\/v2\/comments?post=1965"}],"version-history":[{"count":0,"href":"https:\/\/www.appblog.cn\/index.php\/wp-json\/wp\/v2\/posts\/1965\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.appblog.cn\/index.php\/wp-json\/wp\/v2\/media?parent=1965"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.appblog.cn\/index.php\/wp-json\/wp\/v2\/categories?post=1965"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.appblog.cn\/index.php\/wp-json\/wp\/v2\/tags?post=1965"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}