A, requirements,

We cannot access the customer’s database through the account password, but we can access the interface provided by the customer to obtain data. Therefore, we can request the interface to parse the returned JSON data, and then we can get the data we need.

  1. You can configure required information in a configuration file to enhance flexibility

  2. The requested data is updated if it exists in the database and inserted if it does not

  3. If a certain data in JSON does not exist, the data is automatically completed, set to null, and stored in the database

  4. If the returned data has a timestamp, it needs to be parsed and saved to the database

  5. Use HTTP connection pooling to reduce the overhead of frequent disconnection

Second, the train of thought

Kit:

Httpclient: sends HTTP requests

JsonPath: Used to parse strings

HttpClient tool use

Introducing Maven dependencies:

<! -- httpClient -->
<dependency>
	<groupId>org.apache.httpcomponents</groupId>
	<artifactId>httpclient</artifactId>
	<version>4.5.5</version>
</dependency>
Copy the code

Add a new HttpClientUtil utility class to use:

public class HttpClientUtil {
    
    private static CloseableHttpClient httpClient = null;

    public static void init(a) {
        Create a connection pool manager. By default, this implementation will create no more than 2 concurrent connections for a given route, and no more than 20 connections in total
        PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(60000./ / 1.1
                TimeUnit.MILLISECONDS);// By default, the Tomcat server maintains the connection for 60 seconds. If the connection exceeds 60 seconds, the tomcat server closes the connection to the client
        connectionManager.setMaxTotal(1000);// Set the connector to support up to 1000 links at a time
        connectionManager.setDefaultMaxPerRoute(50);// Set a maximum of 50 links per route. Note that routing refers to IP+PORT or domain name

        //2. Create an HttpClient object
        httpClient = HttpClients.custom()
                .setConnectionManager(connectionManager)
                .disableAutomaticRetries()
                .build();
    }


    public static String doGet(String url) {
        // Initialize the connection pool
        if(httpClient == null)
            init();
        String httpResponse = null;
        // Create a Get request
        HttpGet httpGet = new HttpGet(url);
        // Response model
        CloseableHttpResponse response = null;
        try {
            // Configuration information
            RequestConfig requestConfig = RequestConfig.custom()
                    // Set connection timeout in milliseconds
                    .setConnectTimeout(5000)
                    // Set the request timeout in milliseconds
                    .setConnectionRequestTimeout(5000)
                    // Timeout of socket read and write (milliseconds)
                    .setSocketTimeout(5000)
                    // Sets whether redirection is allowed (default: true)
                    .setRedirectsEnabled(true).build();

            // Apply the above configuration information to the Get request
            httpGet.setConfig(requestConfig);


            // The client executes (sends) the Get request
            response = httpClient.execute(httpGet);
            // Get the response entity from the response model
            HttpEntity responseEntity = response.getEntity();
            // Get the request body
            httpResponse = EntityUtils.toString(responseEntity,"UTF-8");
        } catch (ParseException | IOException e) {
            e.printStackTrace();
        } finally {
            // Reclaim the connection
            if (null! = response) {try {
                    EntityUtils.consume(response.getEntity());
                } catch(IOException e) { e.printStackTrace(); }}}return httpResponse;
    }

    public static String doPost(String url) throws IOException {
        if(httpClient == null)
            init();
        String httpResponse = null;
        // Get the Http client (you need a browser; Note: Actually HttpClient is not the same as browser.
        CloseableHttpClient httpClient = HttpClientBuilder.create().build();

        // Create a Post request
        HttpPost httpPost = new HttpPost(url);
        // Response model
        CloseableHttpResponse response = null;
        HttpEntity responseEntity = null;
        try {
            // The client executes (sends) the Post request

            response = httpClient.execute(httpPost);
            // Get the response entity from the response model
            responseEntity = response.getEntity();
            if(responseEntity ! =null) {
                // Get the request body
                httpResponse = EntityUtils.toString(responseEntity,"UTF-8"); }}catch (ParseException | IOException e) {
            e.printStackTrace();
        } finally {
            // Reclaim the connection
            if (null! = response) {try {
                    EntityUtils.consume(response.getEntity());
                } catch(IOException e) { e.printStackTrace(); }}}return httpResponse;
    }

