应用程序之类创建
用Spring Initializr创建一个简单的应用程序类.但是,这样未免也太单调了一点.有必要像下面的列表这样改动一下应用程序类.
package com.example.springboot;
import java.util.Arrays;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
@Bean
public CommandLineRunner commandLineRunner(ApplicationContext ctx) {
return args -> {
System.out.println("Let's inspect the beans provided by Spring Boot:");
String[] beanNames = ctx.getBeanDefinitionNames();
Arrays.sort(beanNames);
for (String beanName : beanNames) {
System.out.println(beanName);
}
};
}
}COPY
@SpringBootApplication
这个方便的注解可以装配以下所有的注解.
-
@Configuration
: 作为应用程序上下文的Bean定义的源码在类上加上标签 -
@EnableAutoConfiguration
: 基于类路径设置,其它Bean,各种各样的属性设置指示SpringBoot开始Bean的追加.例:如果在类路径上有spring-webmvc的话,该注解会作为web应用程序在应用程序上创建类,DispatcherServlet
的装配等主要动作会是主动的. -
@ComponentScan
: 在Spring查找com/example包内的其它组件,构成,服务,指示检测出控制器.主函数main方法使用SpringBoot的
SpringApplication.run()
方法启动应用程序.注意到xml一行都没有了吗?也没有web.xml文件.该web应用程序是100%纯粹的Java,不需要对应处理接续功能和基础架构的构成.也有作为
@Bean
被标记的CommandLineRunner
方法,启动的时候执行.根据应用程序来创建,或者根据SpringBoot获取自动追加的所有Bean.排序,然后输出.执行应用程序
要执行应用程序,在终端窗口(complete里面)目录执行下面代码.
./gradlew bootRun
使用Maven的话,在终端窗口(complete里面)目录执行下面代码.
./mvnw spring-boot:run
显示如下输出
Let's inspect the beans provided by Spring Boot:
application
beanNameHandlerMapping
defaultServletHandlerMapping
dispatcherServlet
embeddedServletContainerCustomizerBeanPostProcessor
handlerExceptionResolver
helloController
httpRequestHandlerAdapter
messageSource
mvcContentNegotiationManager
mvcConversionService
mvcValidator
org.springframework.boot.autoconfigure.MessageSourceAutoConfiguration
org.springframework.boot.autoconfigure.PropertyPlaceholderAutoConfiguration
org.springframework.boot.autoconfigure.web.EmbeddedServletContainerAutoConfiguration
org.springframework.boot.autoconfigure.web.EmbeddedServletContainerAutoConfiguration$DispatcherServletConfiguration
org.springframework.boot.autoconfigure.web.EmbeddedServletContainerAutoConfiguration$EmbeddedTomcat
org.springframework.boot.autoconfigure.web.ServerPropertiesAutoConfiguration
org.springframework.boot.context.embedded.properties.ServerProperties
org.springframework.context.annotation.ConfigurationClassPostProcessor.enhancedConfigurationProcessor
org.springframework.context.annotation.ConfigurationClassPostProcessor.importAwareProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalRequiredAnnotationProcessor
org.springframework.web.servlet.config.annotation.DelegatingWebMvcConfiguration
propertySourcesBinder
propertySourcesPlaceholderConfigurer
requestMappingHandlerAdapter
requestMappingHandlerMapping
resourceHandlerMapping
simpleControllerHandlerAdapter
tomcatEmbeddedServletContainerFactory
viewControllerHandlerMappingCOPY
org.springframework.boot.autoconfigure
可以很清晰看见Bean.
还有tomcatEmbeddedServletContainerFactory
.
执行下面的命令,在curl执行服务.(别的终端窗口)(同时显示输出)
$ curl localhost:8080
Greetings from Spring Boot!COPY
添加单体测试
有必要添加追加的后端测试(我觉得是后端,也有可能是终端).SpringTest提供了若干的方式(機構翻译为机构感觉不太合理).
使用Gradle的话,在build.gradle
目录添加如下依赖关系.
testImplementation('org.springframework.boot:spring-boot-starter-test')COPY
使用Maven的话,在pom.xml文件里添加如下依赖.
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>COPY (突然发现代码里都有个COPY,这个是不需要的)
同下面的代码所示,通过后端模仿Servlet的request和response创建简单的单体测试.
package com.example.springboot;
import static org.hamcrest.Matchers.equalTo;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.http.MediaType;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
@SpringBootTest
@AutoConfigureMockMvc
public class HelloControllerTest {
@Autowired
private MockMvc mvc;
@Test
public void getHello() throws Exception {
mvc.perform(MockMvcRequestBuilders.get("/").accept(MediaType.APPLICATION_JSON))
.andExpect(status().isOk())
.andExpect(content().string(equalTo("Greetings from Spring Boot!")));
}
}
MockMvc
是从SpringTest衍生而来的,通过便利的builder类装配,发送HTTP request给DispatcherServlet
,可以对结果进行调试(assertion 断言. 异常或说是错误也可以, 可以用来调试测试结果,可能说的不准确).
使用@AutoConfigureMockMvc
以及@SpringBootTest
请注意注入 MockMvc
实例.由于使用了@SpringBootTest
,要求可以创建应用程序Context整体.别的函数,使用@WebMvcTest
只 创建Context的web层也要依赖SpringBoot.不管怎样,SpringBoot会自动查找应用程序的主应用程序类,构造别的东西的话,是否重写,还是可以锁定的.
不仅是测试HTTP request循环,使用SpringBoot,还可以做成简单的全栈式统一测试.例:代替前面展示的Mock测试(和之前一样),可以进行下面的测试.
package com.example.springboot;
import static org.assertj.core.api.Assertions.*;
import java.net.URL;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
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;
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class HelloControllerIT {
@LocalServerPort
private int port;
private URL base;
@Autowired
private TestRestTemplate template;
@BeforeEach
public void setUp() throws Exception {
this.base = new URL("http://localhost:" + port + "/");
}
@Test
public void getHello() throws Exception {
ResponseEntity<String> response = template.getForEntity(base.toString(),
String.class);
assertThat(response.getBody()).isEqualTo("Greetings from Spring Boot!");
}
}
webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT
嵌入式服务器使用随机的端口启动,执行的时候使用 @LocalServerPort
检测实际的端口.
アプリケーションクラスを作成する
Spring Initializr は、簡単なアプリケーションクラスを作成します。ただし、この場合は単純すぎます。次のリストに一致するようにアプリケーションクラスを変更する必要があります(src/main/java/com/example/springboot/Application.java
から)。
package com.example.springboot;
import java.util.Arrays;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
@Bean
public CommandLineRunner commandLineRunner(ApplicationContext ctx) {
return args -> {
System.out.println("Let's inspect the beans provided by Spring Boot:");
String[] beanNames = ctx.getBeanDefinitionNames();
Arrays.sort(beanNames);
for (String beanName : beanNames) {
System.out.println(beanName);
}
};
}
}COPY
@SpringBootApplication
は、次のすべてを追加する便利なアノテーションです。
@Configuration
: アプリケーションコンテキストの Bean 定義のソースとしてクラスにタグを付けます。@EnableAutoConfiguration
: クラスパス設定、他の Bean、さまざまなプロパティ設定に基づいて Bean の追加を開始するよう Spring Boot に指示します。例:spring-webmvc
がクラスパスにある場合、このアノテーションはアプリケーションに Web アプリケーションとしてフラグを立て、DispatcherServlet
のセットアップなどの主要な動作をアクティブにします。@ComponentScan
: Spring に、com/example
パッケージ内の他のコンポーネント、構成、サービスを探して、コントローラーを検出させるように指示します。
main()
メソッドは、Spring Boot の SpringApplication.run()
メソッドを使用してアプリケーションを起動します。XML が 1 行もないことに気付きましたか? web.xml
ファイルもありません。この Web アプリケーションは 100% 純粋な Java であり、接続機能やインフラストラクチャの構成に対処する必要はありませんでした。
@Bean
としてマークされた CommandLineRunner
メソッドもあり、これは起動時に実行されます。アプリケーションによって作成された、または Spring Boot によって自動的に追加されたすべての Bean を取得します。ソートし、出力します。
アプリケーションの実行
アプリケーションを実行するには、ターミナルウィンドウ(complete
内)ディレクトリで次のコマンドを実行します。
./gradlew bootRun
Maven を使用する場合は、ターミナルウィンドウ(complete
内)ディレクトリで次のコマンドを実行します。
./mvnw spring-boot:run
次のような出力が表示されます。
Let's inspect the beans provided by Spring Boot:
application
beanNameHandlerMapping
defaultServletHandlerMapping
dispatcherServlet
embeddedServletContainerCustomizerBeanPostProcessor
handlerExceptionResolver
helloController
httpRequestHandlerAdapter
messageSource
mvcContentNegotiationManager
mvcConversionService
mvcValidator
org.springframework.boot.autoconfigure.MessageSourceAutoConfiguration
org.springframework.boot.autoconfigure.PropertyPlaceholderAutoConfiguration
org.springframework.boot.autoconfigure.web.EmbeddedServletContainerAutoConfiguration
org.springframework.boot.autoconfigure.web.EmbeddedServletContainerAutoConfiguration$DispatcherServletConfiguration
org.springframework.boot.autoconfigure.web.EmbeddedServletContainerAutoConfiguration$EmbeddedTomcat
org.springframework.boot.autoconfigure.web.ServerPropertiesAutoConfiguration
org.springframework.boot.context.embedded.properties.ServerProperties
org.springframework.context.annotation.ConfigurationClassPostProcessor.enhancedConfigurationProcessor
org.springframework.context.annotation.ConfigurationClassPostProcessor.importAwareProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalRequiredAnnotationProcessor
org.springframework.web.servlet.config.annotation.DelegatingWebMvcConfiguration
propertySourcesBinder
propertySourcesPlaceholderConfigurer
requestMappingHandlerAdapter
requestMappingHandlerMapping
resourceHandlerMapping
simpleControllerHandlerAdapter
tomcatEmbeddedServletContainerFactory
viewControllerHandlerMappingCOPY
org.springframework.boot.autoconfigure
Bean をはっきりと見ることができます。tomcatEmbeddedServletContainerFactory
もあります。
次のコマンドを実行して、curl でサービスを実行します(別のターミナルウィンドウで)(出力とともに表示)。
$ curl localhost:8080
Greetings from Spring Boot!COPY
単体テストを追加する
追加したエンドポイントのテストを追加する必要があります。Spring Test はそのためのいくつかの機構を提供します。
Gradle を使用する場合は、build.gradle
ファイルに次の依存関係を追加します。
testImplementation('org.springframework.boot:spring-boot-starter-test')COPY
Maven を使用する場合は、pom.xml
ファイルに次を追加します。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>COPY
次のリスト(src/test/java/com/example/springboot/HelloControllerTest.java
から)が示すように、エンドポイントを介してサーブレットのリクエストとレスポンスを模倣する単純な単体テストを作成します。
package com.example.springboot;
import static org.hamcrest.Matchers.equalTo;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.http.MediaType;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
@SpringBootTest
@AutoConfigureMockMvc
public class HelloControllerTest {
@Autowired
private MockMvc mvc;
@Test
public void getHello() throws Exception {
mvc.perform(MockMvcRequestBuilders.get("/").accept(MediaType.APPLICATION_JSON))
.andExpect(status().isOk())
.andExpect(content().string(equalTo("Greetings from Spring Boot!")));
}
}COPY
MockMvc
は Spring Test に由来し、便利なビルダークラスのセットを介して、HTTP リクエストを DispatcherServlet
に送信し、結果についてアサーションを作成できます。@AutoConfigureMockMvc
および @SpringBootTest
を使用して MockMvc
インスタンスを注入することに注意してください。@SpringBootTest
を使用したため、アプリケーションコンテキスト全体を作成するように求めています。別のメソッドは、@WebMvcTest
を使用してコンテキストの Web レイヤーのみを作成するように Spring Boot に依頼することです。いずれの場合も、Spring Boot はアプリケーションのメインアプリケーションクラスを自動的に見つけようとしますが、別のものを構築する場合は、それをオーバーライドするか、絞り込むことができます。
HTTP リクエストサイクルをモックするだけでなく、Spring Boot を使用して、簡単なフルスタック統合テストを作成することもできます。例: 前に示したモックテストの代わりに(または同様に)、次のテストを作成できます(src/test/java/com/example/springboot/HelloControllerIT.java
から)。
package com.example.springboot;
import static org.assertj.core.api.Assertions.*;
import java.net.URL;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
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;
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class HelloControllerIT {
@LocalServerPort
private int port;
private URL base;
@Autowired
private TestRestTemplate template;
@BeforeEach
public void setUp() throws Exception {
this.base = new URL("http://localhost:" + port + "/");
}
@Test
public void getHello() throws Exception {
ResponseEntity<String> response = template.getForEntity(base.toString(),
String.class);
assertThat(response.getBody()).isEqualTo("Greetings from Spring Boot!");
}
}COPY
webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT
のため、組み込みサーバーはランダムなポートで起動し、実行時に @LocalServerPort
で実際のポートが検出されます。