环境
- 操作系统:Ubuntu 20.04
- 开发工具:IntelliJ IDEA 2020.1.2 (Community Edition)
- JDK:
➜ ~ java -version
openjdk version "14.0.1" 2020-04-14
OpenJDK Runtime Environment (build 14.0.1+7-Ubuntu-1ubuntu1)
OpenJDK 64-Bit Server VM (build 14.0.1+7-Ubuntu-1ubuntu1, mixed mode, sharing)
- Maven:
➜ ~ mvn -v
Apache Maven 3.6.3
Maven home: /usr/share/maven
Java version: 14.0.1, vendor: Private Build, runtime: /usr/lib/jvm/java-14-openjdk-amd64
Default locale: en_US, platform encoding: UTF-8
OS name: "linux", version: "5.4.0-37-generic", arch: "amd64", family: "unix"
配置
配置环境变量
修改 ~/.bashrc
文件,添加配置 JAVA_HOME
和M2_HOME
变量如下:
export JAVA_HOME=/usr/lib/jvm/java-14-openjdk-amd64
export M2_HOME=/usr/share/maven
保存退出,运行 . ~/.bashrc
使之生效。
如果配置了其它shell为默认shell,则需要修改相应的配置文件。比如我配置了zsh为默认shell,则需要修改 ~/.zshrc
文件,然后运行 . ~/.zshrc
使之生效。
注:可用 echo $SHELL
查看默认shell:
➜ ~ echo $SHELL
/usr/bin/zsh
注:可用 echo $0
查看当前shell:
➜ Downloads echo $0
/usr/bin/zsh
配置Maven镜像
打开 settings.xml
(在本例中,其路径为 /usr/share/maven/conf/settings.xml
),在 <mirrors>......</mirrors>
之间添加aliyun的nexus server镜像:
......
<mirror>
<id>alimaven</id>
<mirrorOf>central</mirrorOf>
<name>aliyun maven</name>
<url>http://maven.aliyun.com/nexus/content/groups/public</url>
</mirror>
......
将 settings.xml
复制到 ~/.m2/
目录下:
➜ ~ cp /usr/share/maven/conf/settings.xml ~/.m2/
这是因为,按照惯例,前者是全局配置文件,而后者是当前用户的配置文件。本例中,接下来会在IntelliJ IDEA里面配置Maven settings file为当前用户的设置文件。
配置IntelliJ IDEA
配置Maven路径
File -> Settings… ,如下图所示:
安装Spring Assistant插件
File -> Settings… -> Plugins,点击“Marketplace”,搜索关键字“Spring”,找到“Spring Assistant”并安装,如下图所示:
编写代码
以上准备工作全部完毕,现在就可以开始编写代码了。
新建Project,选择“Spring Assistant”,如下图所示:
下一步,填写Project信息,如下图所示:
下一步,搜索“web”,并选中 Spring Web
,如下图所示:
最终生成的Project结构如下图所示:
这时Project里可能会有一些错误,这是因为缺少所需的依赖包。从右侧的Maven窗口,选择“compile”,下载所需的依赖包。
这时就可以运行程序了,打开 Demo0621Application.java
,点击绿色小箭头,并选择 Run
,如下图所示:
程序启动后,如下图所示:
可见,Tomcat在8080端口已经启动。测试一下8080端口的连通性:
➜ ~ nc -zv localhost 8080
Connection to localhost 8080 port [tcp/http-alt] succeeded!
但是由于目前还没有任何Controller,所以访问server会报404错误:
➜ ~ curl --silent --write-out '\n%{http_code}\n' -XGET "http://localhost:8080/" | jq .
{
"timestamp": "2020-06-21T02:58:23.082+00:00",
"status": 404,
"error": "Not Found",
"message": "",
"path": "/"
}
404
现在我们来添加一个名为“hello”的Controller。
新建Java class “Test0621”,内容如下:
package com.example.demo0621;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class Test0621 {
@RequestMapping("/hello")
public String hello() {
return "hello world!";
}
}
如下图所示:
重新启动程序,现在就可以访问 /hello
了。
➜ ~ curl --silent --write-out '\n%{http_code}\n' -XGET "http://localhost:8080/hello"
hello world!
200
程序的console输出如下:
/home/ding/.jdks/openjdk-14.0.1/bin/java -javaagent:/snap/intellij-idea-community/232/lib/idea_rt.jar=43913:/snap/intellij-idea-community/232/bin -Dfile.encoding=UTF-8 -classpath /home/ding/IdeaProjects/demo0621/target/classes:/home/ding/.m2/repository/org/springframework/boot/spring-boot-starter-web/2.3.1.RELEASE/spring-boot-starter-web-2.3.1.RELEASE.jar:/home/ding/.m2/repository/org/springframework/boot/spring-boot-starter/2.3.1.RELEASE/spring-boot-starter-2.3.1.RELEASE.jar:/home/ding/.m2/repository/org/springframework/boot/spring-boot/2.3.1.RELEASE/spring-boot-2.3.1.RELEASE.jar:/home/ding/.m2/repository/org/springframework/boot/spring-boot-autoconfigure/2.3.1.RELEASE/spring-boot-autoconfigure-2.3.1.RELEASE.jar:/home/ding/.m2/repository/org/springframework/boot/spring-boot-starter-logging/2.3.1.RELEASE/spring-boot-starter-logging-2.3.1.RELEASE.jar:/home/ding/.m2/repository/ch/qos/logback/logback-classic/1.2.3/logback-classic-1.2.3.jar:/home/ding/.m2/repository/ch/qos/logback/logback-core/1.2.3/logback-core-1.2.3.jar:/home/ding/.m2/repository/org/apache/logging/log4j/log4j-to-slf4j/2.13.3/log4j-to-slf4j-2.13.3.jar:/home/ding/.m2/repository/org/apache/logging/log4j/log4j-api/2.13.3/log4j-api-2.13.3.jar:/home/ding/.m2/repository/org/slf4j/jul-to-slf4j/1.7.30/jul-to-slf4j-1.7.30.jar:/home/ding/.m2/repository/jakarta/annotation/jakarta.annotation-api/1.3.5/jakarta.annotation-api-1.3.5.jar:/home/ding/.m2/repository/org/yaml/snakeyaml/1.26/snakeyaml-1.26.jar:/home/ding/.m2/repository/org/springframework/boot/spring-boot-starter-json/2.3.1.RELEASE/spring-boot-starter-json-2.3.1.RELEASE.jar:/home/ding/.m2/repository/com/fasterxml/jackson/core/jackson-databind/2.11.0/jackson-databind-2.11.0.jar:/home/ding/.m2/repository/com/fasterxml/jackson/core/jackson-annotations/2.11.0/jackson-annotations-2.11.0.jar:/home/ding/.m2/repository/com/fasterxml/jackson/core/jackson-core/2.11.0/jackson-core-2.11.0.jar:/home/ding/.m2/repository/com/fasterxml/jackson/datatype/jackson-datatype-jdk8/2.11.0/jackson-datatype-jdk8-2.11.0.jar:/home/ding/.m2/repository/com/fasterxml/jackson/datatype/jackson-datatype-jsr310/2.11.0/jackson-datatype-jsr310-2.11.0.jar:/home/ding/.m2/repository/com/fasterxml/jackson/module/jackson-module-parameter-names/2.11.0/jackson-module-parameter-names-2.11.0.jar:/home/ding/.m2/repository/org/springframework/boot/spring-boot-starter-tomcat/2.3.1.RELEASE/spring-boot-starter-tomcat-2.3.1.RELEASE.jar:/home/ding/.m2/repository/org/apache/tomcat/embed/tomcat-embed-core/9.0.36/tomcat-embed-core-9.0.36.jar:/home/ding/.m2/repository/org/glassfish/jakarta.el/3.0.3/jakarta.el-3.0.3.jar:/home/ding/.m2/repository/org/apache/tomcat/embed/tomcat-embed-websocket/9.0.36/tomcat-embed-websocket-9.0.36.jar:/home/ding/.m2/repository/org/springframework/spring-web/5.2.7.RELEASE/spring-web-5.2.7.RELEASE.jar:/home/ding/.m2/repository/org/springframework/spring-beans/5.2.7.RELEASE/spring-beans-5.2.7.RELEASE.jar:/home/ding/.m2/repository/org/springframework/spring-webmvc/5.2.7.RELEASE/spring-webmvc-5.2.7.RELEASE.jar:/home/ding/.m2/repository/org/springframework/spring-aop/5.2.7.RELEASE/spring-aop-5.2.7.RELEASE.jar:/home/ding/.m2/repository/org/springframework/spring-context/5.2.7.RELEASE/spring-context-5.2.7.RELEASE.jar:/home/ding/.m2/repository/org/springframework/spring-expression/5.2.7.RELEASE/spring-expression-5.2.7.RELEASE.jar:/home/ding/.m2/repository/org/slf4j/slf4j-api/1.7.30/slf4j-api-1.7.30.jar:/home/ding/.m2/repository/org/springframework/spring-core/5.2.7.RELEASE/spring-core-5.2.7.RELEASE.jar:/home/ding/.m2/repository/org/springframework/spring-jcl/5.2.7.RELEASE/spring-jcl-5.2.7.RELEASE.jar com.example.demo0621.Demo0621Application
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v2.3.1.RELEASE)
2020-06-20 20:08:38.135 INFO 5499 --- [ main] c.example.demo0621.Demo0621Application : Starting Demo0621Application on ubuntu with PID 5499 (/home/ding/IdeaProjects/demo0621/target/classes started by ding in /home/ding/IdeaProjects/demo0621)
2020-06-20 20:08:38.138 INFO 5499 --- [ main] c.example.demo0621.Demo0621Application : No active profile set, falling back to default profiles: default
2020-06-20 20:08:39.707 INFO 5499 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port(s): 8080 (http)
2020-06-20 20:08:39.722 INFO 5499 --- [ main] o.apache.catalina.core.StandardService : Starting service [Tomcat]
2020-06-20 20:08:39.723 INFO 5499 --- [ main] org.apache.catalina.core.StandardEngine : Starting Servlet engine: [Apache Tomcat/9.0.36]
2020-06-20 20:08:39.814 INFO 5499 --- [ main] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext
2020-06-20 20:08:39.814 INFO 5499 --- [ main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 1606 ms
2020-06-20 20:08:40.051 INFO 5499 --- [ main] o.s.s.concurrent.ThreadPoolTaskExecutor : Initializing ExecutorService 'applicationTaskExecutor'
2020-06-20 20:08:40.273 INFO 5499 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 8080 (http) with context path ''
2020-06-20 20:08:40.286 INFO 5499 --- [ main] c.example.demo0621.Demo0621Application : Started Demo0621Application in 2.968 seconds (JVM running for 4.244)
2020-06-20 20:09:03.378 INFO 5499 --- [nio-8080-exec-1] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring DispatcherServlet 'dispatcherServlet'
2020-06-20 20:09:03.379 INFO 5499 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : Initializing Servlet 'dispatcherServlet'
2020-06-20 20:09:03.387 INFO 5499 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : Completed initialization in 8 ms
测试
在创建Project的时候,Spring Boot已经帮我们生成好了一个空的测试框架,其结构为: src -> test -> java -> com.example.demo0621 -> Demo0621ApplicationTests
,如下图所示:
pom.xml
里面也已经配置好了相关依赖。
此时虽然还没有写测试代码,但我们可以先运行一下maven的test,下载所需的依赖包:
在package com.example.demo0621
里面新建Java class Test0621Test
,内容如下:
package com.example.demo0621;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.web.client.RestTemplate;
@SpringBootTest
@RunWith(SpringRunner.class)
public class Test0621Test {
@Test
public void testHello(){
RestTemplate restTemplate = new RestTemplate();
String result = restTemplate.getForObject("http://localhost:8080/hello", String.class);
Assert.assertEquals("hello world!", result);
System.out.println(result);
}
}
如下图所示:
测试逻辑非常简单,就是获取 /hello
的response,然后和 hello world!
做对比。
直接运行测试,会报错:
这是因为server还没有启动,所以会报错:
org.springframework.web.client.ResourceAccessException: I/O error on GET request for "http://localhost:8080/hello": Connection refused; nested exception is java.net.ConnectException: Connection refused
把server启动起来,再次运行test,就会success:
如果想要通过maven的test来测试代码,可以直接把测试逻辑写在 Demo0621ApplicationTests.java
里面。
同样的,在测试之前,需要先把server启动起来,否则会测试失败。
测试过程和结果如下图所示:
打包
在项目开发完成之后,就可以打包发布。传统的web应用一般打包为war包。本例中已经内嵌了Tomcat容器,所以打包为jar包。
File -> Project Structure... -> Artifacts
,点击 +
按钮,选择 JAR -> From modules with dependencies...
:
在弹出的对话框中, Main Class
处,选择 Demo0621Application
,如下图所示:
Maven clean
,然后 Maven package
,就会生成jar包。在console里面可以看到jar包的具体路径,本例中为 /home/ding/IdeaProjects/demo0621/target/demo0621-0.0.1-SNAPSHOT.jar
。具体操作如下图所示:
在该目录下,运行 java -jar demo0621-0.0.1-SNAPSHOT.jar
就可以启动server(别忘了先停掉IntelliJ IDEA里面的server):
➜ java -jar demo0621-0.0.1-SNAPSHOT.jar
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v2.3.1.RELEASE)
2020-06-20 23:33:38.473 INFO 8227 --- [ main] c.example.demo0621.Demo0621Application : Starting Demo0621Application v0.0.1-SNAPSHOT on ubuntu with PID 8227 (/home/ding/IdeaProjects/demo0621/target/demo0621-0.0.1-SNAPSHOT.jar started by ding in /home/ding/IdeaProjects/demo0621/target)
2020-06-20 23:33:38.477 INFO 8227 --- [ main] c.example.demo0621.Demo0621Application : No active profile set, falling back to default profiles: default
2020-06-20 23:33:40.030 INFO 8227 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port(s): 8080 (http)
2020-06-20 23:33:40.048 INFO 8227 --- [ main] o.apache.catalina.core.StandardService : Starting service [Tomcat]
2020-06-20 23:33:40.048 INFO 8227 --- [ main] org.apache.catalina.core.StandardEngine : Starting Servlet engine: [Apache Tomcat/9.0.36]
2020-06-20 23:33:40.155 INFO 8227 --- [ main] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext
2020-06-20 23:33:40.155 INFO 8227 --- [ main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 1592 ms
2020-06-20 23:33:40.466 INFO 8227 --- [ main] o.s.s.concurrent.ThreadPoolTaskExecutor : Initializing ExecutorService 'applicationTaskExecutor'
2020-06-20 23:33:40.759 INFO 8227 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 8080 (http) with context path ''
2020-06-20 23:33:40.788 INFO 8227 --- [ main] c.example.demo0621.Demo0621Application : Started Demo0621Application in 3.079 seconds (JVM running for 3.722)