Liangwu's Notes

Just note anything

需求

之前团队从 SVN 已经转到 Git 管理代码了,但是但是大家还是非常不熟悉怎么管理,应该也是我没有把大家带入正轨吧,关于 GitFlow 没有好好给大家讲清楚,木办法。用Gogs 管理感觉不是太好,代码多了,团队项目多之后管理不是太方便。于是把目标转向了 Gitlab。但是发现服务器直接装 Gitlab 很不爽,要装一大垞东东。那就转为 Docker 吧,经过一些尝试,一段时间的运行非常不错,加上 Gitlab Runner 测试提交文件是否有问题。也可以直接用 Runner 来打包发布,但是暂时没用它,现在还是用 Jenkins 来进行发布。也比较好用了,大家代码提交合并后,一键发布代码。 :)

其中外网 IP 的 1111 端口映射到服务器的 5622 端口,但 5622 端口已用 nginx 反射代理了 nexus,所以 docker gitlab 在主要要换一个端口,暂时用了 18080。

安装 Gitlab

把 Docker 安装好,然后设置好代理,要不然的话,下载镜像实在是太太太太慢了。我用了两个代理,一个是官方的天朝代理,一个是中科大的代理。

1
2
3
4
5
6
7
{
"registry-mirrors": ["https://registry.docker-cn.com", "https://docker.mirrors.ustc.edu.cn"],
"insecure-registries": ["x.x.x.x:8088"],
"disable-legacy-registry": true,
"log-driver": "json-file",
"log-opts": { "max-size": "5m", "max-file": "3" }
}

然后就是开始拖镜像,运行容器了。再稍微进行一点配置就 OK。

前期准备工作

  • Host 有 git 用户
  • 生成 Host git 用户与 docker git 用户通信用的 ssh 密钥与公钥, ssh-keygen。公钥保存在/opt/gitlab/authorized_keys_proxy,密钥保存在/opt/gitlab/id_rsa
  • 找一份 sshd 配置文件拷贝一份至/opt/gitlab/sshd_config,修改一处AuthorizedKeysFile,让 Host git 用户用密钥登录至 docker gitlab。参考处
1
2
3
...
AuthorizedKeysFile %h/.ssh/authorized_keys /gitlab-data/ssh/authorized_keys ****重要****
...
  • 查看 git 用户 user id 和 group id,生成一份passwdgroup文件给 docker gitlab 使用,文件见文末,从 gitlab 中提取的。我服务器上分别是 1006 和 1008。为了保证 Host 和 docker gitlab 中的数据文件不会因为权限问题而无法使用。主要是 gitlab 中的用户 SSH Key 文件与 Host git 用户共享。
  • 在 Host 写个 bash 脚本,用于转发 Host 22 端口接收到 git 用户时转到 docker gitlab 去。
1
2
3
su - git
mkdir -p /opt/gitlab/data/.ssh
ln -sf /opt/gitlab/data/.ssh /home/git/.ssh
  • gitlab 用户用 SSH Key 进行 git 操作时,先连接到 Host,读取/home/git/.ssh/authorized_keys信息并验证,其中authorized_keys第一行告诉用户强制运行一条命令/opt/gitlab/embedded/service/gitlab-shell/bin/gitlab-shell,正好用此命令转发 git 命令至 docker gitlab。这点与gogs中的配置类似。
/opt/gitlab/embedded/service/gitlab-shell/bin/gitlab-shell
1
2
3
#!/bin/sh

ssh -i /opt/gitlab/id_rsa -p 12222 -o StrictHostKeyChecking=no git@127.0.0.1 "SSH_ORIGINAL_COMMAND=\"$SSH_ORIGINAL_COMMAND\" $0 $@"

运行 gitlab