    public static String doPostWithEntity(String url,String json) throws IOException {
        if(httpClient == null)
            init();
        String httpResponse = null;
        // Get the Http client (you need a browser; Note: Actually HttpClient is not the same as browser.
        CloseableHttpClient httpClient = HttpClientBuilder.create().build();

        // Create a Post request
        HttpPost httpPost = new HttpPost(url);
        // Response model
        CloseableHttpResponse response = null;
        HttpEntity responseEntity = null;
        try {
            StringEntity requestEntity = new StringEntity(json,"utf-8");
            requestEntity.setContentEncoding("UTF-8");
            httpPost.setHeader("Content-type"."application/json");
            httpPost.setEntity(requestEntity);

            // The client executes (sends) the Post request
            response = httpClient.execute(httpPost);
            // Get the response entity from the response model
            responseEntity = response.getEntity();
            if(responseEntity ! =null) {
                // Get the request body
                httpResponse = EntityUtils.toString(responseEntity,"UTF-8"); }}catch (ParseException | IOException e) {
            e.printStackTrace();
        } finally {
            // Reclaim the connection
            if (null! = response) {try {
                    EntityUtils.consume(response.getEntity());
                } catch(IOException e) { e.printStackTrace(); }}}returnhttpResponse; }}Copy the code

4. Use JsonPath tool

The introduction of maven:

<! -- jsonPath json extraction tool -->
<dependency>
	<groupId>com.jayway.jsonpath</groupId>
	<artifactId>json-path</artifactId>
	<version>2.4.0</version>
</dependency>
Copy the code

JsonToSqlUtill: JsonToSqlUtill: JsonToSqlUtill: JsonToSqlUtill


@Component
public class JsonToSqlUtill {
    @Value("${JsonToSqlUtill.field}")
    private Set<Object> field;

    private static Set<Object> s_field;

    @Value("${JsonToSqlUtill.timeField}")
    private Set<Object> timeField;

    private static Set<Object> s_timeField;

    @Value("${JsonToSqlUtill.timeFieldType}")
    private boolean timeFieldType;

    private static boolean s_timeFieldType;

    @Value("${JsonToSqlUtill.tableName}")
    private String tableName;

    private static String s_tableName;

    @Value("${JsonToSqlUtill.dataPath}")
    private String dataPath;

    private static String s_dataPath;

    @Value("${JsonToSqlUtill.url}")
    private String url;

    private static String s_url;

    @PostConstruct
    public void getField(a){
        s_field = this.field;
    }

    @PostConstruct
    public void getTimeField(a){
        s_timeField = this.timeField;
    }

    @PostConstruct
    public void getTimeFieldType(a){
        s_timeFieldType = this.timeFieldType;
    }

    @PostConstruct
    public void getTableName(a){
        s_tableName = this.tableName;
    }
    @PostConstruct
    public void getDataPath(a){
        s_dataPath = this.dataPath;
    }
    @PostConstruct
    public void getUrl(a){
        s_url = this.url;
    }

    public static String getSqlWithJson(String json) throws IOException {
        // Get the data returned by httpClient
        String httpResponse = doPostWithEntity(s_url,json);
        return getSql(httpResponse);
    }

    public static String getSqlWithGet(a) throws IOException {
        // Get the data returned by httpClient
        String httpResponse = doGet(s_url);
        return getSql(httpResponse);
    }

    public static String getSqlWithPost(a) throws IOException {
        // Get the data returned by httpClient
        String httpResponse = doPost(s_url);
        return getSql(httpResponse);
    }

