C++ 网络编程项目fastDFS分布式文件系统(六)--qss样式表,项目文件的上传和下载。

news2024/11/23 11:42:53

目录

1 单例模式

2. 如何在单例类中存储数据?

3. QSS样式表

        3.1 选择器类型

3.2 QSS的使用步骤

 3.3 登录窗口设置

4. 客户端post方式上传数据

        4.1 常用的四种方式

5. 上传协议    


1 单例模式

#include<iostream>
#include<vector>
#include<mutex>
#include<thread>
#include<algorithm>
using namespace std;
 
//饿汉式
 
// class Singleton{
 
//     public:
//         static Singleton *GetInstance(){
//             return &m_instance;
//         }
 
//     private:
//         Singleton(){}
 
//         //c++ 98 防止拷贝
//         // Singleton(Singleton const &);
//         // Singleton& operator=(Singleton const &);
 
//         //c++ 11 防止拷贝
//         Singleton(Singleton const &)=delete;
//         Singleton& operator=(Singleton const &)=delete;
 
//         static Singleton m_instance;
 
// };
 
// Singleton Singleton::GetInstance();//在程序入口之前就完成初始化
 
//懒汉式
class Singleton{
 
    public:
        static Singleton *GetInstance(){
// 注意这里一定要使用Double-Check的方式加锁,才能保证效率和线程安全
            if(nullptr==m_pInstance){
                m_mtx.lock();
                if(nullptr==m_pInstance){
                    m_pInstance=new Singleton();
                }
                m_mtx.unlock();
 
            }
 
            return m_pInstance;
        }
 
        //实现一个内嵌的垃圾回收类
 
        class CGarbo{
 
            public:
                ~CGarbo(){
                    if(Singleton::m_pInstance){
 
                        delete Singleton::m_pInstance;
 
                    }
                }
 
        };
 
        static CGarbo Garbo;
 
    private:
    //构造函数私有
    Singleton(){}
 
    //防止拷贝
    Singleton(Singleton const &)=delete;
    Singleton &operator=( Singleton const&)=delete;
 
    static Singleton* m_pInstance;//单例对象指针
    static mutex m_mtx; //互斥锁
 
};
Singleton * Singleton::m_pInstance=nullptr;
Singleton::CGarbo Garbo;
mutex Singleton::m_mtx;
 
int main()
{
 
thread t1([]{cout<<(Singleton::GetInstance())<<endl;});
thread t2([]{cout<<(Singleton::GetInstance())<<endl;});
 
t1.join();
t2.join();
 
cout<<(Singleton::GetInstance())<<endl;
cout<<(Singleton::GetInstance())<<endl;
 
system("pause");
return 0;
}
 

        

2. 如何在单例类中存储数据?

        

// 实现了一个单例模式的类
// 存储用户名/密码/服务器的iP/端口
class Test
{
public:
static Test* getInstance()
{
return &m_test;
}
// 设置数据
void setUserName(QString name)
{
// 多线程-> 加锁
m_user = name;
// 解锁
}
// 获取数据
QString getUserName()
{
return m_user;
}
private:
Test();
Test(const Test& t);
// 静态变量使用之前必须初始化
// static Test* m_test;
static Test m_test;
// 定义变量 -> 属于唯一的单例对象
QString m_user;
QString m_passwd;
QString m_ip;
QString m_port;
QString m_token;
}
// Test* Test::m_test = new Test(); // 初始化
Test Test::m_test;
在客户端登录的时候 , 服务器回复给客户端的数据
        
// 成功
{
"code" : "000" ,
"token" : "xxx"
}
// 失败
{
"code" : "001" ,
"token" : "faild"
}
token -> 客户端成功连接了服务器 , 服务器针对于客户端的个人信息生成了一个唯一的身份标识
- 可以按照每个人的身份证号理解
- 服务器将这个 token 发送给客户端
- 客户端 token 的使用和保存 :
- 使用 : 登录成功之后 , 向服务器在发送任意请求都需要携带该 token
- 保存方式 : 放到单例对象中
- 服务器端的使用和保存 :
- 使用 : 接收客户端发送的 token , 和服务器端保存的 token 进行认证
- 认证成功 : 合法客户端 , 失败 : 客户端非法
- 保存 : 服务器需要保存所有客户端的 token
- 数据库中
- 配置文件 -> 效率低
- redis -> 效率最高
( 客户端信息 + 随机数 ) * des * md5 * base64