1
2
3
4
5
6
7
8
9
10
11
12
13
14
docker pull gitlab/gitlab-ce:latest # 拉镜像文件
docker run -d -e -p 18080:5622 -p 12222:22 \
--name gitlab --restart always \ # restart always保证Docker服务启动时gitlab容器运行
-v /opt/gitlab/config:/etc/gitlab \ # 配置文件保存到Host,也可以用volume
-v /opt/gitlab/logs:/var/log/gitlab \ # 日志
-v /opt/gitlab/data:/var/opt/gitlab \ # 数据
-v /opt/gitlab/sshd_config:/etc/ssh/sshd_config:ro \ # 配置Host用密钥与docker gitlab通信
-v /opt/gitlab/authorized_keys_proxy:/gitlab-data/ssh/authorized_keys:ro \ # Host git用户密钥
-v /opt/gitlab/passwd:/etc/passwd:ro \ # git用户信息
-v /opt/gitlab/group:/etc/group:ro \ # git用户group信息
-v /usr/share/zoneinfo/Asia/Shanghai:/etc/timezone:ro \ # 时区
--ulimit sigpending=62793 --ulimit nproc=131072 \ # 优化参数
--ulimit nofile=60000 --ulimit core=0 \
gitlab/gitlab-ce:latest

配置 gitlab

docker ps查看 gitlab 容器运行成功后,停止容器运行,对 gitlab 进行配置。我的配置项如下。详细各配置项可见 gitlab.rb 的注释说明,或参照gitlab 官网说明

/opt/gitlab/config/gitlab.rb
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
external_url 'http://10.17.65.22:5622/gitlab'
gitlab_rails['gitlab_ssh_host'] = '10.17.65.22'
gitlab_rails['time_zone'] = 'Asia/Shanghai'
gitlab_rails['gitlab_email_enabled'] = true
gitlab_rails['gitlab_email_from'] = 'admin@guoliangwu.com'
gitlab_rails['gitlab_email_display_name'] = 'Admin'
gitlab_rails['gitlab_email_reply_to'] = 'no_reply@guoliangwu.com'
gitlab_rails['gitlab_username_changing_enabled'] = false
gitlab_rails['gitlab_default_theme'] = 4
gitlab_rails['gitlab_default_projects_features_snippets'] = false
gitlab_rails['gitlab_default_projects_features_builds'] = false
gitlab_rails['gitlab_default_projects_features_container_registry'] = false
gitlab_rails['incoming_email_enabled'] = false
gitlab_rails['smtp_enable'] = true
gitlab_rails['smtp_address'] = "smtp.guoliangwu.com"
gitlab_rails['smtp_port'] = 465
gitlab_rails['smtp_user_name'] = "admin@guoliangwu.com"
gitlab_rails['smtp_password'] = "xxxx"
gitlab_rails['smtp_domain'] = "guoliangwu.com"
gitlab_rails['smtp_authentication'] = "login"
gitlab_rails['smtp_enable_starttls_auto'] = true
gitlab_rails['smtp_tls'] = true
gitlab_rails['registry_enabled'] = false
unicorn['worker_processes'] = 4
sidekiq['concurrency'] = 15
postgresql['shared_buffers'] = "2GB"
prometheus['enable'] = false

end

至此,Gitlab 应该能欢快地跑起来了。后面我在其它服务器配了 gitlab runner 来检查上传的代码是否有问题,不知道有没有时间深入了解 runner,先把.gitlab-ci.yml传上来,以备以后使用吧。PS:因为以后打包发布什么的都要用 maven,就用了 maven 镜像。

.gitlab.yml
1
2
3
4
5
6
7
8
9
10
image: maven:latest

test:
stage: test
script:
- test $(find shanghai/service -name "*.properties" -path "*/properties/*" | wc -l) -eq 0
- test $(find shanghai/web -name "index.js" -path "*/config/*" | wc -l) -eq 0
- test $(find shanghai/web -name "*.vue" -type f -exec grep -E 'debugger|console\.log' {} \; | wc -l) -eq 0
tags:
- common

passwd

