spring对接InfluxDB(三)--数据获取之多条语句

Influx提供多条语句的同时查询(Multiple queries):

curl -G 'http://localhost:8086/query?pretty=true' --data-urlencode "db=mydb" --data-urlencode "q=SELECT \"value\" FROM \"cpu_load_short\" WHERE \"region\"='us-west';SELECT count(\"value\") FROM \"cpu_load_short\" WHERE \"region\"='us-west'"

就是说我一次请求可以同时执行多条sql,官网明确说明只要每个sql中间用分号(;)隔开就好。
获取信息的代码:

public void getTest(){
        RestTemplate restTemplate=new RestTemplate();

        String url="http://localhost:8086/query?pretty=true&q=select * from pkk;select count(*) from pkk&db=mydb";

        String points=restTemplate.getForObject(url,String.class);

        System.out.println("points:"+points);
    }

返回的信息:

points:{
    "results": [
        {
            "statement_id": 0,
            "series": [
                {
                    "name": "pkk",
                    "columns": [
                        "time",
                        "address",
                        "age",
                        "name"
                    ],
                    "values": [
                        [
                            "2017-07-28T01:32:03.378554614Z",
                            "shanghai",
                            21,
                            "pangkun1"
                        ],
                        [
                            "2017-07-28T01:32:03.378554614Z",
                            "shanghai",
                            23,
                            "pangkun3"
                        ],
                        [
                            "2017-07-28T01:32:03.378554614Z",
                            "shanghai",
                            22,
                            "pangkun2"
                        ]
                    ]
                }
            ]
        }
    ]
}

这里可以看出上边返回的只有第一条查询语句的结果,第二条根本就没有执行,或者执行后根本就没返回。

同样的sql在InfluxDB的web端可以正常返回数据,但是放到代码中就是查询不出结果。

所以我判断问题应该是出在两条sql的连接处–分号,仔细查看curl中的url是说要encode的,现在看下web端执行成功的url:

http://localhost:8086/query?q=select+*+from+pkk%3Bselect+count(*)+from+pkk&db=mydb

通过抓包,或者直接在浏览器中执行我代码中的URL:

http://localhost:8086/query?pretty=true&q=select%20*%20from%20pkk;select%20count(*)%20from%20pkk&db=mydb

仔细对比可以发现自己执行的url中的分号(;)并没有没加密处理,在网上搜索可以看到其对应的编码为%3B。

所以,现在的问题是sping的resttemplate没有对分号进行处理。解决方案,重写resttemplate的url处理部分。
重写之后的代码:

package org.springframework.web.client;

import org.springframework.http.HttpMethod;
import org.springframework.http.client.ClientHttpRequest;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.util.Assert;
import org.springframework.web.util.UriTemplateHandler;

import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;

/**
 * Created by pangkunkun on 2017/7/21.
 */
public class DisplayRestTemplate extends RestTemplate{

    @Override
    public  T getForObject(String url, Class responseType, Object... uriVariables) throws RestClientException {
        RequestCallback requestCallback = acceptHeaderRequestCallback(responseType);
        HttpMessageConverterExtractor responseExtractor =
                new HttpMessageConverterExtractor(responseType, getMessageConverters(), logger);
        return execute(url, HttpMethod.GET, requestCallback, responseExtractor, uriVariables);
    }

    // general execution

    @Override
    public  T execute(String url, HttpMethod method, RequestCallback requestCallback,
                         ResponseExtractor responseExtractor, Object... uriVariables) throws RestClientException {

        URI expanded = getUriTemplateHandler().expand(url, uriVariables);

        try {
            //对处理完之后的url进行二次处理,;替换为%3B
            expanded=new URI(expanded.toString().replace(";","%3B"));
        }catch (Exception e){
            e.printStackTrace();
        }
        return doExecute(expanded, method, requestCallback, responseExtractor);
    }

    /**
     * Execute the given method on the provided URI.
     * 

The {@link ClientHttpRequest} is processed using the {@link RequestCallback}; * the response with the {@link ResponseExtractor}. * @param url the fully-expanded URL to connect to * @param method the HTTP method to execute (GET, POST, etc.) * @param requestCallback object that prepares the request (can be {@code null}) * @param responseExtractor object that extracts the return value from the response (can be {@code null}) * @return an arbitrary object, as returned by the {@link ResponseExtractor} */ @Override protected T doExecute(URI url, HttpMethod method, RequestCallback requestCallback, ResponseExtractor responseExtractor) throws RestClientException { Assert.notNull(url, "'url' must not be null"); Assert.notNull(method, "'method' must not be null"); ClientHttpResponse response = null; try { ClientHttpRequest request = createRequest(url, method); if (requestCallback != null) { requestCallback.doWithRequest(request); } response = request.execute(); handleResponse(url, method, response); if (responseExtractor != null) { return responseExtractor.extractData(response); } else { return null; } } catch (IOException ex) { String resource = url.toString(); String query = url.getRawQuery(); resource = (query != null ? resource.substring(0, resource.indexOf(query) - 1) : resource); throw new ResourceAccessException("I/O error on " + method.name() + " request for \"" + resource + "\": " + ex.getMessage(), ex); } finally { if (response != null) { response.close(); } } } }

修改获取的代码:

    public void getTest(){
        DisplayRestTemplaterestTemplate=new DisplayRestTemplate();

        String url="http://localhost:8086/query?pretty=true&q=select * from pkk;select count(*) from pkk&db=mydb";

        String points=restTemplate.getForObject(url,String.class);

        System.out.println("points:"+points);
    }

修改后的结果:

