{"id":1950,"date":"2023-04-01T10:13:11","date_gmt":"2023-04-01T02:13:11","guid":{"rendered":"https:\/\/www.appblog.cn\/?p=1950"},"modified":"2023-04-22T08:40:29","modified_gmt":"2023-04-22T00:40:29","slug":"dynamic-routing-implementation-of-spring-cloud-gateway","status":"publish","type":"post","link":"https:\/\/www.appblog.cn\/index.php\/2023\/04\/01\/dynamic-routing-implementation-of-spring-cloud-gateway\/","title":{"rendered":"Spring Cloud Gateway\u7684\u52a8\u6001\u8def\u7531\u5b9e\u73b0"},"content":{"rendered":"<h2>\u524d\u8a00<\/h2>\n<p>\u7f51\u5173\u4e2d\u6709\u4e24\u4e2a\u91cd\u8981\u7684\u6982\u5ff5\uff0c\u90a3\u5c31\u662f\u8def\u7531\u914d\u7f6e\u548c\u8def\u7531\u89c4\u5219\uff0c\u8def\u7531\u914d\u7f6e\u662f\u6307\u914d\u7f6e\u67d0\u8bf7\u6c42\u8def\u5f84\u8def\u7531\u5230\u6307\u5b9a\u7684\u76ee\u7684\u5730\u5740\u3002\u800c\u8def\u7531\u89c4\u5219\u662f\u6307\u5339\u914d\u5230\u8def\u7531\u914d\u7f6e\u4e4b\u540e\uff0c\u518d\u6839\u636e\u8def\u7531\u89c4\u5219\u8fdb\u884c\u8f6c\u53d1\u5904\u7406\u3002<br \/>\nSpring Cloud Gateway\u4f5c\u4e3a\u6240\u6709\u8bf7\u6c42\u6d41\u91cf\u7684\u5165\u53e3\uff0c\u5728\u5b9e\u9645\u751f\u4ea7\u73af\u5883\u4e2d\u4e3a\u4e86\u4fdd\u8bc1\u9ad8\u53ef\u9760\u548c\u9ad8\u53ef\u7528\uff0c\u5c3d\u91cf\u907f\u514d\u91cd\u542f\uff0c\u9700\u8981\u5b9e\u73b0Spring Cloud Gateway\u52a8\u6001\u8def\u7531\u914d\u7f6e\u3002Spring Cloud Gateway\u63d0\u4f9b\u7684\u4e24\u79cd\u65b9\u6cd5\u53bb\u914d\u7f6e\u8def\u7531\u89c4\u5219\uff0c\u4f46\u90fd\u662f\u5728Spring Cloud Gateway\u542f\u52a8\u65f6\uff0c\u5c31\u5c06\u8def\u7531\u914d\u7f6e\u548c\u89c4\u5219\u52a0\u8f7d\u5230\u5185\u5b58\u91cc\uff0c\u65e0\u6cd5\u505a\u5230\u4e0d\u91cd\u542f\u7f51\u5173\u5c31\u53ef\u4ee5\u52a8\u6001\u7684\u5bf9\u5e94\u8def\u7531\u7684\u914d\u7f6e\u548c\u89c4\u5219\u8fdb\u884c\u589e\u52a0\uff0c\u4fee\u6539\u548c\u5220\u9664\u3002<\/p>\n<p><!-- more --><\/p>\n<h2>Spring Cloud Gateway\u7b80\u5355\u7684\u52a8\u6001\u8def\u7531\u5b9e\u73b0<\/h2>\n<p>Spring Cloud Gateway\u7684\u5b98\u65b9\u6587\u6863\u5e76\u6ca1\u6709\u8bb2\u5982\u4f55\u52a8\u6001\u914d\u7f6e\uff0c\u67e5\u770b Spring Cloud Gateway\u7684\u6e90\u7801\uff0c\u53d1\u73b0\u5728<code>org.springframework.cloud.gateway.actuate.GatewayControllerEndpoint<\/code>\u7c7b\u4e2d\u63d0\u4f9b\u4e86\u52a8\u6001\u914d\u7f6e\u7684Rest\u63a5\u53e3\uff0c\u4f46\u662f\u9700\u8981\u5f00\u542fGateway\u7684\u7aef\u70b9\uff0c\u800c\u4e14\u63d0\u4f9b\u7684\u529f\u80fd\u4e0d\u662f\u5f88\u5f3a\u5927\u3002\u901a\u8fc7\u53c2\u8003\u548cGatewayControllerEndpoint\u76f8\u5173\u7684\u4ee3\u7801\uff0c\u53ef\u4ee5\u81ea\u5df1\u7f16\u7801\u5b9e\u9645\u52a8\u6001\u8def\u7531\u914d\u7f6e\u3002<\/p>\n<h2>\u7b80\u5355\u52a8\u6001\u8def\u7531\u7684\u5b9e\u73b0<\/h2>\n<h3>Maven\u4f9d\u8d56<\/h3>\n<pre><code class=\"language-xml\">&lt;dependencies&gt;\n    &lt;dependency&gt;\n        &lt;groupId&gt;org.springframework.cloud&lt;\/groupId&gt;\n        &lt;artifactId&gt;spring-cloud-starter-gateway&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-webflux&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-actuator&lt;\/artifactId&gt;\n    &lt;\/dependency&gt;\n    &lt;dependency&gt;\n        &lt;groupId&gt;com.alibaba&lt;\/groupId&gt;\n        &lt;artifactId&gt;fastjson&lt;\/artifactId&gt;\n    &lt;\/dependency&gt;\n&lt;\/dependencies&gt;<\/code><\/pre>\n<h3>\u6839\u636eSpring Cloud Gateway\u7684\u8def\u7531\u6a21\u578b\u5b9a\u4e49\u6570\u636e\u4f20\u8f93\u6a21\u578b<\/h3>\n<p>\u5206\u522b\u521b\u5efa<code>GatewayRouteDefinition.java<\/code>, <code>GatewayPredicateDefinition.java<\/code>, <code>GatewayFilterDefinition.java<\/code>\u8fd9\u4e09\u4e2a\u7c7b\u3002<\/p>\n<p>(1) \u521b\u5efa\u8def\u7531\u5b9a\u4e49\u6a21\u578b<\/p>\n<pre><code class=\"language-java\">\/**\n * Gateway\u7684\u8def\u7531\u5b9a\u4e49\u6a21\u578b\n * @author yezhou\n *\/\n@Data\npublic class GatewayRouteDefinition {\n\n    \/**\n     * \u8def\u7531\u7684Id\n     *\/\n    private String id;\n\n    \/**\n     * \u8def\u7531\u65ad\u8a00\u96c6\u5408\u914d\u7f6e\n     *\/\n    private List&lt;GatewayPredicateDefinition&gt; predicates = new ArrayList&lt;&gt;();\n\n    \/**\n     * \u8def\u7531\u8fc7\u6ee4\u5668\u96c6\u5408\u914d\u7f6e\n     *\/\n    private List&lt;GatewayFilterDefinition&gt; filters = new ArrayList&lt;&gt;();\n\n    \/**\n     * \u8def\u7531\u89c4\u5219\u8f6c\u53d1\u7684\u76ee\u6807uri\n     *\/\n    private String uri;\n\n    \/**\n     * \u8def\u7531\u6267\u884c\u7684\u987a\u5e8f\n     *\/\n    private int order = 0;\n\n}<\/code><\/pre>\n<p>(2) \u521b\u5efa\u8fc7\u6ee4\u5668\u5b9a\u4e49\u6a21\u578b<\/p>\n<pre><code class=\"language-java\">\/**\n * \u8fc7\u6ee4\u5668\u5b9a\u4e49\u6a21\u578b\n * @author yezhou\n *\/\n@Data\npublic class GatewayFilterDefinition {\n\n    \/**\n     * Filter Name\n     *\/\n    private String name;\n\n    \/**\n     * \u5bf9\u5e94\u7684\u8def\u7531\u89c4\u5219\n     *\/\n    private Map&lt;String, String&gt; args = new LinkedHashMap&lt;&gt;();\n\n}<\/code><\/pre>\n<p>(3) \u8def\u7531\u65ad\u8a00\u5b9a\u4e49\u6a21\u578b<\/p>\n<pre><code class=\"language-java\">\/**\n * \u8def\u7531\u65ad\u8a00\u5b9a\u4e49\u6a21\u578b\n * @author yezhou\n *\/\n@Data\npublic class GatewayPredicateDefinition {\n\n    \/**\n     * \u65ad\u8a00\u5bf9\u5e94\u7684Name\n     *\/\n    private String name;\n\n    \/**\n     * \u914d\u7f6e\u7684\u65ad\u8a00\u89c4\u5219\n     *\/\n    private Map&lt;String, String&gt; args = new LinkedHashMap&lt;&gt;();\n\n}<\/code><\/pre>\n<h3>\u7f16\u5199\u52a8\u6001\u8def\u7531\u5b9e\u73b0\u7c7b<\/h3>\n<p>\u7f16\u5199DynamicRouteServiceImpl\u5e76\u5b9e\u73b0ApplicationEventPublisherAware\u63a5\u53e3<\/p>\n<pre><code class=\"language-java\">import com.alibaba.fastjson.JSON;\nimport me.yezhou.spring.cloud.gateway.model.GatewayPredicateDefinition;\nimport me.yezhou.spring.cloud.gateway.model.GatewayRouteDefinition;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.cloud.gateway.event.RefreshRoutesEvent;\nimport org.springframework.cloud.gateway.handler.predicate.PredicateDefinition;\nimport org.springframework.cloud.gateway.route.RouteDefinition;\nimport org.springframework.cloud.gateway.route.RouteDefinitionWriter;\nimport org.springframework.context.ApplicationEventPublisher;\nimport org.springframework.context.ApplicationEventPublisherAware;\nimport org.springframework.stereotype.Service;\nimport org.springframework.web.util.UriComponentsBuilder;\nimport reactor.core.publisher.Mono;\n\nimport java.net.URI;\nimport java.util.Arrays;\nimport java.util.HashMap;\nimport java.util.Map;\n\n\/**\n * @author yezhou\n *\/\n@Service\npublic class DynamicRouteServiceImpl implements ApplicationEventPublisherAware {\n\n    @Autowired\n    private RouteDefinitionWriter routeDefinitionWriter;\n\n    private ApplicationEventPublisher publisher;\n\n    \/**\n     * \u589e\u52a0\u8def\u7531\n     *\n     * @param definition\n     * @return\n     *\/\n    public String add(RouteDefinition definition) {\n        routeDefinitionWriter.save(Mono.just(definition)).subscribe();\n        this.publisher.publishEvent(new RefreshRoutesEvent(this));\n        return &quot;success&quot;;\n    }\n\n    \/**\n     * \u66f4\u65b0\u8def\u7531\n     *\n     * @param definition\n     * @return\n     *\/\n    public String update(RouteDefinition definition) {\n        try {\n            this.routeDefinitionWriter.delete(Mono.just(definition.getId())).subscribe();\n        } catch (Exception e) {\n            return &quot;update fail,not find route  routeId: &quot; + definition.getId();\n        }\n        try {\n            routeDefinitionWriter.save(Mono.just(definition)).subscribe();\n            this.publisher.publishEvent(new RefreshRoutesEvent(this));\n            return &quot;success&quot;;\n        } catch (Exception e) {\n            return &quot;update route  fail&quot;;\n        }\n    }\n\n    \/**\n     * \u5220\u9664\u8def\u7531\n     *\n     * @param id\n     * @return\n     *\/\n    public String delete(String id) {\n        System.out.println(id);\n        try {\n            this.routeDefinitionWriter.delete(Mono.just(id)).subscribe();\n            return &quot;delete success&quot;;\n        } catch (Exception e) {\n            e.printStackTrace();\n            return &quot;delete fail&quot;;\n        }\n    }\n\n    @Override\n    public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {\n        this.publisher = applicationEventPublisher;\n    }\n\n    \/**\n     * spring:\n     * cloud:\n     * gateway:\n     * routes: #\u5f53\u8bbf\u95eehttp:\/\/localhost:8080\/baidu,\u76f4\u63a5\u8f6c\u53d1\u5230https:\/\/www.baidu.com\/\n     * - id: baidu_route\n     * uri: http:\/\/baidu.com:80\/\n     * predicates:\n     * - Path=\/baidu\n     *\n     * @param args\n     *\/\n    public static void main(String[] args) {\n        GatewayRouteDefinition definition = new GatewayRouteDefinition();\n        GatewayPredicateDefinition predicate = new GatewayPredicateDefinition();\n        Map&lt;String, String&gt; predicateParams = new HashMap&lt;&gt;(8);\n        definition.setId(&quot;jd_route&quot;);\n        predicate.setName(&quot;Path&quot;);\n        predicateParams.put(&quot;pattern&quot;, &quot;\/jd&quot;);\n        predicate.setArgs(predicateParams);\n        definition.setPredicates(Arrays.asList(predicate));\n        String uri = &quot;http:\/\/www.jd.com&quot;;\n        \/\/URI uri = UriComponentsBuilder.fromHttpUrl(&quot;http:\/\/www.baidu.com&quot;).build().toUri();\n        definition.setUri(uri);\n        System.out.println(&quot;definition:&quot; + JSON.toJSONString(definition));\n\n        RouteDefinition definition1 = new RouteDefinition();\n        PredicateDefinition predicate1 = new PredicateDefinition();\n        Map&lt;String, String&gt; predicateParams1 = new HashMap&lt;&gt;(8);\n        definition1.setId(&quot;baidu_route&quot;);\n        predicate1.setName(&quot;Path&quot;);\n        predicateParams1.put(&quot;pattern&quot;, &quot;\/baidu&quot;);\n        predicate1.setArgs(predicateParams1);\n        definition1.setPredicates(Arrays.asList(predicate1));\n        URI uri1 = UriComponentsBuilder.fromHttpUrl(&quot;http:\/\/www.baidu.com&quot;).build().toUri();\n        definition1.setUri(uri1);\n        System.out.println(&quot;definition1\uff1a&quot; + JSON.toJSONString(definition1));\n    }\n}<\/code><\/pre>\n<h3>\u7f16\u5199Rest\u63a5\u53e3<\/h3>\n<p>\u7f16\u5199RouteController\u7c7b\u7684\u63d0\u4f9bRest\u63a5\u53e3\uff0c\u7528\u4e8e\u52a8\u6001\u8def\u7531\u914d\u7f6e\u3002<\/p>\n<pre><code class=\"language-java\">import me.yezhou.spring.cloud.gateway.model.GatewayFilterDefinition;\nimport me.yezhou.spring.cloud.gateway.model.GatewayPredicateDefinition;\nimport me.yezhou.spring.cloud.gateway.model.GatewayRouteDefinition;\nimport me.yezhou.spring.cloud.gateway.service.DynamicRouteServiceImpl;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.cloud.gateway.filter.FilterDefinition;\nimport org.springframework.cloud.gateway.handler.predicate.PredicateDefinition;\nimport org.springframework.cloud.gateway.route.RouteDefinition;\nimport org.springframework.web.bind.annotation.*;\nimport org.springframework.web.util.UriComponentsBuilder;\n\nimport java.net.URI;\nimport java.util.ArrayList;\nimport java.util.List;\n\n\/**\n * @author yezhou\n *\/\n@RestController\n@RequestMapping(&quot;\/route&quot;)\npublic class RouteController {\n\n    @Autowired\n    private DynamicRouteServiceImpl dynamicRouteService;\n\n    \/**\n     * \u589e\u52a0\u8def\u7531\n     * @param gwdefinition\n     * @return\n     *\/\n    @PostMapping(&quot;\/add&quot;)\n    public String add(@RequestBody GatewayRouteDefinition gwdefinition) {\n        try {\n            RouteDefinition definition = assembleRouteDefinition(gwdefinition);\n            return this.dynamicRouteService.add(definition);\n        } catch (Exception e) {\n            e.printStackTrace();\n        }\n        return &quot;succss&quot;;\n    }\n\n    @GetMapping(&quot;\/delete\/{id}&quot;)\n    public String delete(@PathVariable String id) {\n        return this.dynamicRouteService.delete(id);\n    }\n\n    @PostMapping(&quot;\/update&quot;)\n    public String update(@RequestBody GatewayRouteDefinition gwdefinition) {\n        RouteDefinition definition = assembleRouteDefinition(gwdefinition);\n        return this.dynamicRouteService.update(definition);\n    }\n\n    private RouteDefinition assembleRouteDefinition(GatewayRouteDefinition gwdefinition) {\n\n        RouteDefinition definition = new RouteDefinition();\n\n        \/\/ ID\n        definition.setId(gwdefinition.getId());\n\n        \/\/ Predicates\n        List&lt;PredicateDefinition&gt; pdList = new ArrayList&lt;&gt;();\n        for (GatewayPredicateDefinition gpDefinition: gwdefinition.getPredicates()) {\n            PredicateDefinition predicate = new PredicateDefinition();\n            predicate.setArgs(gpDefinition.getArgs());\n            predicate.setName(gpDefinition.getName());\n            pdList.add(predicate);\n        }\n        definition.setPredicates(pdList);\n\n        \/\/ Filters\n        List&lt;FilterDefinition&gt; fdList = new ArrayList&lt;&gt;();\n        for (GatewayFilterDefinition gfDefinition: gwdefinition.getFilters()) {\n            FilterDefinition filter = new FilterDefinition();\n            filter.setArgs(gfDefinition.getArgs());\n            filter.setName(gfDefinition.getName());\n            fdList.add(filter);\n        }\n        definition.setFilters(fdList);\n\n        \/\/ URI\n        URI uri = UriComponentsBuilder.fromUriString(gwdefinition.getUri()).build().toUri();\n        definition.setUri(uri);\n\n        return definition;\n    }\n\n}<\/code><\/pre>\n<h3>\u914d\u7f6eapplication.yml\u6587\u4ef6<\/h3>\n<p>\u5728application.yml\u6587\u4ef6\u914d\u7f6e\u5e94\u7528\u7684\u914d\u7f6e\u4fe1\u606f\uff0c\u5e76\u5f00\u542fSpring Cloud Gateway\u5bf9\u5916\u63d0\u4f9b\u7684\u7aef\u70b9Rest\u63a5\u53e3\u3002<\/p>\n<pre><code class=\"language-yml\">server:\n  port: 8080\nspring:\n  application:\n    name: ok-cloud-gateway\n\n# \u914d\u7f6e\u8f93\u51fa\u65e5\u5fd7\nlogging:\n  level:\n    org.springframework.cloud.gateway: TRACE\n    org.springframework.http.server.reactive: DEBUG\n    org.springframework.web.reactive: DEBUG\n    reactor.ipc.netty: DEBUG\n\n#\u5f00\u542f\u7aef\u70b9\nmanagement:\n  endpoints:\n    web:\n      exposure:\n        include: &#039;*&#039;\n  security:\n    enabled: false<\/code><\/pre>\n<h3>\u542f\u52a8\u5e94\u7528\u6d4b\u8bd5<\/h3>\n<p>(1) \u542f\u52a8\u5e94\u7528\u4e4b\u540e\uff0c\u7531\u4e8e\u5f00\u542f\u4e86\u7aef\u70b9\uff0c\u9996\u5148\u6253\u5f00\u6d4f\u89c8\u5668\u8bbf\u95ee\u7aef\u70b9<code>http:\/\/localhost:8080\/actuator\/gateway\/routes<\/code>\uff0c\u67e5\u770b\u8def\u7531\u4fe1\u606f\u8fd4\u56de\u4e3a\u7a7a<\/p>\n<p>(2) \u6253\u5f00PostMan\uff0c\u8bbf\u95ee<code>http:\/\/localhost:8080\/route\/add<\/code>\uff0c\u53d1\u8d77Post\u8bf7\u6c42\uff0c\u8fd4\u56desuccess\u8bf4\u660e\u5411Gateway\u589e\u52a0\u8def\u7531\u914d\u7f6e\u6210\u529f<\/p>\n<pre><code class=\"language-json\">{\n    &quot;filter&quot;: [],\n    &quot;id&quot;: &quot;jd_route&quot;,\n    &quot;order&quot;: 0,\n    &quot;predicates&quot;: [{\n        &quot;args&quot;: {\n            &quot;pattern&quot;: &quot;\/jd&quot;\n        },\n        &quot;name&quot;: &quot;Path&quot;\n    }],\n    &quot;uri&quot;: &quot;http:\/\/www.jd.com&quot;\n}<\/code><\/pre>\n<p>\u7136\u540e\u518d\u6253\u5f00PostMan\u8bbf\u95ee\u7aef\u70b9<code>http:\/\/localhost:8080\/actuator\/gateway\/routes<\/code>\uff0c\u67e5\u770b\u8def\u7531\u4fe1\u606f\u8fd4\u56de\uff0c\u53ef\u4ee5\u770b\u5230\u5df2\u7ecf\u6dfb\u52a0\u7684\u8def\u7531\u914d\u7f6e<\/p>\n<p>(3) \u6253\u5f00\u6d4f\u89c8\u5668\u8bbf\u95ee<code>http:\/\/localhost:8080\/jd<\/code>\uff0c\u53ef\u4ee5\u6b63\u5e38\u8f6c\u53d1<code>https:\/\/www.jd.com\/<\/code>\u5bf9\u5e94\u7684\u4eac\u4e1c\u5546\u57ce\u9996\u9875<\/p>\n<p>(4) \u901a\u8fc7\u8bbf\u95ee<code>http:\/\/localhost:8080\/route\/update<\/code>\uff0c\u5bf9id\u4e3ajd_route\u7684\u8def\u7531\u66f4\u65b0\u914d\u7f6e\uff1a<\/p>\n<pre><code class=\"language-json\">{\n    &quot;filter&quot;: [],\n    &quot;id&quot;: &quot;jd_route&quot;,\n    &quot;order&quot;: 0,\n    &quot;predicates&quot;: [{\n        &quot;args&quot;: {\n            &quot;pattern&quot;: &quot;\/taobao&quot;\n        },\n        &quot;name&quot;: &quot;Path&quot;\n    }],\n    &quot;uri&quot;: &quot;http:\/\/www.taobao.com&quot;\n}<\/code><\/pre>\n<p>\u7136\u540e\u518d\u8bbf\u95ee\u8def\u7531\u7aef\u70b9URL\uff0c\u53d1\u73b0\u8def\u7531\u914d\u7f6e\u5df2\u7ecf\u88ab\u66f4\u65b0\uff0c\u7136\u540e\u901a\u8fc7\u6d4f\u89c8\u5668\u8bbf\u95ee<code>http:\/\/localhost:8080\/taobao<\/code>\uff0c\u53ef\u4ee5\u6210\u529f\u8f6c\u53d1\u5230\u6dd8\u5b9d\u7f51<\/p>\n<p>(5) \u901a\u8fc7\u8bbf\u95ee<code>http:\/\/localhost:8080\/route\/delete\/jd_route<\/code>\uff0c\u5176\u4e2d\u7684id\u4e3a\u8def\u7531\u5bf9\u5e94\u7684id\uff0c\u5220\u9664\u8def\u7531<\/p>\n","protected":false},"excerpt":{"rendered":"<p>\u524d\u8a00 \u7f51\u5173\u4e2d\u6709\u4e24\u4e2a\u91cd\u8981\u7684\u6982\u5ff5\uff0c\u90a3\u5c31\u662f\u8def\u7531\u914d\u7f6e\u548c\u8def\u7531\u89c4\u5219\uff0c\u8def\u7531\u914d\u7f6e\u662f\u6307\u914d\u7f6e\u67d0\u8bf7\u6c42\u8def\u5f84\u8def\u7531\u5230\u6307\u5b9a\u7684\u76ee\u7684\u5730\u5740\u3002\u800c\u8def\u7531 [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[42],"tags":[439],"class_list":["post-1950","post","type-post","status-publish","format-standard","hentry","category-spring-cloud","tag-spring-cloud-gateway"],"_links":{"self":[{"href":"https:\/\/www.appblog.cn\/index.php\/wp-json\/wp\/v2\/posts\/1950","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=1950"}],"version-history":[{"count":0,"href":"https:\/\/www.appblog.cn\/index.php\/wp-json\/wp\/v2\/posts\/1950\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.appblog.cn\/index.php\/wp-json\/wp\/v2\/media?parent=1950"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.appblog.cn\/index.php\/wp-json\/wp\/v2\/categories?post=1950"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.appblog.cn\/index.php\/wp-json\/wp\/v2\/tags?post=1950"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}