/etc/gitlab/passwd
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
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/usr/sbin/nologin
man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
mail:x:8:8:mail:/var/mail:/usr/sbin/nologin
news:x:9:9:news:/var/spool/news:/usr/sbin/nologin
uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin
proxy:x:13:13:proxy:/bin:/usr/sbin/nologin
www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin
backup:x:34:34:backup:/var/backups:/usr/sbin/nologin
list:x:38:38:Mailing List Manager:/var/list:/usr/sbin/nologin
irc:x:39:39:ircd:/var/run/ircd:/usr/sbin/nologin
gnats:x:41:41:Gnats Bug-Reporting System (admin):/var/lib/gnats:/usr/sbin/nologin
nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin
systemd-timesync:x:100:102:systemd Time Synchronization,,,:/run/systemd:/bin/false
systemd-network:x:101:103:systemd Network Management,,,:/run/systemd/netif:/bin/false
systemd-resolve:x:102:104:systemd Resolver,,,:/run/systemd/resolve:/bin/false
systemd-bus-proxy:x:103:105:systemd Bus Proxy,,,:/run/systemd:/bin/false
_apt:x:104:65534::/nonexistent:/bin/false
sshd:x:105:65534::/var/run/sshd:/usr/sbin/nologin
git:x:1006:1008::/var/opt/gitlab:/bin/sh ****注意****
gitlab-www:x:999:999::/var/opt/gitlab/nginx:/bin/false
gitlab-redis:x:997:997::/var/opt/gitlab/redis:/bin/false
gitlab-psql:x:996:996::/var/opt/gitlab/postgresql:/bin/sh
mattermost:x:994:994::/var/opt/gitlab/mattermost:/bin/sh
registry:x:993:993::/var/opt/gitlab/registry:/bin/sh
gitlab-prometheus:x:992:992::/var/opt/gitlab/prometheus:/bin/sh
gitlab-consul:x:991:991::/var/opt/gitlab/consul:/bin/sh

group

/opt/gitlab/group
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
root:x:0:
daemon:x:1:
bin:x:2:
sys:x:3:
adm:x:4:
tty:x:5:
disk:x:6:
lp:x:7:
mail:x:8:
news:x:9:
uucp:x:10:
man:x:12:
proxy:x:13:
kmem:x:15:
dialout:x:20:
fax:x:21:
voice:x:22:
cdrom:x:24:
floppy:x:25:
tape:x:26:
sudo:x:27:
audio:x:29:
dip:x:30:
www-data:x:33:
backup:x:34:
operator:x:37:
list:x:38:
irc:x:39:
src:x:40:
gnats:x:41:
shadow:x:42:
utmp:x:43:
video:x:44:
sasl:x:45:
plugdev:x:46:
staff:x:50:
games:x:60:
users:x:100:
nogroup:x:65534:
systemd-journal:x:101:
systemd-timesync:x:102:
systemd-network:x:103:
systemd-resolve:x:104:
systemd-bus-proxy:x:105:
ssh:x:106:
git:x:1008: ****注意****
gitlab-www:x:999:
gitlab-redis:x:997:
gitlab-psql:x:996:
mattermost:x:994:
registry:x:993:
gitlab-prometheus:x:99

问题

之前团队一直用的Subversion来管理代码的,开发的时候还OK,但是到了上线后,问题就开始出现,往往发布了一个版本后,代码又有一部分提交,同时可能引进一些新的Bug,再发包的时候,又有新的Bug,很不爽。本身SVN的分支管理不好用,我就强烈推荐Git,之前也一直在用,直接在服务器上开SSH端口就OK,但是权限管理又是一个问题啊,又找了一些Git权限管理的东东,但都太理想。后来想是不是有Github一样的东东,后来就发现了Gitlab,但是这货太耗资源,而且搭建起来也不容易,其他人去维护它就很困难。后来一顿放狗搜,找到了一个比较好的替代Gogs,上周末两天基本就在搞这货,使用起来也是很不错的。花时间的部分主要是与主机共享22端口的问题。

现在服务器那边的环境是,服务器位于防火墙后面,防火墙只开了有限供外网使用的端口,所以Gogs必须在某个共用端口的子目录下进行访问,比如domain.com/git/。防火墙8888端口映射到服务器4444端口,然后服务器4444端口再映射到Gogs Container的3000端口。

Docker Gogs安装

其实用Docker来安装Gogs很简单,直接参考官方的文档主OK了。

1
2
3
4
5
6
7
8
9
10
11
12
13
# Pull image from Docker Hub.
$ docker pull gogs/gogs

# Create local directory for volume.
$ mkdir -p /var/gogs

