0%

mongodb手动备份

备份命令mongodump

1
2
3
4
5
6
7
mongodump --host 127.0.0.1 --port 27017 --username user --password pass --out /data/backup/ --db test --collection mycollection
#参数解释
#hsot 数据库ip
#port 数据库端口
#out 备份指定输出目录
#db 备份指定数据库
#collection 备份指定的表

默认备份本地运行在27017端口下的 MongoDB 实例中的所有数据库(local 除外),并在当前目录下生成 dump/ 路径存放备份文件,备份以文件名区分数据库,里面以bsonjson单独存表

  1. 在安装好mongodb的服务器上执行mongodump命令就可以备份数据库了,备份的文件会在当前目录的dump里面

恢复命令mongorestore dump/

参数同备份,其中dump为备份文件的路径

mongodb自动备份

  1. 创建脚本mongod_bak.sh

    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
    #!/bin/sh
    DUMP=mongodump
    #备份文件临时目录
    OUT_DIR=/data/backup/mongod/tmp
    #备份文件正式目录
    TAR_DIR=/data/backup/mongod
    #备份文件将以备份时间保存
    DATE=`date +%Y_%m_%d_%H_%M_%S`
    #数据库操作员,建议设置个单独的用户作为备份用户
    #DB_USER=<USER>
    #数据库操作员密码
    #DB_PASS=<PASSWORD>
    #保留最新14天的备份
    DAYS=14
    #备份文件命名格式
    TAR_BAK="mongod_bak_$DATE.tar.gz"
    #远程备份ip
    #REMOTEIP=<远程服务ip>
    #远程备份用户名
    #REMOTEUSER=<远程连接用户名>
    #创建文件夹
    cd $OUT_DIR
    #清空临时目录
    rm -rf $OUT_DIR/*
    #创建本次备份文件夹
    mkdir -p $OUT_DIR/$DATE
    #执行备份命令,带用户
    #$DUMP -u $DB_USER -p $DB_PASS -o $OUT_DIR/$DATE
    #执行备份命令,不带用户
    $DUMP -o $OUT_DIR/$DATE
    #将备份文件打包放入正式目录
    tar -zcvf $TAR_DIR/$TAR_BAK $OUT_DIR/$DATE
    #删除14天前的旧备份
    find $TAR_DIR/ -mtime +$DAYS -delete
    #远程备份,需要自行配置ssh证书登陆方式,需在远程提前建好备份文件目录TAR_DIR中设置的路径值
    #scp $TAR_DIR/$TAR_BAK $REMOTEUSER@$REMOTEIP:$TAR_DIR/
  2. 添加执行权限chmod +x mongod_bak.sh

  3. 执行测试./mongod_bak.sh,这步可忽略

  4. 添加自动执行脚本功能,执行

    1
    2
    3
    4
    5
    6
    7
    8
    #每天凌晨2点自动执行,脚本路径更改为自己存放的路径
    echo "0 2 * * * root /root/mongod_bak.sh" >>/etc/crontab
    #使能配置
    crontab /etc/crontab
    #检查配置是否生效
    crontab -l
    #检查crond是否运行
    service crond status

备份恢复

1
2
3
4
#解压备份文件
tar -zxvf mongod_bak_2019_xx_xx_xx_xx_xx.tar.gz
#执行mongorestore进行恢复,切换到解压的备份目录里面
mongorestore tmp/

自动生成脚本及自动配置定时备份

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
#!/bin/bash
echo "欢迎使用mongodb自动备份配置脚本"
read -p "请输入mongodb备份路径(/data/mongodbBackUp):" -t 30 path #等待30秒
if [ ! -n "$path" ] ;then
path="/data/mongodbBackUp"
echo "备份路径默认设置为: $path"
else
echo "备份路径为: $path"
fi
read -p "请输入mongodb用户名:" -t 120 dbUserName
if [ ! -n "$dbUserName" ] ;then
echo "用户名输入为空"
exit
else
echo "用户名为: $dbUserName"
fi
read -p "请输入mongodb密码:" -s password
if [ -z "$password" ] ;then
echo "密码输入为空$password"
exit
else
echo -e "\n"
read -p "请再次输入mongodb密码:" -s rpassword
if [ "$rpassword"x != "$password"x ] ;then
echo "输入密码不一致"
exit
else
echo "密码设置成功"
fi
fi
read -p "是否设置远程备份,请输入[y/n]" -n 1 remote
if [ "$remote"x = "y"x ] ;then
echo -e "\n"
echo "进入远程配置,远程备份功能需提前自行配置好ssh证书登陆,远程地址样例"
echo "root@192.168.1.1:/backupPath/"
read -p "请设置远程服务器地址:" scpPath
echo "远程地址为:$scpPath"
fi
echo "正在配置中...."
echo "#!/bin/bash" >/data/mongod_bak.sh
echo -e "DATE=\`date +%Y_%m_%d_%H_%M_%S\`" >>/data/mongod_bak.sh
echo "rm -rf $path/tmp/*" >>/data/mongod_bak.sh
echo "mkdir -p $path/tmp/$DATE" >>/data/mongod_bak.sh
echo "mongodump -u $dbUserName -p $password -o $path/tmp/$DATE" >>/data/mongod_bak.sh
echo -e "tar -zcvf $path/mongod_bak_\$DATE.tar.gz $path/tmp/$DATE" >>/data/mongod_bak.sh
echo "find $path/ -mtime +14 -delete" >>/data/mongod_bak.sh
if [ "$remote"x = "y"x ] ;then
echo -e "scp $path/mongod_bak_\$DATE.tar.gz $scpPath" >>/data/mongod_bak.sh
fi
chmod +x /data/mongod_bak.sh
echo "配置完成"
echo "开始设置定时备份,定时设置目录/etc/crontab"
echo "定时任务脚本生成路径/data/mongod_bak.sh"
echo "0 2 * * * root /data/mongod_bak.sh" >>/etc/crontab
crontab /etc/crontab
crontab -l
echo "设置成功"

rpm打包SpringBoot实战

  1. 环境需求安装rpm

    1
    2
    3
    4
    #centos
    yum -y install rpmdevtools
    #mac
    brew install rpm
  2. 添加插件

    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
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
      <properties>
    .......
    <rpm.release>0.3.0</rpm.release>
    <rpm.install.path>/home/face/java</rpm.install.path>
    <rpm.prefix>/data/micro-services/9090-web-api-jar</rpm.prefix>
    </properties>

    <build>
    <finalName>${autoPackage.name}</finalName>
    <plugins>
    <plugin>
    <groupId>org.codehaus.mojo</groupId>
    <artifactId>rpm-maven-plugin</artifactId>
    <version>2.2.0</version>
    <extensions>true</extensions>
    <executions>
    <execution>
    <goals>
    <goal>rpm</goal>
    </goals>
    </execution>
    </executions>
    <configuration>
    <prefix>${rpm.prefix}</prefix>
    <distribution>myron</distribution>
    <group>myron.com</group>
    <packager>hello</packager>
    <version>${project.version}</version>
    <autoRequires>true</autoRequires>
    <release>3</release>
    <requires>
    <require>java-1.7.0 >= 1.7</require>
    </requires>
    <mappings>
    <mapping>
    <!-- 安装rpm后指向的服务器安装目录 -->
    <directory>${rpm.install.path}/${project.artifactId}</directory>
    <filemode>755</filemode>
    <username>root</username>
    <groupname>root</groupname>
    <sources>
    <source>
    <location>target/${project.artifactId}.jar</location>
    </source>
    </sources>
    </mapping>
    <!-- 复制安装相关脚本命令 根据具体项目需要决定是否使用-->
    <!-- <mapping>-->
    <!-- <directory>${rpm.install.path}/${project.artifactId}/bin</directory>-->
    <!-- <filemode>750</filemode>-->
    <!-- <username>root</username>-->
    <!-- <groupname>root</groupname>-->
    <!-- <sources>-->
    <!-- <source>-->
    <!-- <location>src/bin</location>-->
    <!-- </source>-->
    <!-- </sources>-->
    <!-- </mapping>-->

    <!--配置软连接注册服务起停项目,相当于:ln -sf myapp.jar /etc/init.d/myapp)
    启动: systemctl start myapp
    停止: systemctl stop myapp
    重启: systemctl restart myapp
    查看日志: journalctl -u myapp-->
    <!-- <mapping>-->
    <!-- <directory>/etc/init.d</directory>-->
    <!-- <filemode>750</filemode>-->
    <!-- <username>root</username>-->
    <!-- <groupname>root</groupname>-->
    <!-- <sources>-->
    <!-- <softlinkSource>-->
    <!-- <location>${rpm.install.path}/${project.artifactId}/${project.artifactId}-${project.version}.jar</location>-->
    <!-- <destination>${project.artifactId}</destination>-->
    <!-- </softlinkSource>-->
    <!-- </sources>-->
    <!-- </mapping>-->
    </mappings>
    <preinstallScriptlet>
    <script>echo "installing ${project.name} now"</script>
    </preinstallScriptlet>
    <postinstallScriptlet>
    <!-- 通过软链接 配置"service demo-swagger2 " 相关操作命令启动-->
    <!-- 使用上面softlinkSource配置替代
    <script>
    rm -f /etc/init.d/${project.artifactId};
    ln -sf ${rpm.install.path}/${project.artifactId}/bin/startup.sh /etc/init.d/demo-swagger2;
    </script>
    -->
    </postinstallScriptlet>
    <preremoveScriptlet>
    <script>
    <!--rm -f /etc/init.d/${project.artifactId};-->
    echo "uninstalling ${project.name} success";
    </script>
    <!-- 引用脚本方式
    <scriptFile>src/main/scripts/preremove</scriptFile>
    <fileEncoding>utf-8</fileEncoding>
    -->
    </preremoveScriptlet>
    </configuration>
    </plugin>
    ........
    </plugins>
    </build>
    </project>

空配置

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
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>rpm-maven-plugin</artifactId>
<version>2.2.0</version>
<inherited>false</inherited>
<executions>
<execution>
<!-- unbinds rpm creation from maven lifecycle -->
<phase>none</phase>
<goals>
<goal>attached-rpm</goal>
</goals>
</execution>
</executions>
<configuration>
<release>1</release>
<distribution>loganshen</distribution>
<group>ifengkou.github.io</group>
<packager>loganshen</packager>
<prefix>/opt/soft</prefix>
<mappings>
<mapping>
<directory>/tmp</directory>
</mapping>
</mappings>
</configuration>
</plugin>

package rpm:rpm -U

参考

maven使用rpm-maven-plugin构建RPM包

理论基础

目录结构解释
  1. BUILD是编译rpm包的临时目录
  2. BUILDROOT是最后生成rpm包的临时安装目录
  3. RPMS存放最终生成的rpm二进制包
  4. SOURCES是源代码(.tar.gz)存放目录
  5. SPECS用来存放spec文件
  6. SRPMS存放最终生成的rpm源码包
spec文件标签解释
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
# 安装包名
Name:
#版本号
Version: 1.0.0
Release: 1%{?dist}
#简介
Summary: This is pragram printf hell world hahah
#分组,可去掉
Group: Development/Tools
#协议
License: GPL
#资源路径(源代码路径)
Source0: %{name}-%{version}.tar.gz
#安装依赖
Requires: vim
#详细描述
%description
#编译前准备
%prep
%setup -q #自动解压?
#编译
%build
#安装
%install
mkdir -p $RPM_BUILD_ROOT/usr/bin
cp $RPM_BUILD_DIR/%{name}-%{version}/hello-world $RPM_BUILD_ROOT/usr/bin
#执行安装完成后需要启动服务或修改配置文件等脚本,例如启动服务等,这里执行的脚本不需要收集文件
%post
#删除临时构建目录
%clean
rm -rf $RPM_BUILD_ROOT
#收集文件
%files
%doc
/usr/bin/hello-world

%changelog

实战hello-world

  1. 安装制作工具yum -y install rpmdevtools会自动依赖安装rpm-build

  2. 生成开发目录rpmdev-setuptree会在~目录生成rpmbuild文件目录

    1
    2
    3
    4
    5
    6
    `-- rpmbuild
    |-- BUILD
    |-- RPMS
    |-- SOURCES
    |-- SPECS
    `-- SRPMS
  3. 创建源代码

    1
    2
    3
    4
    5
    6
    7
    8
    9
    ~> mkdir -p rpmbuild/SOURCES/hello-world-1.0.0
    ~> cd rpmbuild/SOURCES/hello-world-1.0.0/
    hello-world-1.0.0> vim hello-world
    #hello-world文件内容如下,就是一个简单的输出hello world的脚本
    #!/bin/sh
    echo Hello World hahah
    #-----------------------------------------------------
    hello-world-1.0.0> chmod 755 hello-world
    hello-world-1.0.0> ./hello-world #测试脚本打印Hello World hahah
  4. 打包源码tar zcvf hello-world-1.0.0.tar.gz hello-world-1.0.0

  5. 编写spec文件cd ~/rpmbuild/SPECS然后vim hello-world.spec创建hello-world.spec文件,vim会自动根据后缀spec加载默认模版,修改模版如下

    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
    Name: hello-world
    Version: 1.0.0
    Release: 1%{?dist}
    Summary: This is pragram printf hell world hahah

    Group: Development/Tools
    License: GPL
    Source0: %{name}-%{version}.tar.gz

    %description

    %prep
    %setup -q

    %build

    %install
    mkdir -p $RPM_BUILD_ROOT/usr/bin
    cp $RPM_BUILD_DIR/%{name}-%{version}/hello-world $RPM_BUILD_ROOT/usr/bin

    %clean
    rm -rf $RPM_BUILD_ROOT
    %files
    %doc
    /usr/bin/hello-world

    %changelog
  6. 执行rpmbuild -ba hello-world.spec进行打包最后目录结构

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    .
    |-- BUILD
    | `-- hello-world-1.0.0
    | |-- debugfiles.list
    | |-- debuglinks.list
    | |-- debugsources.list
    | |-- elfbins.list
    | `-- hello-world
    |-- BUILDROOT
    |-- RPMS
    | `-- x86_64
    | |-- hello-world-1.0.0-1.el7.x86_64.rpm
    | `-- hello-world-debuginfo-1.0.0-1.el7.x86_64.rpm
    |-- SOURCES
    | |-- hello-world-1.0.0
    | | `-- hello-world
    | `-- hello-world-1.0.0.tar.gz
    |-- SPECS
    | `-- hello-world.spec
    `-- SRPMS
    `-- hello-world-1.0.0-1.el7.src.rpm
  7. 安装打包好的安装包yum install ~/rpmbuild/RPMS/x86_64/hello-world-1.0.0-1.el7.x86_64.rpm

  8. 测试

    1
    2
    3
    > hello-world
    Hello World hahah
    > yum remove hello-world #卸载刚刚安装的

创建本地yum源

  1. 新建添加本地源vim /etc/yum.repos.d/CentOS-Media.repo,内容如下

    1
    2
    3
    4
    5
    6
    [c7-media]
    name=CentOS-$releasever - Media
    baseurl=file:///root/nantianrepo/
    gpgcheck=0
    enabled=1
    gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-7
  2. 安装yum install createrepo

  3. 新建仓库目录结构,然后放入需要的安装包,及依赖包

    1
    2
    3
    4
    5
    `-- ntrepo
    |-- CentOS-Local.rpeo
    `-- packages
    |-- CodeMeter-lite-6.50.2631-502.x86_64.rpm
    `-- hello-world-1.0.0-1.el7.x86_64.rpm
  4. 在ntrepo目录执行createrepo .会生成多一个目录,以及包的索引

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    `-- nantianrepo
    |-- CentOS-Local.rpeo
    |-- packages
    | |-- CodeMeter-lite-6.50.2631-502.x86_64.rpm
    | `-- hello-world-1.0.0-1.el7.x86_64.rpm
    `-- repodata
    |-- 14a98942df6d04-other.xml.gz
    |-- 16b2285eb13334fe6-filelists.xml.gz
    |-- 839450f23accab4617-primary.sqlite.bz2
    |-- 8e84312460f2957b7c3-other.sqlite.bz2
    |-- a2596c92ad4f0c5750156f-filelists.sqlite.bz2
    |-- d4e9d532b7bf9a0c2af-primary.xml.gz
    `-- repomd.xml
  5. 然后执行yum clean all清理缓存

  6. 最后测试安装yum install hello-world会自动依赖

下载rpm依赖包

  1. 安装yum ``install yum-plugin-downloadonly

  2. 下载依赖包yum install –downloadonly –downloaddir= <依赖包存储路径> <需要下载依赖包的安装包名>例如:

    1
    yum install --downloadonly --downloaddir=/data/rpm  mongodb

常见问题

  1. 错误信息分析,关键信息cd jdk-8u77-linux-x64-1.0.0

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    执行(%prep): /bin/sh -e /var/tmp/rpm-tmp.QO57WH
    + umask 022
    + cd /root/rpmbuild/BUILD
    + cd /root/rpmbuild/BUILD
    + rm -rf jdk-8u77-linux-x64-1.0.0
    + /usr/bin/gzip -dc /root/rpmbuild/SOURCES/jdk-8u77-linux-x64-1.0.0.tar.gz
    + /usr/bin/tar -xf -
    + STATUS=0
    + '[' 0 -ne 0 ']'
    + cd jdk-8u77-linux-x64-1.0.0
    /var/tmp/rpm-tmp.QO57WH: line 35: cd: jdk-8u77-linux-x64-1.0.0: No such file or directory
    错误:/var/tmp/rpm-tmp.QO57WH (%prep) 退出状态不好

    原因,是因为解压之后路径找不到对应目录

    解决:

    1. 方式一手动解压,重新手动压缩

    2. 方式二修改spec文件中的prep,然后查看BUILD里面的实际解压目录/root/rpmbuild/BUILD/jdk1.8.0_77然后设置为实际目录即可

      1
      2
      %prep
      %setup -n jdk1.8.0_77
  2. 编译后无法运行提示无架构

    1
    2
    3
    4
    5
    [root@xuan SRPMS]# yum install jdk-1.8-77.src.rpm
    已加载插件:fastestmirror
    正在检查 jdk-1.8-77.src.rpm: jdk-1.8-77.src
    无法添加软件包 jdk-1.8-77.src.rpm 至操作中。不属于任何可兼容的架构:src
    错误:无须任何处理

    解决:进错目录,这个是源代码

参考

制作一个简单的rpm包:helloworld

RPM 包制作

rpmbuild SPEC文件说明

https://blog.csdn.net/wl_fln/article/details/7263668

centos设置交换分区之阿里云

交换分区是在内存不足的情况下,存储长期不活跃的内存,但是性能受硬盘影响,下降10倍不等,固态稍微好一点,机械硬盘简直卡死建议不设置

添加交换分区
  1. 创建交换分区文件dd if=/dev/zero of=/home/swap bs=1024 count=3764224其中**3764244=1024x2x实际内存大小(M)**其中2代表虚拟内存是实际内存的2倍
  2. 设置交换分区文件mkswap /home/swap
  3. 启用交换分区swapon /home/swap
  4. 设置开机有效echo "/home/swap swap swap defaults 0 0" >> /etc/fstab
  5. 重启reboot非必须,然后执行df -h就可以看到swap有值了
删除交换分区
  1. 停止swap分区swapoff /home/swap
  2. 删除swap分区rm -fr /home/swap
  3. 删除开机启动,在/etc/fstab删除行/home/swap swap swap defaults 0 0即可

腾讯云CDN配置

cdn是资源加速缓存的服务

  1. 开通CDN
  2. 在域名管理界面添加域名
  3. 域名是指最后访问的域名,后面通过该域名访问就会加速
  4. 源站类型就是要加速的资源cos(oss)或服务
  5. 设置好后还需要把刚刚添加的域名做域名解析,解析的地址填CNAME的地址
  6. 测试解析是否成功可以ping或linux执行dig coscdn.xxxx.com
  7. 测试通过设置的域名访问cos里面的资源,就是把cos的资源链接,替换为新的域名
  8. 然后访问,查看统计分析是否有记录(感觉有很长的延时)

常见问题

  1. 访问资源时读取老的资源不更新

    解决:在CDN设置里面的访问控制->过滤参数按钮关闭即可

    原因:打开之后回忽略url中?号后面的所有参数,所以带参数时,就不会访问新资源

参考

过滤参数配置

protobuf介绍

就是一种

protobuf简单测试

项目源码见xuanfong1/springLeaning/protobuf

  1. 在项目引入maven/gradle依赖compile 'com.google.protobuf:protobuf-java:3.6.1'

  2. 下载代码生成工具,作用是将file.proto文件转换成其他语言(java/C++/GO/Python/C#/Dart)的文件,eg:这里选择window平台,版本和maven版本一致,因此选择protoc-3.6.1-win32.zip,其他操作系统选择对应平台即可,然后解压,在bin目录可以看到protoc.exe文件,复制重命名protoc-3.6.1-win32.exe为了好区分版本,其他文件用不着

  3. 编写一个测试PersonMsg.proto文件

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    message Person {

    // ID(必需)
    required int32 id = 1;

    // 姓名(必需)
    required string name = 2;

    // email(可选)
    optional string email = 3;

    // 朋友(集合)
    repeated string friends = 4;
    }
  4. 使用工具进行java代码生成,执行.\protobuf\protoc-3.6.1-win32.exe --java_out=.\protobuf\src\main\java\com\exxk\protobuf\ .\protobuf\src\test\protobuf\PersonMsg.proto

    注意,这里生成的代码PersonMsg.java里面是没有包名的,可以手动加入

  5. ProtobufApplicationTests.java编写测试方法

    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
    import java.io.ByteArrayInputStream;
    import java.io.ByteArrayOutputStream;
    import java.io.IOException;
    import java.util.List;


    //@RunWith(SpringRunner.class)
    //@SpringBootTest
    public class ProtobufApplicationTests {

    @Test
    public void contextLoads() {
    // 按照定义的数据结构,创建一个Person
    PersonMsg.Person.Builder personBuilder = PersonMsg.Person.newBuilder();
    personBuilder.setId(1);
    personBuilder.setName("叉叉哥");
    personBuilder.setEmail("xxg@163.com");
    personBuilder.addFriends("Friend A");
    personBuilder.addFriends("Friend B");
    PersonMsg.Person xxg = personBuilder.build();

    // 将数据写到输出流,如网络输出流,这里就用ByteArrayOutputStream来代替
    ByteArrayOutputStream output = new ByteArrayOutputStream();
    try {
    xxg.writeTo(output);
    } catch (IOException e) {
    e.printStackTrace();
    }

    // -------------- 分割线:上面是发送方,将数据序列化后发送 ---------------

    byte[] byteArray = output.toByteArray();

    // -------------- 分割线:下面是接收方,将数据接收后反序列化 ---------------

    // 接收到流并读取,如网络输入流,这里用ByteArrayInputStream来代替
    ByteArrayInputStream input = new ByteArrayInputStream(byteArray);

    // 反序列化
    PersonMsg.Person xxg2 = null;
    try {
    xxg2 = PersonMsg.Person.parseFrom(input);
    } catch (IOException e) {
    e.printStackTrace();
    }
    System.out.println("ID:" + xxg2.getId());
    System.out.println("name:" + xxg2.getName());
    System.out.println("email:" + xxg2.getEmail());
    System.out.println("friend:");
    List<String> friends = xxg2.getFriendsList();
    for(String friend : friends) {
    System.out.println(friend);
    }
    }
    }
  6. 设置自动生成包名,修改PersonMsg.proto文件

    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
    //指定编译版本2或3
    syntax = "proto2";
    //当前包名
    package PersonMsg;
    //包路径
    option java_package = "com.exxk.protobuf";
    //类名
    option java_outer_classname = "PersonMsg";

    message Person {

    // ID(必需)
    required int32 id = 1;

    // 姓名(必需)
    required string name = 2;

    // email(可选)
    optional string email = 3;

    // 朋友(集合)
    repeated string friends = 4;
    }

    message car {
    }
  7. 修改命令.\protobuf\protoc-3.6.1-win32.exe --java_out=.\protobuf\src\main\java\ .\protobuf\src\test\protobuf\PersonMsg.proto

protoc gradle插件

插件地址:google/protobuf-gradle-plugin

  1. 在父级build.gradle添加

    1
    2
    3
    4
    5
    6
    7
    8
    buildscript {
    repositories {
    mavenCentral()
    }
    dependencies {
    classpath 'com.google.protobuf:protobuf-gradle-plugin:0.8.8'
    }
    }
  2. 在子项目build.gradle添加

    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
    apply plugin: 'com.google.protobuf'

    dependencies {
    compile 'com.google.protobuf:protobuf-java:3.6.1'
    }

    sourceSets {
    main {
    proto {
    // In addition to the default 'src/main/proto'
    //proto输入目录
    srcDir 'src/main/protobuf'
    srcDir 'src/main/protocolbuffers'
    srcDir 'src/main/protocol buffers'
    // In addition to '**/*.proto' (use with caution).
    // Using an extension other than 'proto' is NOT recommended, because when
    // proto files are published along with class files, we can only tell the
    // type of a file from its extension.
    include '**/*.protodevel'
    }
    }
    test {
    proto {
    // In addition to the default 'src/test/proto'
    srcDir 'src/test/protocolbuffers'
    }
    }
    }
    protobuf {
    //输出目录
    generatedFilesBaseDir = "$projectDir/src"
    protoc {
    //protoc编译版本
    artifact = 'com.google.protobuf:protoc:3.0.0'
    }
    }
  3. 然后点击右侧gradleprotobuf->Tasks->other->generateProto编译proto文件生成java文件

