提供了內嵌的 Servlet 容器以及 Spring MVC 的相依,提供自動配置,整合開發, EP 5 增加了相依套件,應用設定檔及主程式起點,快速啟動 Web Server。
Table of Contents
Toggle功能簡介
SpringMVC 是一個基於 MVC 設計模式的輕量級 Web 開發框架,透過了功能強大的控制器 DispatcherServlet,對請求和回應進行統一處理,適用於大多數 Web 開發場景。
Spring Boot Web
檔案目錄
./
+- build.gradle
+- src
+- main
+- resources
| +- application.properties
+- java
| +- org
| +- ruoxue
| +- spring_boot_168
| +- config
| +- WebMvcConfig.java
| +- Application.java
Gradle
build.gradle
Spring Boot Web 主要包含以下這些套件:
Spring boot 設定。
Spring WebMVC 元件。
內嵌 Tomcat 。
Slf4j logback 。
Snakeyaml 。
Jackson 2.x 。
增加相依套件,修改完後,點右鍵,Gradle -> Refresh Gradle Project 。
buildscript {
group 'org.ruoxue.spring-boot-168'
version = '0.0.1-SNAPSHOT'
ext {
springBootVersion = '2.1.7.RELEASE'
}
}
plugins {
id 'java-library'
}
repositories {
jcenter()
}
dependencies {
api 'org.apache.commons:commons-math3:3.6.1'
implementation 'com.google.guava:guava:27.0.1-jre'
implementation "org.springframework.boot:spring-boot-starter-web:${springBootVersion}"
testImplementation 'junit:junit:4.12'
}
組態設定
application.properties
Spring MVC 新增檔案,設定相關資訊。
spring.application.name=ruoxue-spring-boot-168
spring.main.allow-bean-definition-overriding=true
server.address=0.0.0.0
server.port=10000
server.servlet.context-path=/
spring.jackson.default-property-inclusion=non_null
spring.mvc.view.prefix=/WEB-INF/
spring.mvc.view.suffix=.jsp
spring.mvc.view.view-names=jsp/*
spring.mvc.view.order=2
WebMvcConfig.java
新增檔案。
Spring Web
addCorsMappings() ,實現跨網域請求 CORS。
路徑映射。
允許跨網域請求的來源。
允許跨域攜帶 cookie 資訊,預設是不攜帶。
允許使用那些請求方式。
允許哪些 header。
可獲取哪些 header。
Async Thread Pool
asyncExecutor() ,非同步執行緒連線池。
package org.ruoxue.spring_boot_168.config;
import java.util.concurrent.ThreadPoolExecutor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.web.servlet.config.annotation.AsyncSupportConfigurer;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import lombok.extern.slf4j.Slf4j;
@EnableWebMvc
@Configuration
@Slf4j
public class WebMvcConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**") //
.allowedOrigins("*") //
.allowCredentials(true) //
.allowedMethods("*") //
.allowedHeaders("*") //
.exposedHeaders("Authorization", "Accept", "X-Requested-With", "Origin",
"Access-Control-Request-Method", "Access-Control-Request-Headers",
"Access-Control-Expose-Headers", "Content-Length", "Content-Range") //
.maxAge(1800) // 30min
; //
}
@Bean
public ThreadPoolTaskExecutor asyncExecutor() {
String prefix = "ASYNC-T-";
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setThreadNamePrefix(prefix);
executor.setCorePoolSize(ThreadPoolConfig.CORE_POOL_SIZE);
executor.setMaxPoolSize(ThreadPoolConfig.MAX_POOLSIZE);
executor.setQueueCapacity(ThreadPoolConfig.QUEUE_CAPACITY);
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
executor.initialize();
log.info("prefix: " + prefix);
log.info("corePoolSize: " + executor.getCorePoolSize());
log.info("maxPoolSize: " + executor.getMaxPoolSize());
return executor;
}
public void configureAsyncSupport(AsyncSupportConfigurer configurer) {
configurer.setTaskExecutor(asyncExecutor());
}
}
Application.java
新增檔案。
package org.ruoxue.spring_boot_168;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.servlet.ServletComponentScan;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
@SpringBootApplication
@ComponentScan(basePackages = { "org.ruoxue.spring_boot_168" })
@ServletComponentScan
public class Application extends SpringBootServletInitializer {
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
SpringApplicationBuilder builder = application.sources(Application.class);
return builder;
}
public static void main(String[] args) {
SpringApplication app = new SpringApplication(Application.class);
app.run();
}
}
單元測試
WebMvcConfigTest.java
新增單元測試,驗證是否符合預期 。
package org.ruoxue.spring_boot_168.config;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.ruoxue.spring_boot_168.Application;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit.jupiter.SpringExtension;
@ExtendWith(SpringExtension.class)
@SpringBootTest(classes = Application.class)
public class WebMvcConfigTest {
@Autowired
private WebMvcConfig config;
@Test
public void config() {
System.out.println(config);
assertNotNull(config);
}
}
config
測試方法上點右鍵執行 Run As -> JUnit Test ,查看 console 。
org.ruoxue.spring_boot_168.config.$$EnhancerBySpringCGLIB$$bd5dea30@24be6e34
Application.main
在主程式點右鍵執行 Run As -> Java Application,查看 console,Server 已成功啟動,監聽 10000 port。
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v2.1.7.RELEASE)
2022-04-15 15:55:41.932 INFO 10992 --- [ main] org.ruoxue.spring_boot_168.Application : Starting Application on cheng-pc with PID 10992 (D:\dev\gitlab\ruoxue\spring-boot-168\bin\main started by cheng in D:\dev\gitlab\ruoxue\spring-boot-168)
2022-04-15 15:55:41.934 INFO 10992 --- [ main] org.ruoxue.spring_boot_168.Application : No active profile set, falling back to default profiles: default
[GC (Metadata GC Threshold) 125345K->16356K(1005056K), 0.0094106 secs]
[Full GC (Metadata GC Threshold) 16356K->15540K(1005056K), 0.0171040 secs]
2022-04-15 15:55:42.691 INFO 10992 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port(s): 10000 (http)
2022-04-15 15:55:42.715 INFO 10992 --- [ main] o.apache.catalina.core.StandardService : Starting service [Tomcat]
2022-04-15 15:55:42.715 INFO 10992 --- [ main] org.apache.catalina.core.StandardEngine : Starting Servlet engine: [Apache Tomcat/9.0.22]
2022-04-15 15:55:42.792 INFO 10992 --- [ main] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext
2022-04-15 15:55:42.793 INFO 10992 --- [ main] o.s.web.context.ContextLoader : Root WebApplicationContext: initialization completed in 830 ms
2022-04-15 15:55:42.940 INFO 10992 --- [ main] o.s.s.concurrent.ThreadPoolTaskExecutor : Initializing ExecutorService 'applicationTaskExecutor'
2022-04-15 15:55:43.074 INFO 10992 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 10000 (http) with context path ''
2022-04-15 15:55:43.077 INFO 10992 --- [ main] org.ruoxue.spring_boot_168.Application : Started Application in 1.384 seconds (JVM running for 1.674)
心得分享
提供 Spring Boot Web Application Example 從相依套件到設定,Web Spring 大部分都已經整合成 Starter,只要引入所需的套件,再加上少許的簡單設定,就能從主程式入口順利啟動 Web Server,預設是內嵌 Tomcat,也可置換成 Jetty 或 Undertow 等其他伺服器。