points:{
    "results": [
        {
            "statement_id": 0,
            "series": [
                {
                    "name": "pkk",
                    "columns": [
                        "time",
                        "address",
                        "age",
                        "name"
                    ],
                    "values": [
                        [
                            "2017-07-28T01:32:03.378554614Z",
                            "shanghai",
                            21,
                            "pangkun1"
                        ],
                        [
                            "2017-07-28T01:32:03.378554614Z",
                            "shanghai",
                            23,
                            "pangkun3"
                        ],
                        [
                            "2017-07-28T01:32:03.378554614Z",
                            "shanghai",
                            22,
                            "pangkun2"
                        ]
                    ]
                }
            ]
        },
        {
            "statement_id": 1,
            "series": [
                {
                    "name": "pkk",
                    "columns": [
                        "time",
                        "count_age"
                    ],
                    "values": [
                        [
                            "1970-01-01T00:00:00Z",
                            3
                        ]
                    ]
                }
            ]
        }
    ]
}

现在可以看到结果是OK的,正常返回了两个查询语句的信息。

现在再来看看两个表之间的一次查询:
再创建另外一个measurement:

public void writePoints(){

        String url="http://localhost:8086/write?db=mydb";

        String pointValue="pangkunkun,name=pangkun4,address=shanghai age=24\n" +
                "pangkunkun,name=pangkun5,address=shanghai age=25\n" +
                "pangkunkun,name=pangkun6,address=shanghai age=26";

        RestTemplate restTemplate=new RestTemplate();

        restTemplate.postForObject(url,pointValue,Object.class);
    }

从两个表中获取数据

    public void getTest(){
        DisplayRestTemplaterestTemplate=new DisplayRestTemplate();

        String url="http://localhost:8086/query?pretty=true&q=select * from pkk;select * from pangkunkun&db=mydb";

        String points=restTemplate.getForObject(url,String.class);

        System.out.println("points:"+points);
    }

返回结果:

points:{
    "results": [
        {
            "statement_id": 0,
            "series": [
                {
                    "name": "pkk",
                    "columns": [
                        "time",
                        "address",
                        "age",
                        "name"
                    ],
                    "values": [
                        [
                            "2017-07-28T01:32:03.378554614Z",
                            "shanghai",
                            21,
                            "pangkun1"
                        ],
                        [
                            "2017-07-28T01:32:03.378554614Z",
                            "shanghai",
                            23,
                            "pangkun3"
                        ],
                        [
                            "2017-07-28T01:32:03.378554614Z",
                            "shanghai",
                            22,
                            "pangkun2"
                        ]
                    ]
                }
            ]
        },
        {
            "statement_id": 1,
            "series": [
                {
                    "name": "pangkunkun",
                    "columns": [
                        "time",
                        "address",
                        "age",
                        "name"
                    ],
                    "values": [
                        [
                            "2017-07-28T05:39:53.081302642Z",
                            "shanghai",
                            24,
                            "pangkun4"
                        ],
                        [
                            "2017-07-28T05:39:53.081302642Z",
                            "shanghai",
                            26,
                            "pangkun6"
                        ],
                        [
                            "2017-07-28T05:39:53.081302642Z",
                            "shanghai",
                            25,
                            "pangkun5"
                        ]
                    ]
                }
            ]
        }
    ]
}

如果是习惯hibernate或者JPA的朋友应该会知道,一般的表联合查询的时候很多都是放到一起:

    public void getTest(){
        DisplayRestTemplaterestTemplate=new DisplayRestTemplate();

        String url="http://localhost:8086/query?pretty=true&q=select * from pkk,pangkunkun&db=mydb";

        String points=restTemplate.getForObject(url,String.class);

        System.out.println("points:"+points);
    }

返回结果:

points:{
    "results": [
        {
            "statement_id": 0,
            "series": [
                {
                    "name": "pangkunkun",
                    "columns": [
                        "time",
                        "address",
                        "age",
                        "name"
                    ],
                    "values": [
                        [
                            "2017-07-28T05:39:53.081302642Z",
                            "shanghai",
                            24,
                            "pangkun4"
                        ],
                        [
                            "2017-07-28T05:39:53.081302642Z",
                            "shanghai",
                            26,
                            "pangkun6"
                        ],
                        [
                            "2017-07-28T05:39:53.081302642Z",
                            "shanghai",
                            25,
                            "pangkun5"
                        ]
                    ]
                },
                {
                    "name": "pkk",
                    "columns": [
                        "time",
                        "address",
                        "age",
                        "name"
                    ],
                    "values": [
                        [
                            "2017-07-28T01:32:03.378554614Z",
                            "shanghai",
                            21,
                            "pangkun1"
                        ],
                        [
                            "2017-07-28T01:32:03.378554614Z",
                            "shanghai",
                            23,
                            "pangkun3"
                        ],
                        [
                            "2017-07-28T01:32:03.378554614Z",
                            "shanghai",
                            22,
                            "pangkun2"
                        ]
                    ]
                }
            ]
        }
    ]
}

这个返回的数据是完整的,但是仔细对比会发现跟上边的json结构不同。
第一种两条语句用分号(;)隔开的返回的是两个或多个series(此处只是两条查询,所以是两个),而且statement_id是0和1两个。
第二种两张表之间用逗号隔开的,只返回一个series,所有的结果都在这个series中,而且statement_id的值只有1.

这种情况很好理解,第一种用分号隔开的是两条查询语句,第二种用逗号隔开两张表是一条语句。第二种不需要重写RestTemplate。具体的两种方式的用途也不太相同,各位可以思考下。

你可能感兴趣的:(InfluxDB,Spring,SpringBoot)