    private static String getSql(String httpResponse) throws IOException {
        List<Object> list = new ArrayList<>();
        // Get the data needed in json
        List<HashMap> data = JsonPath.read( httpResponse,"$."+ s_dataPath +"[*]");


        //ON DUPLICATE KEY UPDATE (SQL: UPDATE if database exists, insert if database does not exist
        StringBuilder updateFields = new StringBuilder();
        for (Object key : s_field){
            // Add the fields to the list to make it easier for the following fields to be nullated
            list.add(key.toString());
            updateFields.append(key).append("=").append("values(").append(key).append("),");
        }
        // Remove the last comma
        updateFields.delete(updateFields.length()-1,updateFields.length()).append(";");

        // Get the field to insert in values
        // index is used to determine if a field in the map has a null value
        int index = 0;
        StringBuilder values = new StringBuilder();
        for (Map map : data){
            // Set the loop to 0 each time
            index = 0;
            values.append("(");
            for (Object key : map.keySet()){
                // If the index is not correct, the missing segment is automatically filled with null values until the index is equal
                while(list.indexOf(key) ! = index){ values.append("'").append("null").append("'").append(",");
                    index++;
                }
                // If the value is time, format conversion is required
                if (s_timeField.contains(key)){
                    if (s_timeFieldType){
                        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
                        String date = df.format(new Date(Long.parseLong((map.get(key).toString()))));
                        // Write time, skip subsequent execution steps
                        values.append("'").append(date).append("'").append(",");
                    }else {
                        values.append("'").append(map.get(key).toString()).append("'").append(",");
                    }
                    index++;
                    continue;
                }

                // Add the value to values
                values.append("'").append(map.get(key)).append("'").append(",");
                // Go to the next index
                index++;
            }
            // Finally fill the missing data segment with null values
            while(list.size() ! = index){// If time is missing, take the default time
                if (s_timeField.contains(list.get(index))){
                    // Write time, skip subsequent execution steps
                    values.append("'").append("0000-00 00 -").append("'").append(",");
                    index++;
                    continue;
                }
                values.append("'").append("null").append("'").append(",");
                index++;
            }
            // Remove the comma from the last field
            values.delete(values.length()-1,values.length());
            values.append("),");
        }
        // Remove the generated comma at the end
        values.delete(values.length()-1,values.length());

        // The final splice
        StringBuilder finallySql = new StringBuilder();
        finallySql.append("INSERT INTO ").append(s_tableName).append("(").append(s_field.toString().substring(1,s_field.toString().length()-1)).append(")").
                append("VALUES").append(values).append("ON DUPLICATE KEY UPDATE ").append(updateFields);

        returnString.valueOf(finallySql); }}Copy the code

Use: Start with the configuration file (yML format used here)

JsonToSqlUtill:
  field: id,name,description,pictureUrl,url,createDate # Data field names in return order
  timeField: createDate,updateDate # format is the field of time (English, separated)
  timeFieldType: true # Whether to use timestamp format
  tableName: data SQL > alter table name
    Example: {"store": {" data": [{"category": "reference", "price": 8.95}, path: store.data
  dataPath: data.data
  url: https://xxxxxxxxxx #url
Copy the code

Once the files are configured, there are three methods that you can use directly

GetSqlWithGet () : Make a Get request directly using the URL of the configuration file and return a complete SQL

GetSqlWithPost () : Makes a Post request directly using the URL of the configuration file and returns a complete SQL

GetSqlWithJson (JSON) : Request with a JSON string and return a complete SQL

        // Request through Get
        String Sql = getSqlWithGet();
        System.out.println(Sql);

        // Request through Post
        String Sql = getSqlWithPost();
        System.out.println(Sql);

        // Request via Post+Json parameters
        String Sql = getSqlWithJson(json);
        System.out.println(Sql);

Copy the code

As shown in the figure:

Create the corresponding data table in the database, and finally use their own way to execute this SECTION of SQL.

Delete the primary key id of the database, store it as a list, and then parse the ID with the JSON obtained from HTTP as a list. Use removeAll between the two lists to obtain the id that has been deleted