3. QSS样式表

        3.1 选择器类型

3.2 QSS的使用步骤

// QSS 是一个文件 , 样式表文件 (CSS 文件 )
// - Qt 样式表支持 css2.0, 1.0 所有的语法 , css3.0 部分样式在 qt 中不支持
// 如何使用
/*
1. 根据介绍的选择器对所有的控件样式设置 , 写入 qss 文件中
2. 在程序中读样式表文件 , 得到一个字符串 -> 样式字符串
3. 将读出的样式设置给 QT 的应用程序对象
4. qt 中有一个全局的应用程序指针 qApp
5. qApp->setStyleSheet(" 样式字符串 ");
6. QFile 读磁盘文件 , 磁盘文件的编码格式必须是 utf8
*/

 3.3 登录窗口设置

/* 登录窗口设置背景图片 */
/* 登录窗口所有控件设置字体 , 字体大小 */
/* 设置登录 / 注册 / 服务器设置窗口标题字体 , 字体大小 */
/* 设置 logo 显示的图片 */
/* 设置窗口标题字体 , 字体大小 , 加粗 */
/* 没有账号马上注册按钮 : 字体颜色和添加下划线 */
/* 登录 / 注册 /OK 按钮 : 字体颜色 , 宽度 , 高度 , 字体大小 , 显示图片 */
/* 标题栏按钮 : normal, hover, press 三种状态切换 */

/* 按钮的默认状态 */
QPushButton #loginBtn
{
color : white ;
width : 200 ;
height : 50 ;
font-size : 30px ;
border-image : url ( :/images/balckButton.png ); /* 默认显示的图片 */
}
/* 按钮的悬停状态 */
QPushButton #loginBtn : hover
{
border-image : url ( :/images/balckButton1.png ); /* 默认显示的图片 */
}
/* 按钮的按下状态 不是 css 中的标准状态 , qt 独有的 */
QPushButton #loginBtn : pressed
{
border-image : url ( :/images/balckButton2.png ); /* 默认显示的图片 */
}

4. 客户端post方式上传数据

        4.1 常用的四种方式

application/x-www-form-urlencoded
        
# 请求行
POST http: //www.example.com HTTP/1.1
# 请求头
Content-Type: application/x-www-form-urlencoded;charset=utf-8
# 空行
# 请求数据 ( 向服务器提交的数据 )
title=test&user=kevin&passwd=32222
application/json
        
POST http://www.example.com HTTP/1.1
Content-Type: application/json;charset=utf-8
{"title": "test","sub":[1,2,3]}

 text/xml

POST http://www.example.com HTTP/1.1
Content-Type: text/xml
<?xml version="1.0" encoding="utf8"?>
<methodcall>
<methodname color="red">examples.getStateName</methodname>
<params>
<value><i4>41</i4></value>
</params>
</methodcall>
multipart/form-data
  tool.oschina.net
        
POST http://www.example.com HTTP/1.1
Content-Type: multipart/form-data
# 发送的数据
------WebKitFormBoundaryPpL3BfPQ4cHShsBz \r\n
Content-Disposition: form-data; name="file"; filename="qw.png"; md5="xxxxxxxxxx"
Content-Type: image/png\r\n;
\r\n
............. 文件内容 ................
............. 文件内容 ................
------WebKitFormBoundaryPpL3BfPQ4cHShsBz
Content-Disposition: form-data; name="file"; filename="qw.png"; md5="xxxxxxxxxx"
Content-Type: image/png\r\n;
\r\n
............. 文件内容 ................
............. 文件内容 ................
------WebKitFormBoundaryPpL3BfPQ4cHShsBz--

5. 上传协议    

文件上传的一般步骤 :
尝试秒传 -> 文件并没上传
给服务器发送的不是文件内容 , 是文件的哈希值
在服务器端收到哈希值 , 查询数据库
查到了 -> 秒传成功
没查到 -> 秒传失败 , 需要进行一个真正的上传操作
进行真正的上传
需要的时间长
上传有文件内容 , 文件的哈希值
文件内容 -> 分布式文件系统
哈希值 -> 数据库
1. 秒传 
 客户端
# url
http: //127.0.0.1:80/md5
# post 数据格式
{
user:xxxx,
token:xxxx,
md5:xxx,
fileName: xxx
}

服务器 

location / md5
{
# 转发数据
fastcgi_pass localhost:10002;
include fastcgi.conf;
}