# Use `docker run` for the first time.
$ docker run --name=gogs -p 10022:22 -p 10080:3000 -v /var/gogs:/data gogs/gogs
# 下面是我的配置
$ docker run --name gogs -p 3000:3000 -p 10022:22 --link mysql:db -v /opt/my_gogs:/data -e "PUID=1002" -e "PGID=1002" -d gogs/gogs

# Use `docker start` if you have stopped it.
$ docker start gogs

其中我运行Gogs的时候加了一些东西。将前端端口映射到Host的3000端口,将Container的SSH端口22映射到Host的1022端口,然后将另一个mysql的Container链接到Gogs,这样可以直接访问MySQL,然后就是将Gogs的配置文件和其它工作文件链接到Host的gogs目录下,然后就是设置Gogs Containerm里面git用户的uid和gid。如果不设置uid和gid的话,container默认的是1000,一般情况下都不是我们想要的结果。一般是在Host新建一个git的用户,将container的uid和gid设置成Host上git用户对应的值,比如我的就是1002和1002。

Gogsl配置

Docker Gogs运行起来后,就可以直接浏览器连3000端口进行配置,配置界面很明了,一看就OK。但此时我用的MySQL也是用的Docker,因为之前用了--link mysql:db,表示我有一个container的名称为mysql,映射到gogs的container的名称为db,这样我可以直接用db:3306就可以连上了。在配置界面点确定前,需要在MySQL里新建一个仓,具体代码可以参考官方脚本

等界面配置好后就再对Gogs进行详细的修改,具体可以参考官方文档

app.ini
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
APP_NAME = Gogs
RUN_USER = git
RUN_MODE = prod

[database]
DB_TYPE = mysql
HOST = db:3306
NAME = gogs
USER = root
PASSWD = mysql_password
SSL_MODE = disable
PATH = data/gogs.db

[repository]
ROOT = /data/git/gogs-repositories
FORCE_PRIVATE = true
DISABLE_HTTP_GIT = true

[repository.upload]
ENABLED = false

[server]
DOMAIN = yourdomain.com
HTTP_PORT = 3000
ROOT_URL = http://localhost:3000/git/
DISABLE_SSH = false
SSH_PORT = 22
START_SSH_SERVER = false
OFFLINE_MODE = false

[mailer]
ENABLED = true
DISABLE_HELO = true
HOST = smtp.xxx.com:587
SUBJECT = GIT
FROM = "GIT" <xxx@xxx.com>
USER = xxx@xxx.com
PASSWD = xxx
SKIP_VERIFY = false
USE_PLAIN_TEXT = false

[service]
REGISTER_EMAIL_CONFIRM = true
ENABLE_NOTIFY_MAIL = true
DISABLE_REGISTRATION = true
ENABLE_CAPTCHA = true
REQUIRE_SIGNIN_VIEW = true

[picture]
DISABLE_GRAVATAR = true
ENABLE_FEDERATED_AVATAR = true

[session]
PROVIDER = file

[log]
MODE = file
LEVEL = Info
ROOT_PATH = /app/gogs/log

[security]
INSTALL_LOCK = true
SECRET_KEY = qHtSV2KhCcMA0Xl

[other]
SHOW_FOOTER_BRANDING = false
SHOW_FOOTER_VERSION = false
SHOW_FOOTER_TEMPLATE_LOAD_TIME = false

现在可以在浏览http://localhost:3000/git/来访问页面了。

Nginx反向代理

对于Nginx反向代理官方也给出了具体配置,还包括Apache和Lighttpd。其中Nginx中很重要的一点就是必须**要最后的反斜框[/]**。

1
2
3
4
5
6
location /git/ {
proxy_pass http://localhost:3000/;
}
location = /git {
proxy_pass http://localhost:3000/;
}

官方文档只提到了上面的一条,后面一条是根据我的实情情况加的。我发现登录的时候,点一次登录好长时间没有反应,过段时间后,返回的地址却是domain.com:4444/git/,很无语,不知道为啥跳到4444端口呢。后来发现登录跳转的路径是domain.com/git,没有最后的一个反斜框,Nginx无法知道怎么代理,这块搞了我快一两个小时,一直没有查出来原因。后来加了下面一条就解决了。

与Host共享22端口的问题

