【REST2SQL】04 REST2SQL第一版Oracle版实现

【REST2SQL】01RDB关系型数据库REST初设计
【REST2SQL】02 GO连接Oracle数据库
【REST2SQL】03 GO读取JSON文件

REST2SQL的第一个版本,只支持Oracle数据库,以后会逐步加入其它数据看的支持。

项目文件组织如下:
在这里插入图片描述

1 REST2SQL为项目主目录

主控main()函数、请求日志函数、请求响应函数、请求参数返回函数在此目录。

1.1 import引用包

import (
	"encoding/json"
	"fmt"

	"io"
	"log"
	"net/http"
	"rest2sql/config" //配置信息在config.json文件
	do "rest2sql/dothing"
	"strings"
	"time"
)

1.2 请求信息放在Map里

// 请求信息map
var (
	req   map[string]interface{} = make(map[string]interface{}) //请求参数
	count int                    = 0                            //请求计数器
)

1.3 main() 主控函数

// main()
func main() {
	// 打印配置信息
	fmt.Println("config:", config.Conf)

	//响应所有的请求
	http.HandleFunc("/", handler)
	// http.HandleFunc("/REST", restHandler)
	// http.HandleFunc("/SQL", sqlHandler)

	println("Starting Http Server at", config.Conf.HostPort, "\n")

	//启动监听和服务
	//log.Println(http.ListenAndServe(Conf.HostPort, RequestLogger(http.DefaultServeMux)))
	http.ListenAndServe(config.Conf.HostPort, RequestLogger(http.DefaultServeMux))
	//log.Println(err)

	//测试可以用这个
	//curl -X POST -d "{\"gpdm\":600800}" -H "Content-Type:application/json" http://localhost:8080/rest/blma

}

1.4 请求日志函数

// 请求日志
func RequestLogger(targetMux http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		count++
		start := time.Now()
		targetMux.ServeHTTP(w, r)
		log.Printf(
			"(%v)\t%s\t\t%s\t\t%s\t\t%v",
			count,
			r.Method,
			r.RemoteAddr,
			r.RequestURI,
			time.Since(start),
		)
	})
}

1.5 请求响应函数

// handler
func handler(w http.ResponseWriter, r *http.Request) {
	// 1请求主机Host
	req["Host"] = r.Host

	// 2请求路径Path
	req["Path"] = r.URL.Path
	path := strings.Split(r.URL.Path, "/")
	if len(path) < 3 {
		w.Write([]byte("400 Bad Request错误请求。请尝试/rest/xxx or /sql/xxx"))
		return
	}

	//fmt.Println(path)
	// 3 请求类型REST or SQL
	rors := strings.ToUpper(fmt.Sprint(path[1]))
	// 支持的请求类型
	if !(rors == "REST" || rors == "SQL") {
		w.Write([]byte("400 Bad Request错误请求。请尝试/REST/xxx or /SQL/xxx"))
		return
	}
	req["RESTorSQL"] = rors //请求类型SQL or REST

	// 4 资源名 ResName
	req["ResName"] = path[2] //资源名,表名ResName

	// 5请求方法Method
	req["Method"] = r.Method

	// 6请求头Content-Type
	req["Content-Type"] = r.Header.Get("Content-Type")

	// 7请求数据Data
	data, err := io.ReadAll(r.Body)

	if err != nil {
		w.Write([]byte(err.Error()))
		return
	}
	defer r.Body.Close()
	//反序列化
	if len(data) > 0 {
		var idata interface{}
		//fmt.Println("data:", data)
		err = json.Unmarshal(data, &idata)
		if err != nil {
			w.Write([]byte(err.Error()))
			return
		}
		//fmt.Println("idata:", idata)
		req["Data"] = idata
	} else {
		req["Data"] = ""
	}

	// 8 请求参数
	query := r.URL.Query()
	req["Where"] = query.Get("where")
	req["OrderBy"] = query.Get("orderby")

	//返回http请求参数
	resReturn(w, req)

	//根据请求参数执行不同的操作
	do.DoThing(w, req)
}

1.6 请求参数返回函数

// http请求主要参数直接返回
func resReturn(w http.ResponseWriter, req map[string]interface{}) {
	w.Write([]byte("{\"Request\":"))
	str, err := json.MarshalIndent(req, "", "   ")
	if err != nil {
		w.Write([]byte(err.Error()))
	}
	//fmt.Println(str)
	w.Write(str)
	w.Write([]byte(","))
}