protoc maven插件

解决不同平台开发编译问题,功能能实现自动根据不同系统(os/win/linux)调用不同的protoc工具

插件一os72/protoc-jar-maven-plugin

配置更改一直不生效,一直使用最新的3.6.0版本的protoc工具

插件二org.xolstice.maven.plugins/protobuf-maven-plugin

Maven工程处理Protobuf

目录结构:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
├─src
│ ├─main
│ │ ├─java //proto生成java文件目录
│ │ │ └─com
│ │ │ └─surelive
│ │ │ └─app
│ │ │ └─server
│ │ │ └─protocol
│ │ │ ├─request
│ │ │ └─response
│ │ └─resources
│ │ └─proto //proto文件目录
│ │ ├─request
│ │ └─response
│ └─test
│ └─java
├─pom.xml

编写pom.xml添加插件

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
<project ...>    
....
<dependencies>
<dependency>
<groupId>com.google.protobuf</groupId>
<artifactId>protobuf-java</artifactId>
<version>2.5.0</version>
</dependency>

</dependencies>

<build>
<defaultGoal>package</defaultGoal>
<!--识别系统类型-->
<extensions>
<extension>
<groupId>kr.motd.maven</groupId>
<artifactId>os-maven-plugin</artifactId>
<version>1.6.0</version>
</extension>
</extensions>
<plugins>
<!-- protobuf 编译组件 -->
<plugin>
<groupId>org.xolstice.maven.plugins</groupId>
<artifactId>protobuf-maven-plugin</artifactId>
<version>0.6.1</version>
<extensions>true</extensions>
<configuration>
<!--proto源文件目录-->
<protoSourceRoot>${project.basedir}/src/main/proto</protoSourceRoot>
<!--输出目录-->
<outputDirectory>${project.basedir}/src/main/java</outputDirectory>
<!--设置是否在生成java文件之前清空outputDirectory的文件,默认值为true,设置为false时也会覆盖同名文件-->
<clearOutputDirectory>true</clearOutputDirectory>
<!--编译命令及版本,${os.detected.classifier}识别版本号,依赖os-maven-plugin插件-->
<protocArtifact>com.google.protobuf:protoc:2.5.0:exe:${os.detected.classifier}</protocArtifact>
</configuration>
<executions>
<execution>
<goals>
<goal>compile</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