刚开始放狗搜了好久,都没有好的解决方案,有的提到sshd_config里面使用ForceCommand,看着比较靠谱,但好像也不成功。后来发现官方文档推荐一篇不错的文章。看守实操了一遍,大致原理是Host和Container用同一个uid的用户(假定为git),这时候连接到Host的git用户再转到container的10022端口,并运行特定的命令来进行git操作。

新建git用户

1
2
3
4
5
6
7
8
9
$ sudo useradd -s /bin/bash -d /opt/my_gogs -m git
$ id git
uid=1002(git) gid=1002(git) groups=1002(git)
$ su - git
$ cd ~
$ ssh-key -t rsa
$ cd ~/.ssh
$ cat id_rsa.pub >> authorized_keys
$ chmod 600 authorized_keys

这里我新建的git用户的uid和gid是1002,与之前运行gogs container需要对应。同时为了安全起见,将authorized_keys前加一些配置。

1
no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty rsa...

字面意思就很好理解了。因为之前Docker运行Gogs时已经设置-v /opt/my_gogs:/data -e "PUID=1002" -e "PGID=1002", 这样在Host和Container的git用户主目录是同一个,uid和gid也一样,这样Host的git用户直接ssh -p 10022 127.0.0.1是可以直接连接到Container的。

配置git用户登录问题

经过上面一步的设置,在外网就可以直接用git用户的密钥进行登录了,但是因为安全设置,没有tty等。然后就是设置像github那样,用户自己在web端导入自己的公钥,就可以用密钥拉取、推送代码。新建/app/gogs/gogs,脚本如下。

1
2
3
4
5
6
7
mkdir -p /app/gogs/
cat >/app/gogs/gogs <<'END'
#!/bin/sh
ssh -p 10022 -o StrictHostKeyChecking=no git@127.0.0.1 \
"SSH_ORIGINAL_COMMAND=\"$SSH_ORIGINAL_COMMAND\" $0 $@"
END
chmod 755 /app/gogs/gogs

对共享22端口不熟悉的话,可以认真看看这篇文件。SSH真是神器。 :) Happy coding…

正式全职做开发已经半年了,两台服务器作开发,Oracle/MySQL/Nexus/Jenkins/Redis/ActiveMQ,一大堆的东东,还好有一些Linux的经验(上次CentOS被人挖矿,下次再说如何抓别人的),搭建这些东西都是比较容易的,当然不包括调优。就算自己搭建这些东西不难,但是真的比较费时间。后来有一个想法就是用Docker,今天搞了大半天终于搞定了。记下来,便于以后自己翻查吧。

后台架构

前台用的是Vue来开发,后台Nginx处理静态文件,反向代理请求到Tomcat,Tomcat再到Redis/ActiveMQ/MySQL。

所以后台需要Nginx, Tomcat, Redis, MySQL这些软件。根据调用关系,先把底层的服务开启。Docker安装就看官方文档吧。

Redis服务

首先将Redis的镜像(image)给拉到本地,然后开动。

1
2
3
4
5
6
7
docker pull redis
docker run --name redis -p 6379:6379 --privileged -v `pwd`/redis:/data -v `pwd`/redis/redis.conf:/etc/redis/redis.conf -v /etc/localtime:/etc/localtime -v /etc/timezone:/etc/timezone -d redis redis-server /etc/redis/redis.conf
-----
docker exec -it redis /bin/bash
echo "vm.overcommit_memory = 1" >> /etc/sysctl.conf
echo "net.core.somaxconn = 65536" >> /etc/sysctl.conf
sysctl -p

docker run里面的参数含义分别是:

  • name:给container取名字,方便以后操作,要不得填container ID,很不友好。
  • p:官方解释Publish a container's port(s) to the host,我的理解就是相当于一个端口映射吧。将主机的端口映射到容器的端口。
  • privileged:官方解释Give extended privileges to this container,主要是要修改一些container参数,要不会提示一些Warning。
  • v:Bind mount a volume,将host文件或目录挂载到container,这样可以直接在host修改一些配置文件或container产生的一些文件存在host。
  • d:Run container in background and print container ID,后台运行。

然后redis需要远程访问,就要修改redis.conf,把bind给注释掉,protedted-mod改为no

MySQL服务