2 config配置文件读取子目录

2.1 包名改为 config

//全局变量包

package config

import (
	"encoding/json"
	"io/ioutil"
	"log"
	"strings"
)

var Conf config //全局变量

func init() {
	Conf = getConfig()
}

// 配置结构体
type config struct {
	DBType     string //数据库类型 :oracle、mysql等
	ConnString string `json:"connString"`
	HostPort   string `json:"hostPort"`
	REST       string `json:"REST"`
	SQL        string `json:"SQL"`
}

// 取配置信息
func getConfig() config {
	bytes, err := ioutil.ReadFile("config.json")
	if err != nil {
		log.Println("读取json文件失败:", err)
		panic(nil)
	}
	conf := &config{}
	err = json.Unmarshal(bytes, conf)
	if err != nil {
		log.Println("json解析失败", err)
		panic(nil)
	}
	//数据库类型为数据库的第一部分
	end := strings.Index(conf.ConnString, ":/")
	if end < 0 {
		log.Println("连接字符串设置有误。")
		panic(nil)
	}
	conf.DBType = conf.ConnString[0:end]
	// fmt.Println(conf)
	// fmt.Println("connString:", conf.ConnString)
	// fmt.Println("hostPort:", conf.HostPort)
	return *conf
}

2.2 doc.go 文件设置

// config project doc.go

/*
config document
*/
package config

3 dboracle子目录,Oracle数据库操作

3.1 包名:dboracle

// gooracle project main.go
package dboracle

import (
	"database/sql/driver"
	"encoding/json"

	"io"
	"log"
	"rest2sql/config"

	go_ora "github.com/sijms/go-ora/v2" // 1 go get github.com/sijms/go-ora/v2
)

// Oracle连接字符串
//var ConnStr string = "oracle://blma:5217@127.0.0.1:1521/CQYH"

var ConnString string = config.Conf.ConnString

/*
func main() {
	var (
		sqls   string //sql语句
		result string //sql执行后返回的结果
	)

	// select查询数据
	sqls = "select sysdate from dual"
	result = selectData(sqls)
	fmt.Println(result)

	// delete 删除数据
	sqls = "delete from atop where p_id = -5"
	result = deleteData(sqls)
	fmt.Println(result)

	// update 更新数据
	sqls = "update atop set f_dm = '005217' where p_id = -5217"
	result = updateData(sqls)
	fmt.Println(result)

	// insert 插入一行数据
	sqls = "insert into atop (p_id) values (FLOOR(DBMS_RANDOM.value(0, 100)))"
	result = insertData(sqls)
	fmt.Println(result)
}
*/

// 连接Oracle数据库
func connDB(connStr string) *go_ora.Connection {
	//创建连接
	DB, err := go_ora.NewConnection(connStr)
	dieOnError("Can't open the driver:", err)
	//打开连接
	err = DB.Open()
	dieOnError("Can't open the connection:", err)
	return DB
}

// delete
func DeleteData(deleteSql string) string {
	result, _ := execSQL(deleteSql)
	rows, err := result.RowsAffected()
	dieOnError("Can't delete", err)
	ret := map[string]int{
		"Delete rowsAffected": int(rows),
	}
	jsonBytes, err := json.MarshalIndent(ret, "", "   ")
	dieOnError("map 转 json失败:", err)
	return string(jsonBytes)
}

// update
func UpdateData(updateSql string) string {
	result, _ := execSQL(updateSql)
	rows, err := result.RowsAffected()
	dieOnError("Can't update", err)
	ret := map[string]int{
		"Update rowsAffected": int(rows),
	}
	jsonBytes, err := json.Marshal(ret)
	dieOnError("map 转 json失败:", err)
	return string(jsonBytes)
}

// insert
func InsertData(insertSql string) string {
	result, _ := execSQL(insertSql)
	rows, err := result.RowsAffected()
	dieOnError("Can't insert", err)
	ret := map[string]int{
		"Insert rowsAffected": int(rows),
	}
	jsonBytes, err := json.MarshalIndent(ret, "", "   ")
	dieOnError("map 转 json失败:", err)
	return string(jsonBytes)
}