使用,点击右侧插件里面的protobuf->protobuf:compile或者执行mvn protobuf:compile

注意
  1. 不添加输出目录识别不了多级目录(奇怪)
  2. 设置目录protoSourceRoot目录是,是以该目录为相对路径,因此代码里面的import "response/xxx.proto要加上response二级目录,但是如果可以设置protoSourceRoot为两个或二级目录就不需要修改,clearOutputDirectory设置true,也不会清理其他目录中其他文件

gitlab类似仓库Gogs

Gogs内存占用小

部署脚本docker-compose.yml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
version: '3'

services:
gogs:
restart: always
image: gogs/gogs
ports:
- "14080:3000"
- "14022:22"
volumes:
- /dockerdata/v-gogs:/data
deploy:
replicas: 1
restart_policy:
condition: on-failure
placement:
constraints: [node.hostname == xuanps]

第一次运行需要初始化,网页里面设置见Application

后面可以通过脚本/dockerdata/v-gogs/gogs/conf/app.ini修改所有配置

github:gogs/gogs

app.ini配置文档

镜像仓库设置

win10子系统Ubuntu安装java

安装java环境
1
2
3
4
5
6
7
cd /usr/lib/
sudo mkdir jvm
#在windos下载的该文件路径
sudo mv jdk-8u201-linux-x64.tar.gz /usr/lib/jvm/
#在/usr/lib/jvm路面
sudo tar -zxvf jdk-8u201-linux-x64.tar.gz
sudo rm jdk-8u201-linux-x64.tar.gz
配置环境变量

