上周是到公司实习的第一周,在之后的工作中要用到Spring Boot,Git以及Docker等,就以一个简单的小项目为例学习了一下,现在做一个总结记录。
在之前的学习中用过maven作为构建工具,这里选择使用了Gradle。
我使用的IDE是Intellij IDEA,首先新建Gradle项目,填写完GroupId和ArtifactId之后,选中Use auto-import和Create directories for empty content roots automatically两个选项,这样就会自动为我们生成项目的目录结构,以及在修改build.gradle后自动导入。
接下来修改build.gradle:
plugins {
id 'java'
//intellij idea项目
id 'idea'
id 'org.springframework.boot' version '1.4.3.RELEASE'
}
group 'com.xxx.xxx'
version '1.0-SNAPSHOT'
repositories {
mavenCentral()
}
dependencies {
testCompile group: 'junit', name: 'junit', version: '4.12'
compile("org.springframework.boot:spring-boot-starter-web")
compile("org.springframework.boot:spring-boot-starter-thymeleaf")
}
由于是spring boot项目,这里在dependencies添加了spring-boot-starter-web依赖,并以thymeleaf作为模板引擎。
Spring Boot简化了Spring中大量的XML配置以及复杂的依赖管理,从上面可以看到,仅仅一行代码就可以导入所有需要用到的依赖包,无需我们手动配置xml文件,并且spring boot内嵌了Tomcat服务器。
既然不用我们自己去配置繁琐的xml文件,我们就可以专注于代码的编写了。首先在src/main/java文件夹内新建一个包,例如com.example.demo。对于这个简单的web服务,我们只需要一个控制器类TestController和一个启动类Application。
//TestController.java
package com.example.demo;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
@RequestMapping("/")
public class TestController {
@RequestMapping(method = RequestMethod.GET)
public String index(Model model) {
model.addAttribute("info", "hello thymeleaf!");
return "index";
}
@RequestMapping("/hello/{info}")
public @ResponseBody String hello(@PathVariable String info) {
return "hello spring boot!
Your info:" + info;
}
}
这里有两个方法,分别是index(对应路径:/)和hello(对应路径:/hello/?)。对于index方法,返回了字符串“index”,只要spring boot项目的类路径下有thymeleaf,那么就会自动去src/main/resources/templates目录下寻找index.html并返回。而对于hello方法,@PathVariable注解会解析请求url中的字符串,@ResponseBody 注解会将方法返回的字符串直接作为HTTP 响应正文返回。
//Application.java
package com.example.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.context.annotation.ComponentScan;
/**
* Created by mi on 2017/5/12.
*/
@ComponentScan
@EnableAutoConfiguration
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
这里启用了Spring Boot的组件扫描和自动配置功能,并启动了该应用。
使用thymeleaf模板引擎,页面的后缀名可以是html,而不是jsp。下面是index.html:
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8" />
<title>Indextitle>
head>
<body>
<span th:text="${info}">errorspan>
body>
html>
由于Spring Boot内嵌了Tomcat,接下来我们就可以直接运行Application类启动项目。
分别访问http://localhost:8080/和http://localhost:8080/hello/test,效果如下:
最后我们可以在项目根目录下,也就是build.gradle所在目录,执行gradle build命令生成jar包。这样就可以直接使用java -jar xxx.jar启动项目,也可以将jar包部署到docker中运行。
当已经通过gradle或者maven下载了所需的jar包,但是项目依然提示找不到类文件时,可以在File->Prject Structure->Dependencies中添加jar包。
在这里使用Git进行代码管理,可以上传到github或gitlab等仓库。
在终端进入到项目的根目录,执行以下命令:
git init
touch README
git add .
git commit -m 'first commit'
git remote add origin your_repository_address
git push -u origin master
git init会生成.git文件,这样项目就可以使用git进行管理了。第五个命令是添加上游地址并命名为origin,这样最后我们就可以使用-u指定上游的路径(这是指定的是origin),并将本地的master分支push上去。
类似于Git会有一个Github,docker也会有一个Docker Hub。我们在Docker Hub上注册账号之后,就可以将我们自己的镜像push上去。
首先我们会基于已有的镜像来构建,新建Dockerfile文件:
FROM azul/zulu-openjdk:8
VOLUME /tmp
ADD xxx.jar app.jar
ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar"]
然后运行sudo docker build -t loveqh/spring-boot-docker .就生成了docker镜像,可以通过sudo docker images命令进行查看所有镜像。
注:在使用Dockerfile生成镜像时,每一条语句都会生成一个新的层,因此为了节省空间,语句要尽可能的少,可以通过将多个命令合并到一条语句中。为了阅读方便和更好地复用(合理分层),在合并时应该合并一组功能相关的命令,如把添加和删除命令放在一起。
下一步就可以通过命令sudo docker run -p 80:8080 -it loveqh/spring-boot-demo启动一个容器。如果想要查看所有容器,可以使用sudo docker ps。
-p参数指定了端口映射关系,由于spring boot默认端口号是8080,这里我们把容器的8080端口映射到了host主机的80端口。接下来就和上面一样了,可以通过http://localhost进行访问。
首先我们需要在docker hub上注册一个账号,账号名要与刚刚镜像名中一致。
要想将镜像push到Docker Hub,我们需要在终端中使用sudo docker login登录。
然后使用sudo docker push loveqh/spring-boot-demo就可以推送上去了,这样我们就能在自己的Docker Hub主页中看到刚刚push的镜像了。