// 执行SQL, execute stmt (INSERT, UPDATE, DELETE, DML, PLSQL) and return driver.Result object
func execSQL(sqls string) (result driver.Result, err error) {
	//连接数据库
	DB := connDB(ConnString)
	//延迟关闭连接
	defer DB.Close()

	//准备sql语句
	stmt := go_ora.NewStmt(sqls, DB)
	//延迟关闭SQL
	defer stmt.Close()

	//执行SQL, execute stmt (INSERT, UPDATE, DELETE, DML, PLSQL) and return driver.Result object
	result, err = stmt.Exec(nil)
	dieOnError("Can't execSql() ", err)

	return result, err
}

// select查询,结果为json
func SelectData(sqls string) string {
	//连接数据库
	DB := connDB(ConnString)
	//延迟关闭连接
	defer DB.Close()

	//准备sql语句
	stmt := go_ora.NewStmt(sqls, DB)
	//延迟关闭SQL
	defer stmt.Close()

	rows, err := stmt.Query(nil)
	dieOnError("Can't query", err)

	defer rows.Close()

	//fmt.Println(rows)

	columns := rows.Columns()
	//fmt.Println("columns:", columns)
	values := make([]driver.Value, len(columns))
	var dataset []map[string]interface{} //元素为map的切片
	//Header(columns)
	for {
		err = rows.Next(values)
		if err != nil {
			break
		}
		//fmt.Println("values:", values)
		row1 := record(columns, values)
		dataset = append(dataset, row1)

	}
	if err != io.EOF {
		dieOnError("Can't Next", err)
	}

	//切片转json
	jsonBytes, err := json.MarshalIndent(dataset, "", "   ")
	dieOnError("slice 转 json失败:", err)
	//fmt.Println(string(jsonBytes))
	return string(jsonBytes)
}

// 发生错误退出1
func dieOnError(msg string, err error) {
	if err != nil {
		log.Println(msg, err)
		//os.Exit(1)
	}
}

// func Header(columns []string) {

// }

// 一行记录加入 map
func record(columns []string, values []driver.Value) map[string]interface{} {
	mc := make(map[string]interface{}) //一行记录信息放入 map
	for i, c := range values {
		//fmt.Printf("\"%s\":%v,", columns[i], c)
		mc[columns[i]] = c
	}
	//fmt.Println(mc)

	return mc //返回一行记录的信息map
}

/* 查询表的主键方法
select * from user_cons_columns where table_name = 'ATOP'
and constraint_name = (
select constraint_name from user_constraints
where table_name = 'ATOP' and constraint_type = 'P')
order by position
*/

// func returnErr(err error) error {
// 	if err != nil {
// 		return err
// 	}
// 	return nil
// }

// // 7调用存储过程
// func callStoredProcedure() error {
// 	var (
// 		id  int
// 		msg string = strings.Repeat(" ", 2000) //先赋值内容
// 	)
// 	//执行存储过程,
// 	_, err := db.Exec(`BEGIN ora_test2_pro(:1, :2 ); END;`,
// 		id,
// 		sql.Out{Dest: &msg},
// 	)
// 	if err != nil {
// 		return err
// 	}
// 	//输出结果
// 	fmt.Println(msg)
// 	return nil
// }

// // 8.调用函数
// func callFunction() error {
// 	var (
// 		id  int
// 		msg string = strings.Repeat(" ", 2000) //先赋值内容
// 	)
// 	//执行存储过程,
// 	_, err := db.Exec(`BEGIN :1 := ora_test2_func(:2 ); END;`,
// 		sql.Out{Dest: &msg},
// 		id,
// 	)
// 	if err != nil {
// 		return err
// 	}
// 	//输出结果
// 	fmt.Println(msg)
// 	return nil
// }

3.2 doc.go

// gooracle project doc.go

/*
gooracle document
*/
package dboracle

4 dothing主要逻辑处理

4.1 包名dothing

// dothing project dothing.go
package dothing

import (
	"encoding/json"
	"fmt"
	"net/http"
	"rest2sql/config"
	"rest2sql/dboracle"
	"strings"
)

// 当前连接的数据库类型oracle
var (
	DBType string = config.Conf.DBType //数据库类型
	REST   string = config.Conf.REST   //支持的REST:GET,POST,PUT,DELETE
	SQL    string = config.Conf.SQL    //支持的SQL:SELECT,INSERT,UPDATE,DELETE
)

