【技术应用】java基于UNIX域套接字unix domain socket连接postgresql数据库

  • 一、前言
  • 二、postgresql套接字文件
  • 三、PostgreSQL 配置文件pg_hba.conf
  • 四、准备工作
  • 五、jdbc基于UDS连接postgresql数据库
  • 六、springboot+mybatis基于UDS使用示例


一、前言

之前分享了java基于unix domain socket实现mysql的jdbc连接,由于平时使用postgresql数据库比较多,今天总结一下java基于unix domain socket实现postgresql数据库的jdbc连接mybatis的使用;

二、postgresql套接字文件

postgresql数据库的套接字文件是.s.PGSQL.nnnn,其中nnnn是服务器的端口号,如下图:

java 连接pg_sql


通过unix套接字实现连接服务端:

java 连接pg_java_02

关于postgresql套接字文件连接介绍几个概念:

unix_socket_directories (string)

  1. 指定服务器用于监听来自客户端应用的连接的 Unix 域套接字目录。通过列出用逗号分隔的多个目录可以建立多个套接字。项之间的空白被忽略,如果你需要在名字中包括空白或逗号,在目录名周围放上双引号。一个空值指定在任何
    Unix 域套接字上都不监听,在这种情况中只能使用 TCP/IP 套接字来连接到服务器。默认值通常是/tmp,但是在编译时可以被改变。这个参数只能在服务器启动时设置。
    这个值通过修改postgresql.conf文件修改失败,只有通过alter system set
    unix_socket_directories='/opt/pg12';命令修改才生效,不知道是我改的不对还是就应该这样设置。
  2. 除了套接字文件本身(名为.s.PGSQL.nnnn,其中nnnn是服务器的端口号),一个名
    为.s.PGSQL.nnnn.lock的普通文件会在每一个unix_socket_directories目录中被创建。任何一个都不应该被手工移除。
  3. Windows下没有 Unix 域套接字,因此这个参数与 Windows 无关

unix_socket_group (string)

  1. 设置 Unix域套接字的所属组(套接字的所属用户总是启动服务器的用户)。可以与选项unix_socket_permissions一起用于对Unix域连接进行访问控制。默认是一个空字符串,表示服务器用户的默认组。这个参数只能在服务器启动时设置。

unix_socket_permissions (integer)

  1. 设置 Unix 域套接字的访问权限。Unix 域套接字使用普通的 Unix
    文件系统权限集。这个参数值应该是数字的形式,也就是系统调用chmodumask接受的
    形式(如果使用自定义的八进制格式,数字必须以一个0(零)开头)。
  2. 默认的权限是0777,意思是任何人都可以连接。合理的候选是0770(只有用户和同组的人可以访问,
    又见unix_socket_group)和0700(只有用户自己可以访问)(请注意,对于 Unix
    域套接字,只有写权限有麻烦,因此没有对读取和执行权限的设置和收回)。
  3. 依然只能使用alter system set unix_socket_permissions = '0700';修改才生效;

三、PostgreSQL 配置文件pg_hba.conf

文件路径:/usr/data/postgresql/pg_hba.conf

java 连接pg_sql_03


属性说明:

1、TYPE 定义了多种连接PostgreSQL的方式,一般分为:

  • local 使用本地unix套接字
  • host 使用TCP/IP连接(包括SSL和非SSL),host结合IPv4地址/结合IPv6地址
  • hostssl 只能使用SSL TCP/IP连接
  • hostnossl 不能使用SSL TCP/IP连接

2、METHOD 为身份验证模式一般分为:ident、trust、md5、password、peer、reject。其中ident和peer模式仅适用于LinuxUnixMax不适用于Windows

  • trust:该模式可以不用密码直接连接数据库,不安全
  • md5:该模式很常用,要求连接发起者携带用md5算法加密的密码
  • password:该模式是使用明文密码进行身份验证,也不安全,不推荐
  • ident:该模式下系统会将请求发起者的操作系统用户映射为PostgesSQL数据库内部用户,并以该内部用户的权限登录,且此时无需提供登录密码。操作系统用户与数据库内部用户之间的映射关系会记录在pg_ident.conf文件中。
  • peer:该模式使用连接发起端的操作系统名进行身份验证。仅限于Linux、BSD、Mac OS
    X和Solaris
    ,并且仅可用于本地服务器发起的连接。
  • reject:该模式表示拒绝所有请求。

四、准备工作

1、设置pom.xml文件

<dependency>
			<groupId>org.postgresql</groupId>
			<artifactId>postgresql</artifactId>
			<version>42.5.0</version>
		</dependency>
		
		<dependency>
			<groupId>com.alibaba</groupId>
			<artifactId>druid-spring-boot-starter</artifactId>
			<version>1.1.21</version>
		</dependency>

		<!--MyBatis整合SpringBoot框架的起步依赖-->
		<dependency>
			<groupId>org.mybatis.spring.boot</groupId>
			<artifactId>mybatis-spring-boot-starter</artifactId>
			<version>2.2.1</version>
		</dependency>

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-aop</artifactId>
		</dependency>

2、创建数据库表

DROP TABLE IF EXISTS "public"."student";
CREATE TABLE "public"."student" (
  "id" int4 NOT NULL,
  "name" varchar(255) COLLATE "pg_catalog"."default",
  "sex" varchar(255) COLLATE "pg_catalog"."default",
  "pwd" varchar(255) COLLATE "pg_catalog"."default",
  "email" varchar(255) COLLATE "pg_catalog"."default"
)
;

-- ----------------------------
-- Primary Key structure for table student
-- ----------------------------
ALTER TABLE "public"."student" ADD CONSTRAINT "student_pkey" PRIMARY KEY ("id");