1
docker run --name mysql -e MYSQL_ROOT_PASSWORD=your-mysql-root-password -p 3306:3306 -v `pwd`/mysql:/var/lib/mysql -v /etc/localtime:/etc/localtime -v /etc/timezone:/etc/timezone -d mysql/mysql-server

注意将其中的your-mysql-root-password改为自己的密码。

这时MySQL的root不能远程访问,放狗搜的话一大堆。

1
2
docker exec -it mysql /bin/bash
mysql -u root -p
1
2
GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' IDENTIFIED BY 'your-mysql-root-password' WITH GRANT OPTION;
FLUSH RIVILEGES

Tomcat服务

1
docker run --name tomcat -p 8080:8080 -v `pwd`/tomcat/webapps:/usr/local/tomcat/webapps -v `pwd`/tomcat/conf/tomcat-users.xml:/usr/local/tomcat/conf/tomcat-users.xml -v /etc/localtime:/etc/localtime -v /etc/timezone:/etc/timezone --link redis:redis --link mysql:mysql -d andreptb/tomcat

--link主要是一个container连接到另一个contaner,好像是在container的/etc/hosts加上到另一个容器的地上,然后environment里加一些环境变量。这个只是我的猜测,等过段里子好好看看Docker的文件后再深入了解下。

这样在tomcat的应用中可以把jdbc.url里的host直接填mysql,redis的host填redis。比如jdbc.url=jdbc:mysql://mysql:3306/test

Nginx服务