// 根据请求类型参数执行不同的操作 
func DoThing(w http.ResponseWriter, req map[string]interface{}) {
	w.Write([]byte("\n"))
	//请求类型 REST or SQL
	switch req["RESTorSQL"] {
	case "REST":
		//REST请求方法过滤
		sMethod := strings.ToUpper(req["Method"].(string))
		if !strings.Contains(REST, sMethod) {
			w.Write([]byte("!!!不准许的REST请求,检查配置文件config.json的REST项。"))
			return
		}
		//执行REST请求
		doREST(w, req)
	case "SQL":
		//SQL过滤
		resSQL := req["ResName"].(string)
		sqlToUpper := strings.ToUpper(resSQL)
		sql6 := sqlToUpper[:6]
		if !strings.Contains(SQL, sql6) {
			w.Write([]byte("!!!不准许的SQL请求,检查配置文件config.json的SQL项。"))
			return
		}
		//执行SQL
		doSQL(w, req)
	}
}

// 根据请求参数执行不同的操作
func doREST(w http.ResponseWriter, req map[string]interface{}) {
	//w.Write([]byte("\ndoREST()"))
	//资源名
	resName := req["ResName"].(string)

	// 检查是否有效资源
	if !isRes(resName) {
		w.Write([]byte("\nerror:无效资源" + resName))
		return
	} else {
		//w.Write([]byte("\nresName:" + resName))
	}

	// 查询条件检查
	var qry map[string]string = make(map[string]string)
	qry["ResName"] = resName
	qry["Where"] = req["Where"].(string)
	qry["OrderBy"] = req["OrderBy"].(string)

	// 有效资源,再看请求方法Get、Post、Put、Delete
	sMethod := strings.ToUpper(req["Method"].(string))
	switch sMethod {
	case "GET":
		getAll(w, qry)

	case "POST":
		var iData interface{}
		iData = req["Data"]
		postAdd(w, resName, iData)

	case "PUT":
		var iData interface{}
		iData = req["Data"]
		putUpdate(w, qry, iData)

	case "DELETE":
		deleteDel(w, qry)
	}
}

// 根据请求参数执行不同的操作 
func doSQL(w http.ResponseWriter, req map[string]interface{}) {
	//w.Write([]byte("\ndoSQL()\n"))
	w.Write([]byte("\"Response\":"))
	//资源名sql语句
	resSQL := req["ResName"].(string)
	fmt.Println("SQL://", resSQL)
	sqlToUpper := strings.ToUpper(resSQL)
	sql6 := sqlToUpper[:6]
	var result string
	switch sql6 {
	case "SELECT":
		result = dboracle.SelectData(resSQL)
	case "INSERT":
		result = dboracle.InsertData(resSQL)
	case "UPDATE":
		result = dboracle.UpdateData(resSQL)
	case "DELETE":
		result = dboracle.DeleteData(resSQL)
	default:
		// 过滤sql ,只能执行 SELECT INSERT UPDATE DELETE
		result = "\"只能执行 SELECT INSERT UPDATE DELETE\""
	}
	fmt.Println("SQL://", resSQL)
	w.Write([]byte(result))
	w.Write([]byte("}"))
}

// 检查资源是否存在 /
func isRes(resName string) bool {
	resname := strings.ToUpper(resName)
	var selectSQL string
	switch DBType {
	case "oracle":
		{
			//表和视图
			selectSQL = "select object_name from user_objects where object_type in ('TABLE','VIEW') and object_name = '" + resname + "'"
		}
	case "":
		{
		}

	}

	//执行数据库查询
	result := dboracle.SelectData(selectSQL)
	//检查数据库是否有此表
	if strings.Contains(result, resname) {
		return true
	} else {
		return false
	}
}

// GET all //
func getAll(w http.ResponseWriter, qry map[string]string) {
	//w.Write([]byte("\nGET ALL"))
	w.Write([]byte("\"Response\":"))
	selectSQL := "select * from " + qry["ResName"]
	if len(qry["Where"]) > 0 {
		//fmt.Println("where ", qry["Where"])
		selectSQL += " where " + qry["Where"] + " and rownum < 52"
	}
	if len(qry["OrderBy"]) > 0 {
		//fmt.Println("OrderBy ", qry["OrderBy"])
		selectSQL += " order by " + qry["OrderBy"]
	}

	//执行 sql并返回 json 结果
	fmt.Println("REST://", selectSQL)
	result := dboracle.SelectData(selectSQL)
	w.Write([]byte(result))
	w.Write([]byte("}"))
}

// GET 1
func get1(w http.ResponseWriter) {
	w.Write([]byte("\nGET ONE"))
}