sudo vim ~/.bashrc在文件末尾添加

1
2
3
4
export JAVA_HOME=/usr/lib/jvm/jdk1.8.0_201
export JRE_HOME=${JAVA_HOME}/jre
export CLASSPATH=.:${JAVA_HOME}/lib:${JRE_HOME}/lib
export PATH=${JAVA_HOME}/bin:$PATH

执行source ~/.bashrc生效配置

测试java -version

运行tomcat

进入tomcat安装目录,windos和linux通用,然后右键打开ubunt,执行./catalina.sh run

注意事项

tomcat不要放Program Files带空格或特殊字符的路径,在linux下识别不了

java项目添加maven框架

  1. 右键项目->Add Frameworks Support->[✔]maven会自动整理项目结构

  2. 修改pom.xml

    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
    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.surelive.api</groupId>
    <artifactId>ApiServer</artifactId>
    <version>1.0-SNAPSHOT</version>
    <!--设置打包格式-->
    <packaging>war</packaging>

    <properties>
    <!--设置File encoding,没设置默认GBK会提示错误-->
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
    <!--设置java编译版本-->
    <maven.compiler.source>1.7</maven.compiler.source>
    <maven.compiler.target>1.7</maven.compiler.target>
    <maven.compiler.compilerVersion>1.7</maven.compiler.compilerVersion>
    </properties>

    <!-- 配置maven地址 -->
    <distributionManagement>
    <repository>
    <!--这里的id要和maven里的的settings.xml的id一致-->
    <id>nexus-releases</id>
    <name>Nexus Release Repository</name>
    <url>http://112.74.51.136:14002/repository/maven-releases/</url>
    </repository>
    <snapshotRepository>
    <id>nexus-snapshots</id>
    <name>Nexus Snapshot Repository</name>
    <url>http://112.74.51.136:14002/repository/maven-snapshots/</url>
    </snapshotRepository>
    </distributionManagement>

    </project>
  3. 添加maven解决依赖,可以解压jar查看具体版本(有的没有,可以上传到nexus仓库)

    注意:编译不报错,不代表maven依赖正确

  4. APP\src\main\webapp\WEB-INF\web.xml添加web.xml,里面有启动顺序

  5. 移动配置文件conf复制到APP\src\main\resources

  6. 代码如果采用绝对路径引用配置文件,去掉CONFIG_PATH = "/mybatis-config.xml";里面的/会读取默认的APP\src\main\resources目录下的配置文件

    注意:win10下注意tomcat的路径不能含空格等特殊符号,例如Program Files等,错误显示为某某文件找不到