int main()
{
while(FCGI_Accept() >= 0)
{
// 1. 得到post数据的长度
char* length = getenv("content-length");
int len = atoi(length);
// 2. 根据len将数据读到内存中, json对象字符串
// 3. 解析json对象, user,md5, token, fileName
// 4. token认证 , 查询redis/数据库
// -- 成功: 继续后续操作, 失败, 返回, 给客户端一个结果
// 5. 打开数据库, 并查询md5是否存在
// -- 存在 {"code":"006"}
// -- 不存在 {"code":"007"}
}
}

 2. 上传

        客户端

       

# url
http://127.0.0.1:80/upload
# post数据格式
------WebKitFormBoundary88asdgewtgewx\r\n
Content-Disposition: form-data; user="mike"; filename="xxx.jpg"; md5="xxxx";
size=10240
Content-Type: image/jpg
真正的文件内容
------WebKitFormBoundary88asdgewtgewx--
Qt 中如何组织上述 post 数据块
        
// 组织数据块 - > QHttpPart
QHttpPart::QHttpPart();
// 设置数据头
void QHttpPart::setHeader(QNetworkRequest::KnownHeaders header, const QVariant
&value);
- header:
- QNetworkRequest::ContentDispositionHeader
- QNetworkRequest::ContentTypeHeader
- value:
"form-data; 自定义的数据, 格式 xxx=xxx, 中间以;间隔"
// 适合传递少量的数据
void QHttpPart::setBody(const QByteArray &body);
- body: 传递的数据串
// 传递大文件
void QHttpPart::setBodyDevice(QIODevice *device);
- 使用参数device, 打开一个磁盘文件
// QHttpMulitPart
QHttpMultiPart::QHttpMultiPart(ContentType contentType, QObject *parent =
Q_NULLPTR);
- 参数contentType: QHttpMultiPart::FormDataType
// 调用该函数会自动添加分界线 -> 使用频率高的函数
void QHttpMultiPart::append(const QHttpPart &httpPart);
// 查看添加的分界线的值
QByteArray QHttpMultiPart::boundary() const;
// 自己设置分界线, 一般不需要自己设置
void QHttpMultiPart::setBoundary(const QByteArray &boundary);
// 使用post方式发送数据
QNetworkReply *QNetworkAccessManager::post(const QNetworkRequest &request,
QHttpMultiPart *multiPart);
服务器
        