// POST /
func postAdd(w http.ResponseWriter, resName string, iData interface{}) {
	//curl "http://localhost:5217/rest/atop" --data "{\"p_id\":190,\"s_mc\":\"龙\"}" -X POST
	//w.Write([]byte("\nPOST ADD"))
	w.Write([]byte("\"Response\":{\"Data\":"))
	//fmt.Println("iData:", iData)
	str, err := json.MarshalIndent(iData, "", "   ")
	if err != nil {
		w.Write([]byte(err.Error()))
	}
	//fmt.Println("str", str)
	w.Write(str)
	w.Write([]byte(",\"Row\":"))

	var mapData map[string]interface{}
	err = json.Unmarshal(str, &mapData)
	if err != nil {
		w.Write([]byte(err.Error()))
	}
	//fmt.Println(mapData)
	var keys, values string
	for k, v := range mapData {
		//fmt.Printf("%s %v %T\n", k, v, v)
		keys += k + ","
		if typeofVar(v) == "string" {
			values += "'" + v.(string) + "',"
		}

		if typeofVar(v) == "float64" || typeofVar(v) == "int" {
			values += fmt.Sprintf("%f", v) + ","
		}

	}

	keys = strings.Trim(keys, ",")
	values = strings.Trim(values, ",")
	//fmt.Println(keys, values)
	insertSQL := "insert into " + resName + "(" + keys + ")" + " values( " + values + " )"
	//执行 insertSQL 并返回 json 结果
	fmt.Println("REST://:", insertSQL)
	result := dboracle.InsertData(insertSQL)
	w.Write([]byte(result))
	w.Write([]byte("}}"))

}

// 数据类型断言 
func typeofVar(variable interface{}) string {
	switch variable.(type) {
	case string:
		return "string"
	case int:
		return "int"
	case float32:
		return "float32"
	case float64:
		return "float64"
	case bool:
		return "boolean"
	case []string:
		return "[]string"
	default:
		return "unknown"
	}
}

// PUT
func putUpdate(w http.ResponseWriter, qry map[string]string, iData interface{}) {
	//w.Write([]byte("\nPUT UPDATE"))
	w.Write([]byte("\"Response\":{\"Data\":"))

	str, err := json.MarshalIndent(iData, "", "   ")
	if err != nil {
		w.Write([]byte(err.Error()))
	}
	//fmt.Println("str", str)
	w.Write(str)
	w.Write([]byte(",\"Row\":"))

	var mapData map[string]interface{}
	err = json.Unmarshal(str, &mapData)
	if err != nil {
		w.Write([]byte(err.Error()))
	}
	//fmt.Println(mapData)
	var sets string
	for k, v := range mapData {
		//fmt.Printf("%s %v %T\n", k, v, v)
		sets += k + "="
		if typeofVar(v) == "string" {
			sets += "'" + v.(string) + "',"
		}

		if typeofVar(v) == "float64" || typeofVar(v) == "int" {
			sets += fmt.Sprintf("%f", v) + ","
		}

	}

	sets = strings.Trim(sets, ",")

	updateSQL := "update " + qry["ResName"] + "  set " + sets + " where " + qry["Where"]
	//执行 insertSQL 并返回 json 结果
	fmt.Println("REST://", updateSQL)
	result := dboracle.UpdateData(updateSQL)

	w.Write([]byte(result))
	w.Write([]byte("}}"))
}

// DELETE
func deleteDel(w http.ResponseWriter, qry map[string]string) {
	// 查询条件在URL/?后面
	//w.Write([]byte("\nDELETE DEL"))
	w.Write([]byte("\"Response\":"))
	deleteSQL := "delete from " + qry["ResName"]
	if len(qry["Where"]) > 0 {
		//fmt.Println("where ", qry["Where"])
		deleteSQL += " where " + qry["Where"] + " and rownum < 52"
	}

	//执行 sql并返回 json 结果
	fmt.Println("REST://", deleteSQL)
	result := dboracle.DeleteData(deleteSQL)
	w.Write([]byte(result))
	w.Write([]byte("}"))
}

4.2 doc.go

// Dothing project doc.go

/*
dothing document
*/
package dothing

5 部分运行效果图

5.1 启动REST2SQL.exe服务

编译后的rest2sql.exe为14M,启动后的窗口为:
在这里插入图片描述

5.2 浏览器操作演示效果

