# dapr服务调用 + 请求MySQL

## 计划：一个 client，一个 service，数据库Mysql

(1)java-service 接收请求，并操作mysql,返回结果；

(2)config 操作mysql，返回结果；

在Client 里请求访问Service

String resultUrl = "http://121.43.155.15:" + httpPort + "/v1.0/invoke/java-service/method/save";

httpPort：sideCar 的端口

 

```
package dapr.com.client;
import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
public class DaprClientApplication {
    private final static String saveBodyTmpl="{\"content\": \"%s\"}";
    public static void main(String[] args) throws InterruptedException {
        Thread sendThread = new Thread(new Runnable() {
            public void run() {
                int i=0;
                while(!Thread.interrupted()){
                    try {
                        Thread.sleep(10000);
                        i++;
                        String str = "第"+ i +"个意见~~~";
                        // 客户端将要存储的信息发送
                        String body=String.format(saveBodyTmpl,str);
                        save(body);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }
        });
        sendThread.start();
        Thread.sleep(5*60*60*1000);
    }
    
    /**
     * 新增信息
     * @param body
     * @throws IOException
     */
    private static void save(String body) throws IOException {
        sendRequest(body,"save");
    }
    
    /**
     * 发请求
     * @param body
     * @param mothed
     * @throws IOException
     */
    private static void sendRequest(String body, String mothed) throws IOException {
        String httpPort = System.getenv("DAPR_HTTP_PORT");
        if (httpPort == null) {
            httpPort = "3500";
        }
        String resultUrl = "http://121.43.155.15:" + httpPort + "/v1.0/invoke/java-service/method/" + mothed;
        URL url = new URL(resultUrl);
        HttpURLConnection connection = (HttpURLConnection) url.openConnection();
        connection.setRequestMethod("POST");
        connection.setRequestProperty("Content-Type", "application/json;charset=UTF-8");
        connection.setRequestProperty("Connection", "Keep-Alive");
        connection.setUseCaches(false);
        connection.setDoOutput(true);
        connection.setDoInput(true);
        System.out.println("request body:"+body);
        DataOutputStream out = new DataOutputStream(connection.getOutputStream());
        out.write(body.getBytes("UTF-8"));
        out.flush();
        out.close();
        connection.connect();
        BufferedReader bReader = new BufferedReader(new InputStreamReader(connection.getInputStream(), "UTF-8"));
        String line, resultStr = "";
        while (null != (line = bReader.readLine())) {
            resultStr += line;
        }
        System.out.println(resultStr);
        bReader.close();
    }
}
```

Service里接受请求: Client 访问 Service边车, 边车再把请求发送到服务端

 

```
    @PostMapping(path = "/save")
    public Mono<String> handleMethod(@RequestBody(required = false) byte[] body,
                                     @RequestHeader Map<String, String> headers) {
        return Mono.fromSupplier(() -> {
            try {
                
                String message = body == null ? "" : new String(body, StandardCharsets.UTF_8);
                Calendar utcNow = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
                String utcNowAsString = DATE_FORMAT.format(utcNow.getTime());
                String metadataString = headers == null ? "" : OBJECT_MAPPER.writeValueAsString(headers);
                // Handles the request by printing message.
                System.out.println("Server: " + message);
                System.out.println("@ " + utcNowAsString + " and metadata: " + metadataString);
                // 请求Mql
                save(message);
                return message + " received";
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        });
    }
```

 

```
    private void save(String body) throws IOException {
        // 提取参数
        JSONObject jsonObject = JSONObject.parseObject(body);
        String content = jsonObject.getString("content");
        System.out.println("Content: " + content);
        //拼接SQL
        String bodyTmpl = "{\"operation\": \"exec\",\"metadata\": {\"sql\": \"INSERT INTO feedback (content) VALUES (\\\"%s\\\")\" }}";
        String sql =String.format(bodyTmpl,content);
        // 请求mysql
        doPost(sql);
    }
```

发送POST请求 

```
   public static String doPost(String sql) throws IOException {
        String  httpPort = "3501";
        String resultUrl = "http://121.43.155.15:" + httpPort + "/v1.0/bindings/mysql-binding";
        // 通过httpclient发送post请求
        CloseableHttpClient httpclient = HttpClients.createDefault();
        HttpPost httpPost = new HttpPost(resultUrl);// 创建httpPost
        httpPost.setHeader("Accept", "application/json");
        httpPost.setHeader("Content-Type", "application/json");
        StringEntity entity = new StringEntity(sql, "utf-8");
        System.out.println("Sql: " + sql);
        httpPost.setEntity(entity);
        CloseableHttpResponse response = null;
        try {
            response = httpclient.execute(httpPost);
            StatusLine status = response.getStatusLine();
            int state = status.getStatusCode();
            if (state == HttpStatus.SC_OK) {
                HttpEntity responseEntity = response.getEntity();
                String respContent = EntityUtils.toString(responseEntity,"UTF-8");
                System.out.println("成功返回:" + state + "结果：" + respContent);
                return respContent;
            } else {
                System.out.println("请求返回:" + state + "(" + resultUrl + ")");
            }
        } finally {
            if (response != null) {
                try {
                    response.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            try {
                httpclient.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return null;
    }
```

配置文件：

```
apiVersion: dapr.io/v1alpha1
kind: Component
metadata:
  name: talents-database-mysql-binding
  namespace: default
spec:
  type: bindings.mysql
  version: v1
  metadata:
    - name: url # Required, define DB connection in DSN format
      value: "root:yf123321@tcp(192.168.1.62:10002)/yf_talent_repository"

      #最大空闲连接数。大于 0 的整数
      #"10"
      #N
    - name: maxIdleConns
      value: "100"

      #最大打开连接数。大于 0 的整数
      #"10"
      #N
    - name: maxOpenConns
      value: "500"

      #最大连接寿命。持续时间字符串
      #"12s"
      #N
    - name: connMaxLifetime
      value: "3600s"

      #最大连接空闲时间。持续时间字符串
      #"12s"
      #N
    - name: connMaxIdleTime
      value: "3600s"
```



```
cd /root/talents/
# 配置service请求
dapr run --app-id java-service --app-port 9100 --dapr-http-port 3500 -- java -jar ./java/service/dapr-java-service-exec.jar com.dapr.service.ServiceC -p 9100
# 配置mysql请求
dapr run --app-id config --components-path ./talents-component --dapr-http-port 3501
```

![](E:\JavaLearn\test\cyx\笔记\1635780583572-8cs.png)

请求返回：

select

![](E:\JavaLearn\test\cyx\笔记\select.png)

update/delete

![](E:\JavaLearn\test\cyx\笔记\delete.png)



## 优点：

服务减负：不再依靠sdk而是通过Restful

不需要在应用代码里引入 mysql 的 SDK，也不用关心实际存储使用是什么通信协议，应用代码里只需要使用原语和 dapr runtime 通信，通信的协议是简单的 Http 或者 gRPC，dapr runtime 去实现这些能力

异常恢复速度快

![](E:\JavaLearn\test\cyx\测试结果\mysql 混沌测试.png)

## 风险：

缺乏预处理机制，有sql注入的风险





资料：https://docs.dapr.io/zh-hans/reference/components-reference/supported-bindings/mysql/



JAVASDK: https://github.com/dapr/java-sdk





服务调用: 不同项目之间的调用可以用dapr