location /upload
{
# 转发数据
fastcgi_pass localhost:10003;
include fastcgi.conf;
}
// fastCGI程序
int main()
{
// 1. 获取数据长度 1024000
// 2. 循环读post数据内容
}

 服务器端fastCGI 部分 代码

        

 // 取出 Content-Disposition 中的键值对的值, 并得到文件内容, 并将内容写入文件
     int recv_save_file(char *user, char *filename, char *md5, long *p_size)
     {
         int ret = 0;
         char *file_buf = NULL;
         char *begin = NULL;
         char *p, *q, *k;
     
         char content_text[512] = {0}; //文件头部信息
         char boundary[512] = {0};     //分界线信息
     
         //==========> 开辟存放文件的 内存 <===========
         file_buf = (char *)malloc(4096);
         if (file_buf == NULL)
         {
             return -1;
         }
     
         //从标准输入(web服务器)读取内容
         int len = fread(file_buf, 1, 4096, stdin); 
         if(len == 0)
         {
             ret = -1;
             free(file_buf);
             return ret;
         }
     
         //===========> 开始处理前端发送过来的post数据格式 <============
         begin = file_buf;    //内存起点
         p = begin;
     
         /*
            ------WebKitFormBoundary88asdgewtgewx\r\n
            Content-Disposition: form-data; user="mike"; filename="xxx.jpg"; md5="xxxx"; size=10240\r\n
            Content-Type: application/octet-stream\r\n
            ------WebKitFormBoundary88asdgewtgewx--
         */
     
         //get boundary 得到分界线, ------WebKitFormBoundary88asdgewtgewx
         p = strstr(begin, "\r\n");
         if (p == NULL)
         {
             ret = -1;
             free(file_buf);
             return ret;
         }
     
         //拷贝分界线
         strncpy(boundary, begin, p-begin);
         boundary[p-begin] = '\0';   //字符串结束符
         p += 2; //\r\n
         //已经处理了p-begin的长度
         len -= (p-begin);
         //get content text head
         begin = p;
     
         //Content-Disposition: form-data; user="mike"; filename="xxx.jpg"; md5="xxxx"; size=10240\r\n
         p = strstr(begin, "\r\n");
         if(p == NULL)
         {
             ret = -1;
             free(file_buf);
             return ret;
         }
         strncpy(content_text, begin, p-begin);
         content_text[p-begin] = '\0';
     
         p += 2;//\r\n
         len -= (p-begin);
     
         //========================================获取文件上传者
         //Content-Disposition: form-data; user="mike"; filename="xxx.jpg"; md5="xxxx"; size=10240\r\n
         q = begin;
         q = strstr(begin, "user=");
         q += strlen("user=");
         q++;    //跳过第一个"
         k = strchr(q, '"');
         strncpy(user, q, k-q);  //拷贝用户名
         user[k-q] = '\0';
     
         //========================================获取文件名字
         //"; filename="xxx.jpg"; md5="xxxx"; size=10240\r\n
         begin = k;
         q = begin;
         q = strstr(begin, "filename=");
         q += strlen("filename=");
         q++;    //跳过第一个"
         k = strchr(q, '"');
         strncpy(filename, q, k-q);  //拷贝文件名
         filename[k-q] = '\0';
     
         //========================================获取文件MD5码
         //"; md5="xxxx"; size=10240\r\n
         begin = k;
         q = begin;
         q = strstr(begin, "md5=");
         q += strlen("md5=");
         q++;    //跳过第一个"
         k = strchr(q, '"');
         strncpy(md5, q, k-q);   //拷贝文件名
         md5[k-q] = '\0';
     
         //========================================获取文件大小
         //"; size=10240\r\n
         begin = k;
         q = begin;
         q = strstr(begin, "size=");
         q += strlen("size=");
         k = strstr(q, "\r\n");
         char tmp[256] = {0};
         strncpy(tmp, q, k-q);   //内容
         tmp[k-q] = '\0';
         *p_size = strtol(tmp, NULL, 10); //字符串转long
     
         begin = p;
         p = strstr(begin, "\r\n");
         p += 2; //\r\n
         len -= (p-begin);
     
         //下面才是文件的真正内容
         /*
            ------WebKitFormBoundary88asdgewtgewx\r\n
            Content-Disposition: form-data; user="mike"; filename="xxx.jpg"; md5="xxxx"; size=10240\r\n
            Content-Type: application/octet-stream\r\n
            真正的文件内容\r\n
            ------WebKitFormBoundary88asdgewtgewx--
         */
         // begin指向正文首地址
         begin = p;
         
         // 将文件内容抠出来
         // 文件内容写如本地磁盘文件
     
         free(file_buf);
         return ret;
     }
使用 fastCGI 管理器启动 fastCGI 程序
        
spawn-fcgi -a IP 地址 -p 端口 -f ./fastcgi 程序
- 提示启动失败
- ldd fastCGI 程序

4. Http 上传下载进度
        
// QNetworkReply - 信号
void QNetworkReply::downloadProgress ( qint64 bytesReceived , qint64 bytesTotal )
- bytesReceived : 已经接收的字节数
- bytesTotal : 要接收的总字节数
void QNetworkReply::uploadProgress ( qint64 bytesSent , qint64 bytesTotal )
- bytesSent : 已经发送的字节数
- bytesTotal : 要发送的总字节数

5. 上传大文件Nginx设置

        1. 413 错误

        

服务器提示:413 Request Entity Too Large 的解决方法
原因: 上传文件太大, 请求实体太长了
解决方案:
在配置文件nginx.conf中添加: client_max_body_size 10M
10M: 用户指定的大小
2. 设置的位置 :
http{ } 中设置: client_max_body_size 20m;
所有的 server 中的所有的 location 都起作用
server{ } 中设置: client_max_body_size 20m;
对当前 server 的所有的 location 生效
location{ } 中设置: client_max_body_size 20m;
只对当前 location 生效
3. 三者的区别是:
http{} 中控制着所有 nginx 收到的 http 请求。
报文大小限制设置在 server {}中,控制该 server 收到的请求报文大小
如果配置在 location 中,则报文大小限制,只对匹配了 location 路由规则的请求生效。

6. Qt中的哈希运算

        1. 哈希算法 - QCryptographicHash

        