5.2.1 浏览器REST之GET请求

在这里插入图片描述

5.2.2 浏览器SQL之Select

在这里插入图片描述

5.2.3 执行RESR或SQL请求后,服务窗口返回操作日志

在这里插入图片描述

5.3 详细的操作说明参阅

【REST2SQL】01RDB关系型数据库REST初设计

需要运行程序的可以在评论区留言。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/301332.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

005-Zynq基操之如何去玩EMIO接口(走过路过千万不要错过)

文章目录 前言一、EMIO是啥含义二、两种EMIO的使用1.PS端外设引出来的EMIO2.正常的EMIO口3.PS端驱动源码 总结 前言 今天分享这个主要原因是&#xff0c;把最基础的EMIO接口弄清楚咋操作的&#xff0c;咱们就可以做一些由PS端控制PL端的器件小功能&#xff0c;最常见的就是我们…

SqueezeNet:通过紧凑架构彻底改变深度学习

一、介绍 在深度学习领域&#xff0c;对效率和性能的追求往往会带来创新的架构。SqueezeNet 是神经网络设计的一项突破&#xff0c;体现了这种追求。本文深入研究了 SqueezeNet 的复杂性&#xff0c;探讨其独特的架构、设计背后的基本原理、应用及其对深度学习领域的影响。 在创…

vue项目中的录屏插件recordrtc且带声音

vue项目中的录屏插件recordrtc且带声音 一、效果图二、安装插件三、直接上代码 一、效果图 其中窗口录屏不带声音&#xff0c;chrome标签和整个屏幕的录屏是带声音的 二、安装插件 npm i recordrtc 三、直接上代码 <template><div class"record-page">…

Qt优秀开源项目之二十:RedPanda-CPP(小熊猫C++)

小熊猫C是跨平台、轻量易用的开源C/C集成开发环境。 官网&#xff1a;http://royqh.net/redpandacpp github&#xff1a;https://github.com/royqh1979/RedPanda-CPP 小熊猫C&#xff08;原名小熊猫Dev-C 7)是基于Qt开发的Dev-C替代版本。和经典的Dev-C 5.11、新的Embarcadero …

Minio部署在服务器上,分享图片等文件提示,签名不对

问题描述: 上传没问题 下载没问题 就是分享有问题,签名有问题 找了很多解释,什么nginx代理问题啊,什么端口问题啊 什么防火墙问题啊 都是扯淡,一点用没有 最后发现,我的分享链接是127.0.0.1的地址,并不是我的服务器本机的地址 我访问图片都是要把ip改了再去访问,但是一开始并没…

C#,数值计算,求平方根之巴比伦算法(Babylonian algorithm)的源代码

平方根的巴比伦算法。 1 巴比伦算法介绍一 巴比伦算法可能算是最早的用于计算$sqrt{S}$的算法之一&#xff0c;因为其可以用牛顿法导出&#xff0c;因此在很多地方也被成为牛顿法。其核心思想在于为了计算x的平方根&#xff0c;可以从某个任意的猜测值g开始计算。在真实的运算…

【docker】centos 使用 Nexus Repository 搭建私有仓库

Nexus Repository 是一种流行的软件仓库管理工具&#xff0c;它可以帮助您搭建私有仓库&#xff0c;以便在内部网络或私有云环境中存储、管理和分发各种软件包和组件。 它常被用于搭建Maven的镜像仓库。本文演示如何用Nexus Repository搭建docker 私有仓库。 使用Nexus Repos…

【AIGC工具】我找到了使用大模型问答的最短路径!

大家好&#xff0c;我是豆小匠~ 好久没介绍提高效率的工具啦&#xff0c;这次来介绍一个UTools的骚操作&#xff0c;可以极速打开LLM进行提问&#xff01; 完成后的效果是&#xff1a; 快捷键调出输入框&#xff1b;2. 输入问题&#xff1b;3. 选择模型&#xff1b;4. 回车提…

基于单片机设计的智慧农业大棚检测系统

一、设计目标 本项目基于单片机设计一个智慧农业大棚检测系统&#xff0c;以提供实时监测和管理大棚环境的关键参数。系统支持环境温度、湿度检测&#xff0c;光照强度检测&#xff0c;并能根据预设的阀值进行报警提示。为了实现数据的显示和管理&#xff0c;该系统还利用Qt开…

【数据结构】队列

