Spring Boot Web - Spring Boot 168 EP 5

Spring Boot Web – Spring Boot 168 EP 5

提供了內嵌的 Servlet 容器以及 Spring MVC 的相依,提供自動配置,整合開發, EP 5 增加了相依套件,應用設定檔及主程式起點,快速啟動 Web Server。

功能簡介

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 Web 執行主程式
  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: 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 等其他伺服器。

發佈留言