使用Java通过Nginx反向代理服务器操作PostgreSQL数据库

最近在做一个项目,需要讲Android App和服务器上的PostgreSQL进行连接,但是Android Studio不能够直接通过JDBC进行连接,所以选择通过Nginx作为中间服务器对PostgreSQL进行操作,这篇文章紧接Nginx以及ngx_postgres安装以及配置

更新:后来发现使用nginx的效果并不好,更好的方法可能是使用PostgREST+Nginx反向代理对数据库进行操作,因为PostgREST直接提供了处理PostgreSQL数据库的RESTful接口,更加方便。详细教程可以去网上搜一搜。

我们的数据库中的数据主要存储的是Android app中的使用信息,定义app_usage_info表拥有以下字段

1
2
3
4
5
day date,
app_name text,
package_name text,
app_usage_time interval,
app_usage_count integer

首先,我们需要对nginx的配置文件进行配置,nginx的配置文件一般是在nginx的安装目录下的/conf/nginx.conf,比如在我的系统中就是/opt/nginx/conf/nginx.conf,打开配置文件我们就可以进行配置。Nginx的配置文件结构可以在Nginx 配置详解 | 菜鸟教程 (runoob.com)中简单学习一下。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
worker_processes 1;

events {
worker_connections 1024;
}


http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;

upstream database {
postgres_server 172.29.118.77 dbname=postgres user=postgres password=511668;
}

server {

charset utf-8;
listen 80;
server_name localhost;

location /insert {
postgres_pass database;
rds_json on;
postgres_query "insert into app_usage_info VALUES ('$arg_day', '$arg_app_name', '$arg_package_name', '$arg_time', '$arg_count');
postgres_rewrite no_changes 410;
}

location /query-all {
postgres_pass database;
rds_json on;
postgres_query "select * from app_usage_info";
}

location /query-day {
postgres_pass database;
rds_json on;

postgres_query HEAD GET "SELECT * FROM app_usage_info WHERE day='$arg_day'";
postgres_rewrite HEAD GET no_rows 410;


}

location / {
root html;
index index.html index.htm;
}
# 错误页面
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}

这是我的一个简单的配置,为了对数据库做不同的处理,我定义了insert页面,query-day(查询指定天数)页面,query-all(查询整个表)页面。这里面还涉及到关于Nginx中变量的使用,可以看这一篇Nginx变量使用方法详解 - 简书 (jianshu.com),讲得还是非常的清楚的。这里我使用了$arg_XXX变量,就可以直接通过http网址进行参数的设定了,也就很方便的可以通过JAVA的Http请求执行对应的数据库操作。

下面是用来实现Http请求的Java类,参考这篇文章实现JAVA发送HTTP请求的四种方式总结_java_脚本之家 (jb51.net)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
public class HttpUtils {

private String uri;

public HttpUtils(String hostname) {
uri = hostname;
}

public static void sendRequest(String url, Callback callback) {
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder().url(url).build();
client.newCall(request).enqueue(callback);
}


public static String sendRequestWithHttpURL(String urlParam,String requestType) {

HttpURLConnection con = null;

BufferedReader buffer = null;
StringBuffer resultBuffer = null;

try {
URL url = new URL(urlParam);
//得到连接对象
con = (HttpURLConnection) url.openConnection();
//设置请求类型
con.setRequestMethod(requestType);
//设置请求需要返回的数据类型和字符集类型
con.setRequestProperty("Content-Type", "application/json;charset=utf-8");
//允许写出
con.setDoOutput(true);
//允许读入
con.setDoInput(true);
//不使用缓存
con.setUseCaches(false);
//得到响应码
int responseCode = con.getResponseCode();
System.out.println(urlParam + ": " + responseCode);
if(responseCode == HttpURLConnection.HTTP_OK){
//得到响应流
InputStream inputStream = con.getInputStream();
//将响应流转换成字符串
resultBuffer = new StringBuffer();
String line;
buffer = new BufferedReader(new InputStreamReader(inputStream, "utf-8"));
while ((line = buffer.readLine()) != null) {
resultBuffer.append(line);
}
return resultBuffer.toString();
}
} catch (ProtocolException e) {
e.printStackTrace();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return "Failed!";
}

public void insert(String day, String app_name, String package_name, String interval, int count) {
String responseData = sendRequestWithHttpURL(uri+"/insert?"+"day="+day+"&app_name="+app_name+"&package_name="+package_name+"&time="+interval+"&count="+count, "POST");
System.out.println(responseData);
}

public void queryAll() {
String responseData = sendRequestWithHttpURL(uri+"/query-all", "GET");
System.out.println(responseData);
}

public void queryDay(String day) {
String responseData = sendRequestWithHttpURL(uri+"/query-day?day="+day, "GET");
System.out.println(responseData);
}
}

main函数所在类

1
2
3
4
5
6
7
8
public static void main(String[] args) {
String url ="your host address";
HttpUtils http = new HttpUtils(url);
http.queryAll();
http.queryDay("2021-07-07");
http.insert("2021-07-08", "华为桌面", "com.huawei.android.launcher",
"00:18:41", 63);
}

程序运行结果

image-20210708152524585

参考资料

[1] Nginx 配置详解 | 菜鸟教程 (runoob.com)

[2] Nginx变量使用方法详解 - 简书 (jianshu.com)

[3] JAVA发送HTTP请求的四种方式总结_java_脚本之家 (jb51.net)