给岁月以文明,而不是给文明以岁月。
前言
用Spring Initializr创建SpringBoot工程虽然方便,但是得有网,耗时耗流量,而且默认下载最新版本(强迫症可能会不舒服),网络不佳时还可能下载半天然后失败,如:
不想这样的话,可以参考我的这篇博客,用maven工程构建包括如何同时启动多个SpringBoot工程实例:如何用Maven搭建一个SpringBoot工程
后语
时代变得真快呀,现在SpingBoot官方直接强推Java17,然而现在很多企业还是用Java8
如果还想使用Spring Initializr快速构建的话,需要点击Server URL那一栏的设置按钮,进行换源,换成: https://start.aliyun.com
然后点击OK,就OK啦:
二步搭建
1.打开"IDEA",选择"Create New Project" -> “Next”,填写组织名,如"com.guqueyue"; 项目名,如"hello_guqueyue",再点击"Next",下一步。
2.此处我们勾选"Spring MVC"的核心依赖,开启web功能:点击 “Web” -> “Spring Web”,再点击"Next",确认项目放置位置,再点击"Finish",等待IDEA右下方的进度条显示下载完成,即可。
项目结构
选中application.properties
文件,右键 -> “Refactor” -> “Rename…” ,再点击"Refactor"后,重命名为application.yml
后,项目结构图如下:
其中配置文件pom.xml
中有spring-boot-starter-web
和spring-boot-starter-test
的起步依赖:
代码如下:
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
其中,spring-boot-starter-web
是web功能的起步依赖,它会自动导入与web相关的依赖;spring-boot-starter-test
为SpringBoot测试功能的起步依赖,它会自动导入与SpringBoot测试相关的依赖,通过依赖继承关系图可以很容易看出:
在工程代码包的主目录下有一个名为HelloGuqueyueApplication
的类,该类是程序的启动类,代码如下:
@SpringBootApplication
public class HelloGuqueyueApplication {
public static void main(String[] args) {
SpringApplication.run(HelloGuqueyueApplication.class, args);
}
}
其中,@SpringBootApplication
为SpringBoot的核心注解,该注解包含@SpringBootConfiguration
、@EnableAutoConfiguration
和@ComponentScan
三个注解,开启了包扫描、配置和自动配置的功能。
构建Web
建立一个Web层的Controller,如:
@RestController
public class HelloController {
@RequestMapping("/hello")
public String hello() {
return "Hello, guqueyue!";
}
}
其中@RestController
注解表明这个类是一个RestControlletr。@RestController
是Spring4.0版本的一个注解,它的功能相当于@Controller
和@ResponseBody
两个注解之和,点进去一看便知:
而@RequestMapping
则是配置请求地址的Url映射.
现在controller已经编写好了,那么SpringBoot如何找到这个Controller? ↓ 预知后事如何,请看下回分解 ↓
@Import注解
在启动类上,用@Import
注解导入Controller的反射对象:
@Import(HelloController.class)
那么,问题来了,如果有多个Controller怎么办?
点开@Import
注解一看,发现value里面为一个反射对象数组,因此可以这样:
@Import({HelloController.class, OtherController.class...})
可是还有一个问题,万一有几百个Controller,还需要一个一个写吗?
@SpringBootApplication注解
当然不是!可以通过SpringBoot的核心注解@SpringBootApplication
,配置扫描路径。当然@SpringBootApplication
的默认扫描路径,是从启动类的包下,逐层扫描。如果我们的Controller没有和启动类在一个包下则需要用@Import
注解导入或者自行配置扫描路径,如:
@SpringBootApplication(scanBasePackages = "com.guqueyue")
点开@SpringBootApplication
一看,scanBasePackages()
支持字符串数组,
因此我们也可以同时配置多个扫描路径,如:
@SpringBootApplication(scanBasePackages = {"com.guqueyue", "com.other"...})
找到Tomcat
找到启动类,运行main方法,启动SpringBoot程序。再打开浏览器,在浏览器上输入"http://localhost:8080/hello",浏览器上会显示"Hello, guqueyue!"
其中8080为SpringBoot程序的默认端口。如果需要,可以在配置文件application.yml
中自定义端口,如8762:
server:
port: 8762
可能这里有人会有疑问了,Tomcat去哪儿呢?之前我们运行Web程序,不是把Web工程打成war包,然后放到Tomcat容器中运行,之后再通过浏览器访问的吗?如果有细心的小伙伴可能之前就发现了,Web功能的起步依赖spring-boot-starter-web
中已经自动导入了一个叫spring-boot-starter-tomcat
的依赖,SpringBoot反向整合了Tomcat服务,也就是说它会通过Tomcat的插件,在SpringBoot运行时自动运行Tomcat。
开启测试功能
SpringBoot开启测试功能也十分的简单,只需要在测试类上加
@RunWith(SpringRunner.class)
和@SpringBootTest
两个注解即可
如果使用Spring Initializr搭建工程的话先去除SpringBoot测试起步依赖spring-boot-starter-test
的排除依赖;用maven搭建工程的话,请先添加SpringBoot测试起步依赖spring-boot-starter-test
:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope><!-- 该依赖仅仅参与测试相关的工作 -->
</dependency>
再在src/test/java/com/guqueyue/hello_guqueyue目录下, 创建一个名为TestApplication
的测试类,如:
/**
* @author guqueyue
* @Date 2020/4/19
**/
@RunWith(SpringRunner.class)
@SpringBootTest
public class TestApplication {
@Test
public void test() {
System.out.println("这是一个测试方法");
}
}
运行test()方法,一道绿光闪过,控制台输出:
说明test()运行成功,接着我们可以测试一下之前的controller,再在相同的目录下创建一个HelloController的测试类,代码如下:
package com.guqueyue.hello_guqueyue.controller;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.web.client.TestRestTemplate;
import org.springframework.boot.web.server.LocalServerPort;
import org.springframework.http.ResponseEntity;
import org.springframework.test.context.junit4.SpringRunner;
import java.net.URL;
import static org.hamcrest.Matchers.equalTo;
import static org.junit.Assert.assertThat;
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class HelloControllerIT {
@LocalServerPort
private int port;
private URL base;
@Autowired
private TestRestTemplate template;
@Before
public void setUp() throws Exception {
this.base = new URL("http://localhost:" + port + "/hello");
}
@Test
public void getHello() {
ResponseEntity<String> response = template.getForEntity(base.toString(), String.class);
assertThat(response.getBody(), equalTo("Hello, guqueyue!"));
}
}
其中@SpringBootTest
注解加上了Web测试环境端口为随机端口的配置,RestTemplate用于远程调用Http API接口,而TestRestTemplate为RestTemplate的测试类(千万不要导错包),运行添加了 @Test
注解的getHello()方法:
如果你看到控制台一道绿光闪过,这就说明你的测试通过(^_−)☆