// 构造哈希对象
1 QCryptographicHash ( Algorithm method );
// 添加数据
// c 格式添加数据
void QCryptographicHash::addData ( const char * data , int length );
// qt 中的常用方法
void QCryptographicHash::addData ( const QByteArray & data );
// 适合操作大文件
bool QCryptographicHash::addData ( QIODevice * device ); // QFile
- 使用 device 打开一文件 , addData 进行文件的读操作
// 计算结果
QByteArray QCryptographicHash::result () const ;
// 一般适合 , 哈希值都是使用 16 进制格式的数字串来表示
QByteArray QByteArray::toHex () const ;
[ static ] QByteArray QCryptographicHash::hash ( const QByteArray & data , Algorithm
method );
- 参数 data : 要运算的数据
- 参数 method : 使用的哈希算法
- 返回值 : 得到的哈希值

 

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

初阶c语言:趣味扫雷游戏

目录 前言 制作菜单 构建游戏选择框架 实现游戏功能 模块化编程&#xff1a;查看前节三子棋的内容 初始化雷区 ​编辑 优化棋盘 随机埋入地雷 点击后的决策 实现此功能代码 game&#xff08;&#xff09;&#xff1b;的安排 前言 《扫雷》是一款大众类的益智小游戏&…

lnmp架构-PHP

08 PHP源码编译 09 php初始化配置 nginx 的并发能力强 phpinfo函数 就是 显示php信息 10 php的功能模块 编译memcache模块 php的动态模块方式 mamcache 就是内存 直接从内存中命中 所以性能非常好 但是 这还不是最好的方式 工作流程 关键看后端的 php 什么时候处理完 mamcac…

Windows部署SQL Server-开发者版

一、简介 SQL Server 开发者版本&#xff0c;是一个为开发人员准备的版本。它是免费的&#xff0c;但不能在生产中使用它。它包含所有 SQL Server 企业版的功能&#xff0c;但不能在生产中部署&#xff0c;是一个用于非生产环境的免费版本。 二、下载 访问 https://www.mic…

软件设计师学习笔记5-流水线技术

目录 1.流水线的概念 2.流水线计算 2.1流水线周期及执行时间 2.2流水线吞吐量 1.流水线的概念 考点&#xff1a;相关参数计算&#xff1a;流水线执行时间计算、流水线吞吐率、流水线加速比、流水线效率(后两者的计算中级不考) 流水线是指在程序执行时多条指令重叠进行操作…

一种基于异质结的SiC功率双沟道MOSFET,具有改进的开关性能和反向恢复。

标题&#xff1a;A heterojunction-based SiC power double trench MOSFET with improved switching performance and reverse recovery 摘要 在本文中&#xff0c;提出了一种基于异质结的SiC双沟道MOSFET&#xff08;HJ-DTMOS&#xff09;&#xff0c;旨在改善其开关性能和反…

香港全新的虚拟资产服务商发牌制度

香港证监会2023年2月20日通告&#xff0c;原有虛擬資產交易平台如要符合資格參與當作為獲發牌的安排&#xff0c;必須在2023 年6 月1 日至2024 年2 月29 日期間(即由2023 年6 月1 日37起計九個月內)內&#xff0c;根據《打擊洗錢條例》下的虛擬資產服務提供者制度在網上提交完全…

2023有哪些更好用的网页制作工具

过去&#xff0c;专业人员使用HTMLL、CSS、Javascript等代码手动编写和构建网站。现在有越来越多的智能网页制作工具来帮助任何人实现零代码基础&#xff0c;随意建立和设计网站。在本文中&#xff0c;我们将向您介绍2023年流行的网页制作工具。我相信一旦选择了正确的网页制作…

软考A计划-系统集成项目管理工程师-项目风险管理-尾

点击跳转专栏>Unity3D特效百例点击跳转专栏>案例项目实战源码点击跳转专栏>游戏脚本-辅助自动化点击跳转专栏>Android控件全解手册点击跳转专栏>Scratch编程案例点击跳转>软考全系列点击跳转>蓝桥系列 &#x1f449;关于作者 专注于Android/Unity和各种游…

FPGA GTX全网最细讲解,aurora 8b/10b协议,HDMI视频传输,提供2套工程源码和技术支持

目录 1、前言免责声明 2、我这里已有的 GT 高速接口解决方案3、GTX 全网最细解读GTX 基本结构GTX 发送和接收处理流程GTX 的参考时钟GTX 发送接口GTX 接收接口GTX IP核调用和使用 4、设计思路框架视频源选择IT6802解码芯片配置及采集动态彩条视频数据组包GTX aurora 8b/10b数据…

基于智和网管平台的网络安全运维解决方案