简单不先于复杂&#xff0c;而是在复杂之后。 文章目录 1. 队列1.1 队列的概念及结构1.2 队列的实现 2.栈和队列面试题3.概念选择题 1. 队列 1.1 队列的概念及结构 队列&#xff1a;只允许在一端进行插入数据操作&#xff0c;在另一端进行删除数据操作的特殊线性表&#xff0c…

Kibana错误【Kibana server is not ready yet】

docker部署kibana成功后&#xff0c;访问http://localhost:5601 ,页面返回“Kibana server is not ready yet” 运行 docker logs kibana 后提示 该错误提示为kibana的版本和es的版本不一致&#xff0c;将两个组件的版本更新一致即可 还有另外一种错误 在kibana的kibana.yml配…

本地部署 gemini-openai-proxy,使用 Google Gemini 实现 Openai API

本地部署 gemini-openai-proxy&#xff0c;使用Google Gemini 实现 Openai API 0. 背景1. 申请 Google Gemini API key2. (Optional)Google Gemini 模型说明3. gemini-openai-proxy Github 地址4. 本地部署 gemini-openai-proxy5. 测试 0. 背景 使用 Google Gemini 实现 Opena…

在pycharm中执行 os.makedirs 提示用户名或密码不正确

问题&#xff1a;在pycharm中运行脚本&#xff0c;在 \10.0.21.249\share 共享目录下创建目录提示错误 发现&#xff1a;手动在该目录下创建目录没有问题。 解决方法&#xff1a; 切换到cmd 命令行运行该脚本成功创建 猜测&#xff1a;感觉应该是pycharm中使用的用户名和密码存…

算法的复杂度分析

[王有志](https://www.yuque.com/wangyouzhi-u3woi/dfhnl0/hqrch62un0cc9sp2?singleDoc# 《&#x1f525;快来关注我》)&#xff0c;一个分享硬核Java技术的互金摸鱼侠加入Java人的提桶跑路群&#xff1a;[共同富裕的Java人](https://www.yuque.com/wangyouzhi-u3woi/dfhnl0/n…

C++CLI——4数组、泛型、集合与属性

CCLI——4数组、泛型、集合与属性 C数组 在c中&#xff0c;数组的大小必须在编译时确定&#xff0c;并且将数组传递给函数时&#xff0c;传递的只是数组起始地址&#xff0c;所以要想办法连同数组大小一同传递给函数。 int arr[4] { 1,2,3,4 }; int arr1[] { 1,2,3,4 }; i…

平仓是交易者功力的终极考验

这里的平仓主要针对盈利头寸的平仓&#xff0c;讨论了在什么情况下、如何平仓以使盈利最大化的问题。对于亏损头寸&#xff0c;反而更容易处理&#xff0c;只需在止损位将其平掉即可。开仓时需要考虑风险&#xff0c;平仓时则关注利润。所有风险都源于开仓&#xff0c;而所有利…

java火车查询管理系统Myeclipse开发mysql数据库web结构java编程计算机网页项目

一、源码特点 java Web火车查询管理系统是一套完善的java web信息管理系统&#xff0c;对理解JSP java编程开发语言有帮助&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S模式开发。开发环境为 TOMCAT7.0,Myeclipse8.5开发&#xff0c;数据库为Mysql…

Basal前端梳理

Basalt前端逻辑梳理 TBB安装参考 https://zhuanlan.zhihu.com/p/480823197 代码注释参考 https://blog.csdn.net/qq_39266065/article/details/106175701#t7 光流追踪参考 https://blog.csdn.net/weixin_41738773/article/details/130282527 VI Odometry KLT tracking 原理 …

【面试高频算法解析】算法练习2 回溯(Backtracking)

前言 本专栏旨在通过分类学习算法&#xff0c;使您能够牢固掌握不同算法的理论要点。通过策略性地练习精选的经典题目&#xff0c;帮助您深度理解每种算法&#xff0c;避免出现刷了很多算法题&#xff0c;还是一知半解的状态 专栏导航 二分查找回溯&#xff08;Backtracking&…

C++ 学习笔记之运算符重载+案例

目录 一、C 运算符重载 二、定义一个成员函数或全局函数 三、计算时间 1.计算时间差 2.时间加减 四、一个运算符重载实例 一、C 运算符重载 是一种特性&#xff0c;它允许程序员重新定义已有的运算符的行为&#xff0c;以适应自定义类型的操作。通过运算符重载&#xff0…