1
docker run --name nginx -p 80:80 -v `pwd`/nginx/html:/usr/share/nginx/html -v `pwd`/nginx/nginx.conf:/etc/nginx/nginx.conf -v `pwd`/nginx/conf.d:/etc/nginx/conf.d -v /etc/localtime:/etc/localtime -v /etc/timezone:/etc/timezone --link tomcat:tomcat -d nginx
/etc/nginx/nginx.conf
1
2
3
4
5
6
7
8
9
10
11
12
#...
http {
upstream backend {
server tomcat:8080;
}

fastcgi_intercept_errors on;
proxy_intercept_errors on;

include /etc/nginx/conf.d/*.conf;
#...
}
/etc/nginx/conf.d/default.conf
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
server {
#...
location /service/ {
proxy_pass http://backend;
proxy_set_header Host $host;
proxy_set_header X-Remote-Addr $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}

location ^~ /pic/ {
root /opt/web;
index index.html;

location ~* \.(jpe?g|png|bmp|pdf)$ {
try_files $uri $uri/ /pic/default.png;
}
}
#...
}

嗯,好久好久没有写东西了。下次再讲讲jenkins吧,这个东东解放了好多时间,现在项目中我只是让它自己打包,打包出错时发送邮件。部署的话还没有去实现,主要是现阶段的代码问题太多了。现在还在思考一个问题,是否可以将Docker用于生产环境,然后学习下自己制作Dockerfile,这样我就可以把上面所有的服务打成一个Dockerfile,给别人一个Dockerfile就可以直接用来开发,完全不用自己再去搭环境了。

MyBatis开始写基础的SQL蛮麻烦的,放Google搜了搜,发现有个不错的插件MyBatis-Plugin,可以自动生成这些CRUD的基础语句,OK就用它了。至于如何激活,呵呵。。

MyBatis-Generator配置

直接在resources用插件新建文件mybatis-generator-config.xml,然后编辑其中注释中带!!!!的地方,主要有以下几个地方。

mybatis-generator-config.xml
1
2
3
4
5
6
7
8
9
10
11
12
<!-- !!!! Driver Class Path !!!! -->

<!-- !!!! Database Configurations !!!! -->

<!-- !!!! Model Configurations !!!! -->

<!-- !!!! Mapper XML Configurations !!!! -->

<!-- !!!! Mapper Interface Configurations !!!! -->

<!-- !!!! Table Configurations !!!! -->

其中Driver Class Path当时用最新的6.0.4,无法自己生成,放狗搜了后,改成低版本就OK了。

然后另一个问题就是表与Domain类名字、域名字不相同的情况,直接在Table Configurations里面改就好。

mybatis-generator-config.xml
1
2
3
4
<table tableName="t_teacher" enableCountByExample="false" enableDeleteByExample="false" enableSelectByExample="false"
enableUpdateByExample="false" domainObjectName="Teacher">
<columnRenamingRule searchString="t_" replaceString=""/>
</table>

重点就是tableName,domainObjectName, columnRenameingRule,从字面意思就好理解。

MyBatis Mapper日志中显示SQL语句

在日志方面选择过好几次log4j, log4j2,后来改成了logback,显示SQL语句只需要在配置文件中增加一条。

logback.xml
1
<logger name="com.liangwu.courses.domain.mapper" level="DEBUG"></logger>

插入新数据后,获取ID

一般主键ID都是自动生成的,所以插入新数据的时候ID都是数据库自动生成的,如何在插入数据后Domain获得这个ID呢,最开始自己脑子发热,插入后查询。后来放狗搜,在配置文件里面改改就OK。

mybatis-generator-config.xml
1
2
3
4
<insert id="insert" parameterType="com.liangwu.courses.domain.Teacher" useGeneratedKeys="true" keyColumn="t_id" keyProperty="id" >
insert into t_teacher (t_name, t_gender)
values (#{name,jdbcType=VARCHAR}, #{gender,jdbcType=BIT})
</insert>

在insert配置的时候加useGeneratedKeys="true" keyColumn="t_id" keyProperty="id"三项,insert后就可以直接getId()了。

之前家里用的是DB120-WG,双USB口,16M Flash,64M RAM。用起来爽爽的,刷OpenWrt,接移动硬盘,transmission和Aria2离线下载,设置Shadowsocks,自动配置翻墙。可惜有次吵架,被老婆一脚给踩坏了,唉。后来通过闲鱼重新购入一枚Netgear WNDR3400,这家伙体质没有DB120-WG来得好,Flash、RAM小,无线的驱动不理想,不过还好基本功能能满足,可以刷OpenWrt和dd-Wrt。

Read more »

Spring MyBatis小试

之前了解过Hibernate,感觉不写SQL语句好爽啊。后来写了一个小程序用来计算东西,用Hibernate,但是War包实在是太大了,想要减小下体积,于是试了试MyBatis,感觉不错。写下来方便以后使用。主要是参考了MyBatis官方的文章MyBatisMyBatis-Spring

搭建环境

IDE用的Intellij IDEA,数据库用的H2 Database,包管理Gradle,日志Log4j,然后MyBatis,数据用的是Oracle数据库自带的测试数据UTLSAMPLE.sql。其中build.gradle如下。

Read more »

Eclipse出现问题

在前两天BuildShip升级后就出现问题,导致Eclipse中使用Gradle不方便,算了直接试试神器Intellij Idea吧。之前各版本信息:Eclipse(Version: Neon.2 Release (4.6.2)),BuildShip(Version: 2.0.0.v20170111-2019),Gradle(Version: 3.3)

转向Idea

好嘛,直接导入build.gradle就好了。如果之前不是用Gradle创建的工程,直接在项目目录下加入build.gradle重新导入就可以正常工作。之前在Eclipse中的build.gradle,供以后参考 :)

Read more »

问题

之前写小程序的时候,有一段代码如下。

1
2
3
for (item in data){
do(item);
}

在Chrome和Firefox下运行都没有问题,但在IE11中就出现错误。错误显示item navie code(),好吧,放狗搜呗。在StackOverflow上找到了答案,原来M$ IE在内部定义了item这个变量,无法使用,问题清楚,直接换个变量名就OK了。

VPS自动发布Blog

前文部署到VPS后无法正常工作,而利用git hooks可以解决自动布置的问题。在VPS仓接收receive到同步后,自动将文件同步到Web目录。

blog.git/hooks/post-receive
1
2
#!/bin/bash
git --work-tree=/wwwroot/notes.guoliangwu.com --git-dir=/xxx/xxx/blog.git checkout -f
Read more »

问题

之前写了一个小的燃烧计算程序,其中有一部分是为了计算混合组分的特性参数,用了下面的一些代码。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public interface ComponentCal extends Map<String, Double> {
public double getDensity();

public double getQd();

public double getQg();

public double getL_O2();

public double getCp(double temperature);

public double getC();

public double getH();
}
Read more »
0%