随着信息技术的快速发展及网络应用的广泛普及&#xff0c;企业在享受网络技术带来便利的同时&#xff0c;也受到日益严重的网络安全威胁。未来&#xff0c;企业信息系统规模和复杂程度将不断增大&#xff0c;对信息通信技术的应用也将不断深入&#xff0c;网络安全运维将成为愈…

Unity 之 transform.rotate() 实现旋转

文章目录 详细介绍默认情况下&#xff0c;以局部坐标 详细介绍 在Unity中&#xff0c;Transform.Rotate() 是一个用于在物体上进行旋转的函数。它可以用来在局部坐标系下对物体进行旋转&#xff0c;也可以在世界坐标系下进行旋转。下面是关于 Transform.Rotate() 的详细介绍&a…

章节 2:轻松入手JSX -《React.js手把手教程:从初学者到实战高手》- 第一部分:React.js基础

《React.js手把手教程&#xff1a;从初学者到实战高手》 第一部分&#xff1a;React.js基础 章节 2&#xff1a;轻松入手JSX 在上一章节中&#xff0c;我们初步认识了React.js。现在&#xff0c;我们将更深入地探索React.js中的JSX&#xff08;JavaScript XML&#xff09;语法…

牛客练习赛114

A.最后有0得数肯定是10得倍数&#xff0c;然后直接排序即可 #include<bits/stdc.h> using namespace std; const int N 1e610,mod1e97; int n; void solve(){cin>>n;vector<int> a(n);for(auto&i:a) cin>>i;sort(a.begin(),a.end(),greater<&g…

Airtest遇到模拟器无法输入中文的情况该如何处理?

1. 前言 最近有收到同学们的一些提问&#xff0c;使用Airtest的 text 接口&#xff0c;发现在部分模拟器上&#xff0c; text 无法输入中文&#xff0c;不知道该怎么处理。 今天我们就输入这个小问题&#xff0c;来详细聊一下。 2. Airtest的输入法简介 对于Android设备来说…

Spark 启动时,报JAVA_HOME is not set

文章目录 1、报错内容2、解决方式3、再次启动Spark集群 1、报错内容 Spark启动时报错&#xff1a; hadoop104: JAVA_HOME is not set2、解决方式 解决方式&#xff1a; 打开启动配置文件 cd /opt/module/spark-standalone/sbin/ vim spark-config.sh配置Java的环境变量 …

【网络】HTTPS的加密

目录 第一组&#xff0c;非对称加密第二组&#xff0c;非对称加密第三组&#xff0c;对称加密证书签名 HTTPS使用的是非对称加密加对称加密的方案 &#xff08;非对称加密&#xff1a;公钥加/解密&#xff0c;私钥解/加密&#xff09; &#xff08;对称加密&#xff1a;一组对称…

开发新能源的好处

风能无论是总装机容量还是新增装机容量&#xff0c;全球都保持着较快的发展速度&#xff0c;风能将迎来发展高峰。风电上网电价高于火电&#xff0c;期待价格理顺促进发展。生物质能有望在农业资源丰富的热带和亚热带普及&#xff0c;主要问题是降低制造成本&#xff0c;生物乙…

提速换挡 | 至真科技用技术打破业务壁垒,助力出海破局增长

各个行业都在谈出海&#xff0c;但真正成功的又有多少&#xff1f; 李宁出海十年海外业务收入占比仅有1.3%&#xff0c;走出去战略基本失败。 京东出海业务磕磕绊绊&#xff0c;九年过去国际化业务至今在财报上都不配拥有姓名。 几百万砸出去买量&#xff0c;一点水花都没有…

SpringBootWeb 登录认证

登录认证&#xff0c;那什么是认证呢&#xff1f; 所谓认证指的就是根据用户名和密码校验用户身份的这个过程&#xff0c;认证成功之后&#xff0c;我们才可以访问系统当中的信息&#xff0c;否则就拒绝访问。 在前面的案例中&#xff0c;我们已经实现了部门管理、员工管理的…

【Go 基础篇】Go 语言字符串函数详解:处理字符串进阶

大家好&#xff01;继续我们关于Go语言中字符串函数的探索。字符串是编程中常用的数据类型&#xff0c;而Go语言为我们提供了一系列实用的字符串函数&#xff0c;方便我们进行各种操作&#xff0c;如查找、截取、替换等。在上一篇博客的基础上&#xff0c;我们将继续介绍更多字…