五、jdbc基于UDS连接postgresql数据库

**1、jdbc操作类MysqlDemo **

package com.sk.jdbc;

import java.sql.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;

public class MysqlDemo {

    public static Connection getConn02() throws Exception{
        //加载驱动
        Class.forName("org.postgresql.Driver");
        String url="jdbc:postgresql://localhost/test";
        String user="postgres";
        String password="xxxxxx";//写自己之前设置的

        //建立连接
        Properties info = new Properties();
        info.setProperty("socketFactory","org.newsclub.net.unix.AFUNIXSocketFactory$FactoryArg");
        info.setProperty("user",user);
        info.setProperty("password",password);
        info.setProperty("socketFactoryArg","/run/postgresql/.s.PGSQL.5432");
        info.setProperty("sslMode","prefer");

        Connection conn= DriverManager.getConnection(url,info);
        return conn;
    }

    public static List<String> run() throws Exception{
        Connection conn = getConn02();
        Statement stmt = conn.createStatement();
        String sql = "select * from student";
        ResultSet rs = stmt.executeQuery(sql);
        //处理结果集
        List<String> res = new ArrayList<>();
        while(rs.next()) {
            String str = rs.getString("name");
            res.add(str);
        }
        rs.close();
        System.out.println("结果集关闭成功!");
        stmt.close();
        System.out.println("语句通道关闭成功!");
        conn.close();
        System.out.println("关闭连接成功!");

        //遍历输出
        if(res!=null){
            for(String out:res) {
                System.out.println(out);
            }
        }
        return res;
    }
}

2、业务类

package com.controller;

import com.bean.Student;
import com.mapper.StudentMapper;
import com.sk.jdbc.MysqlDemo;
import lombok.extern.log4j.Log4j2;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.sql.SQLException;
import java.util.List;

@Log4j2
@RestController
public class TestAction {

    @Resource
    private StudentMapper studentMapper;

    /**
     * 验证jdbc调用
     * @return
     */
    @GetMapping("/test/local")
    private Object get(){
        try {
            return MysqlDemo.run();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
}

请求结果:

java 连接pg_postgresql_04

六、springboot+mybatis基于UDS使用示例

1、自定义MyDataSource类

package com.config;


import com.sk.jdbc.MysqlDemo;

import javax.sql.DataSource;
import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.SQLFeatureNotSupportedException;
import java.util.logging.Logger;

public class MyDataSource implements DataSource {

    @Override
    public Connection getConnection() {
        try {
            return MysqlDemo.getConn02();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    @Override
    public Connection getConnection(String username, String password) {
        try {
            return MysqlDemo.getConn02();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    @Override
    public <T> T unwrap(Class<T> iface) throws SQLException {
        return null;
    }

    @Override
    public boolean isWrapperFor(Class<?> iface) throws SQLException {
        return false;
    }

    @Override
    public PrintWriter getLogWriter() throws SQLException {
        return null;
    }

    @Override
    public void setLogWriter(PrintWriter out) throws SQLException {

    }

    @Override
    public void setLoginTimeout(int seconds) throws SQLException {

    }

    @Override
    public int getLoginTimeout() throws SQLException {
        return 0;
    }

    @Override
    public Logger getParentLogger() throws SQLFeatureNotSupportedException {
        return null;
    }
}

2、DruidConfig类

package com.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import javax.sql.DataSource;

@Configuration
public class DruidConfig {

    @Bean
    public DataSource druid(){
        return new MyDataSource();
    }

}

3、dao层StudentMapper

package com.mapper;

import com.bean.Student;
import org.apache.ibatis.annotations.*;
import org.springframework.stereotype.Repository;

import java.util.List;
import java.util.Map;

@Mapper
@Repository
public interface StudentMapper {

    @Select("select * from student")
    List<Student> selectAll();

    @Select("select * from student where id = #{id}")
    Student selectById(@Param("id") int id);

    @Select("select * from student where name = #{name}")
    Map<String, Object> selectByName1(@Param("name") String name);

    @Select("select * from student where name = #{name}")
    Student selectByName2(@Param("name") String name);

    @Select("select * from student where name = #{name} and pwd = #{pwd}")
    Student selectByNameAndPwd(String name, String pwd);

    @Delete("delete from student where id = #{id}")
    boolean deleteById(int id);

    @Insert("insert into student values (null,#{name},#{sex},#{pwd},#{email})")
    boolean insertUser(String name, String sex, String pwd, String email);

    @Update("update student set name =  #{name} where id = #{id}")
    boolean updateById(String name, int id);

}

4、业务类

package com.controller;

import com.bean.Student;
import com.mapper.StudentMapper;
import com.sk.jdbc.MysqlDemo;
import lombok.extern.log4j.Log4j2;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.sql.SQLException;
import java.util.List;

@Log4j2
@RestController
public class TestAction {

    @Resource
    private StudentMapper studentMapper;

    /**
     * 验证
     * @return
     */
    @GetMapping("/test")
    private Object get2(){
        List<Student> studentList = studentMapper.selectAll();
        log.info(studentList);
        return studentList;
    }
}

5、bean类Student

package com.bean;

import lombok.Builder;
import lombok.Data;

@Data
@Builder
public class Student {

    private Integer id;
    private String name;
    private String sex;
    private String pwd;
    private String email;

    public Student() { }

    public Student(Integer id, String name, String sex, String pwd, String email) {
        this.id = id;
        this.name = name;
        this.sex = sex;
        this.pwd = pwd;
        this.email = email;
    }
}

请求结果:

java 连接pg_java 连接pg_05