常见问题

  1. 现象

    1
    2
    [WARNING] Using platform encoding (GBK actually) to copy filtered resources, i.e. build is platform dependent!
    [ERROR] /D:/xuan/workspace/ApiServer/src/main/java/com/xx/api/server/timer/BaseTimerTask.java:[25,77] 编码GBK的不 可映射字符

    解决:在pom.xml添加

    1
    2
    3
    4
    5
    6
    7
    <project ...> 
    <properties>
    <!--设置File encoding,没设置默认GBK会提示错误-->
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
    </properties>
    </project>
  2. [ERROR] /.../SysData.java:[12,81] -source 1.5 中不支持 diamond 运算符 (请使用 -source 7 或更高版本以启用 diamond 运算符)

    解决:在pom.xml添加

    1
    2
    3
    4
    5
    6
    7
    8
    <project ...> 
    <properties>
    <!--设置java编译版本-->
    <maven.compiler.source>1.7</maven.compiler.source>
    <maven.compiler.target>1.7</maven.compiler.target>
    <maven.compiler.compilerVersion>1.7</maven.compiler.compilerVersion>
    </properties>
    </project>
  3. NoClassDefFoundError: redis/clients/jedis/JedisCommands

    分析:编译打包时并没有任何错误,因为其他包里面有jedis的这个子包,所以编译通过了,但是运行时却找不到相应的版本所以导致该错

    解决:添加相应的jedis依赖

  4. SchedulerException: SchedulerPlugin class 'org.quartz.plugins.xml.XMLSchedulingDataProcessorPlugin' could not be instantiated.

    分析:因为使用声明式的不能直接分析出依赖问题

    解决:找到XMLSchedulingDataProcessorPlugin该class,复制该类的所有import到项目里面的一个随便的java文件,查看是否找不到包(有红线),然后添加缺的包的依赖

知识点

NoClassDefFoundError 一般是指没有jar

ClassNotFoundException和NoClassDefFoundError的区别