Part IV. Spring Boot Features(Spring Boot 的特性)SpringApplication
通常放在了main函數中,作為spring-boot的啟動類
public static void main(String[] args) {
SpringApplication.run(MySpringConfiguration.class, args);
}
1. Customizing the Banner(自定義Banner)
Banner將會在系統啟動的時候打印出來,4中方式設置
在classpath中添加一個文件banner.txt
通過參數banner.location來設置文件的位置,設置文件的編碼banner.charset(默認使用UTF-8)
在classpath中添加一個文件banner.gif, banner.jpg or banner.png
通過參數banner.image.location來設置圖片文件的位置
在banner.txt文件中可以設置下面的參數:
${application.version}
${application.formatted-version}
${spring-boot.version}
${spring-boot.formatted-version}
${application.title}
通過程序來設置banner
實現這個接口中org.springframework.boot.Banner 的printBanner()方法,在通過SpringApplication.setBanner(…)
來設置自己實現的Banner
也可以使用spring.main.banner-mode來設置是否啟用或者關閉打印banner功能,可選參數log,off
2. Customizing SpringApplication
通常使用SpringApplication的靜態方法運行,為了設置更多的參數,可以直接new一個SpringApplication
public static void main(String[] args) {
SpringApplication app = new SpringApplication(MySpringConfiguration.class);
app.setBannerMode(Banner.Mode.OFF);
app.run(args);
}
雖然可以通過編程的方式來實現配置參數,但是官方建議使用application.properites來配置。更多配置參數參考SpringApplication Javadoc
3. Application events and listeners
順序如下: ApplicationStartedEvent,ApplicationEnvironmentPreparedEvent,ApplicationPreparedEvent,ApplicationReadyEvent,ApplicationFailedEvent
使用SpringApplication.addListeners(…)添加事件監聽器
4. Accessing application arguments(訪問application的參數)
可以依賴注入org.springframework.boot.ApplicationArguments,ApplicationArguments提供了訪問application參數的方法;
也可以直接把需要的參數作為屬性,使用@Value來訪問
5. Using the ApplicationRunner or CommandLineRunner
如果想要在SpringApplication.run(...)執行完成前對參數做一些特殊處理,可以使用ApplicationRunner,CommandLineRunner這兩個接口
@Component
public class MyBean implements CommandLineRunner {
public void run(String... args) {
// Do something...
}
}
6. Application exit
所有Spring管理的類在結束之前需要做一些事,可以使用DisposableBean接口或者@PreDestroy注解,
如果需要在Application容器結束后返回一些特殊的Code,可以實現org.springframework.boot.ExitCodeGenerator 接口
Externalized Configuration
1. Application property files
Spring-boot會從application.properties中尋找配置屬性,application.properties可以放在如下位置:
放在當前項目根目錄下
放在當前項目根目錄下的/config中
放在classpath根目錄下(推薦)
放在claasspath根目錄下/config中
注意:目錄最深的覆蓋上層的熟悉
也可以通過spring.config.name,spring.config.location在命令行參數中指定參數文件的名字和加載位置
2. Profile-specific properties
通常我們需要對測試環境,開發環境,正式環境配置不同的參數,我們可以寫多個配置文件,
格式 application-{profile}.properties,然后再applicatioin.properties中使用spring.profiles.active來指定使用哪一個或多個配置文件(多個文件使用逗號分隔),特定的配置文件中的屬性將會覆蓋application.propreties中的屬性
也可以使用 @Profile("...") 來指定使用哪個文件
@Configuration
@Profile("production")
public class ProductionConfiguration {
// ...
}
在application.properties中的參數可以項目使用,比如:
app.name=MyApp app.description=${app.name} is a Spring Boot application 3. Type-safe Configuration Properties
使用@Value("${property}")來依賴注入屬性有時候會很麻煩,尤其是多個屬性需要注入。Spring-boot提供一種更加方便的方式@ConfigurationProperties。
首先建立一個類
@ConfigurationProperties(prefix="connection")
public class ConnectionProperties {
private String username;
private InetAddress remoteAddress;
// ... getters and setters
}
在@EnableConfigurationProperties中指定建立的配置類
@Configuration
@EnableConfigurationProperties(ConnectionProperties.class)
public class MyConfiguration {
}
在需要使用的類中使用@Autowired注入ConnectionProperties
另一種方式,可以不用使用EnableConfigurationProperties(ConnectionProperties.class), 直接在ConnectionProperties上添加@Component
4. Relaxed binding(簡便的綁定方式)
@ConfigurationProperties(prefix="person")
public class OwnerProperties {
private String firstName;
public String getFirstName() {
return this.firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
}
5. @ConfigurationProperties Validation
Spring-boot 支持使用JSR-303的方式對@ConfigurationProperties的注解類的屬性進行校驗,并且使用@Valid 來觸發校驗
@Component
@ConfigurationProperties(prefix = "connection")
public class ConnectionProperties {
@NotEmpty
private String userName;
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
}
@RestController
@RequestMapping("/user")
public class UserController {
@Autowired
@Valid
private ConnectionProperties connectionProperties;
@RequestMapping("/login")
String login() {
return "Login Successful!=" + connectionProperties.getUserName();
}
}
6. @ConfigurationProperties vs. @Value
Feature | @ConfigurationProperties | @Value |
---|---|---|
Relaxed binding | Yes | No |
Meta-data support | Yes | No |
evaluation | No | Yes |
7. Programmatically setting profiles(編程的方式來設置profiles)
你可以在application啟動之前調用方法 SpringApplication.setAdditionalProfiles(…);你也可以通過使用ConfigurableEnvironment接口來實現
Logging(系統日志配置)
1. 使用不同顏色輸出日志
spring.output.ansi.enabled 可選的參數 :
ALWAYS ,DETECT , NEVER 參考api supported value
2. 配置日志文件
logging.file 配置日志文件名稱
logging.path 配置日志文件的路徑
logging.file | logging.path | Example Description |
---|---|---|
(none) | (none) | 控制臺輸出 |
指定日志文件名 | (none) | my.log項目根目錄下輸出日志文件 |
(none) | 指定目錄 | /var/log在指定目錄下生成日志文件 |
當日志文件達到10m將會重新在新的文件中輸出
3. 配置日志輸出級別
logging.level.root=WARN
logging.level.org.springframework.web=DEBUG
logging.level.org.hibernate=ERROR
4. 配置日志輸出的格式
logging.pattern.console : 配置控制臺輸出格式
logging.pattern.file : 配置日志文件輸出格式
Developing web applications(開發web應用)
Spring-boot對大部分應用提供了spring mvc 自動配置。自動配置了下面一些特性:
Inclusion of ContentNegotiatingViewResolver and BeanNameViewResolver beans.
Support for serving static resources, including support for WebJars (see below).
Automatic registration of Converter, GenericConverter, Formatter beans.
Support for HttpMessageConverters (see below).
Automatic registration of MessageCodesResolver (see below).
Static index.html support.
Custom Favicon support.
-
Automatic use of a ConfigurableWebBindingInitializer bean (see below).
如果你想要配置spring mvc 的一些攔截器, formatters, view controllers等等,你可以創建一個類繼承于WebMvcConfigurerAdapter;例如:自己配置一個攔截器@Configuration
@ComponentScan(basePackages = "com.spring.boot.controller3")
public class WebConfigure extends WebMvcConfigurerAdapter {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new LogInterceptor()).addPathPatterns("/user/**");
}
}
如果你想要自己實現RequestMappingHandlerMapping, RequestMappingHandlerAdapter,ExceptionHandlerExceptionResolver, 你可以自己實現WebMvcRegistrationsAdapter
1. HttpMessageConverters
Spring-boot已經包含了常用的HttpMessageConverter,比如自動轉換對象為JSON或者XML;如果需要自己定義一些HttpMessageConverter,可以使用Spring-boot的HttpMessageConverters類:
@Configuration
public class MyConfiguration {
@Bean
public HttpMessageConverters customConverters() {
HttpMessageConverter<?> additional = ...
HttpMessageConverter<?> another = ...
return new HttpMessageConverters(additional, another);
}
}
2. Static Content(靜態資源)
默認情況下Spring-boot使用的是Spring-mvc中的ResourceHttpRequestHandler來處理靜態資源,默認靜態資源的位置是在classpath目錄下或者ServletContext根目錄下的/static (or /public or /resources or/META-INF/resources);你也可以添加自己的處理方式,通過使用WebMvcConfigurerAdapter中的addResourceHandlers方法。
你也可以自己定義靜態資源的位置,使用配置參數spring.resources.staticLocations
Spring-boot也支持靜態資源緩存,使用版本號,參考spring-boot文檔靜態資源處理
3. ConfigurableWebBindingInitializer
默認Spring-boot使用的是WebBindingInitializer來初始化WebDataBinder,你可以創建自己的一個WebBindingInitializer,然后使用@Bean,那么Spring-boot將會使用自己定義的來配置Spring-mvc.參考ConfigurableWebBindingInitializer的實現。
5. Template engines
Spring-boot自動配置支持以下模板引擎:
FreeMarker
Groovy
Thymeleaf
Velocity (deprecated in 1.4)
Mustache
注意:JSP在Spring-boot中盡量避免使用,當使用內嵌的Servlet服務器的時候會有一些限制。參考文檔
使用這些模板引擎,它們默認情況下都會在src/main/resources/templates目錄下尋找模板。
6. Error Handling
我們可以通過使用@ControllerAdvice為一些特殊的Controller處理一些特殊的Exception
@ControllerAdvice(basePackageClasses = FooController.class)
public class FooControllerAdvice extends ResponseEntityExceptionHandler {
@ExceptionHandler(YourException.class)
@ResponseBody
ResponseEntity<?> handleControllerException(HttpServletRequest request, Throwable ex) {
HttpStatus status = getStatus(request);
return new ResponseEntity<>(new CustomErrorType(status.value(), ex.getMessage()), status);
}
private HttpStatus getStatus(HttpServletRequest request) {
Integer statusCode = (Integer) request.getAttribute("javax.servlet.error.status_code");
if (statusCode == null) {
return HttpStatus.INTERNAL_SERVER_ERROR;
}
return HttpStatus.valueOf(statusCode);
}
}
7. Custom error pages
為了對不同的錯誤狀態碼顯示不同不錯誤頁面,我們可以在/error目錄下面添加一個文件;這個文件可以是html,也可以是模板;文件的名稱可以狀態碼,也可以是模板,比如:
src/
+- main/
+- java/
| + <source code>
+- resources/
+- public/
+- error/
| +- 404.html
+- <other public assets>
src/
+- main/
+- java/
| + <source code>
+- resources/
+- templates/
+- error/
| +- 5xx.ftl
+- <other templates>
更多復雜的映射,還可以使用ErrorViewResolver來實現:
public class MyErrorViewResolver implements ErrorViewResolver {
@Override
public ModelAndView resolveErrorView(HttpServletRequest request,
HttpStatus status, Map<String, Object> model) {
// Use the request or status to optionally return a ModelAndView
return ...
}
}
我們也可以通過使用springmvc的特性來處理不同的異常,比如:@ExceptionHandler,@ControllerAdvice。其他沒有被處理的異常都會被ErrorController攔截處理
8. CORS support(跨站點資源訪問)
在Spring-mvc中已經支持跨站點資源訪問,只需要在需要訪問的類或方法上面添加注解@CrossOrigin,也可以配置全局的跨站點訪問 參考文檔。
Spring-boot配置全局的跨站點訪問:
@Configuration
public class MyConfiguration {
@Bean
public WebMvcConfigurer corsConfigurer() {
return new WebMvcConfigurerAdapter() {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/api/**");
}
};
}
}
l9. Embedded servlet container support(內嵌的servlet容器)
Spring-boot 已經內嵌了Tomcat,Jetty服務器,默認監聽的端口是8080
9.1 Registering Servlets, Filters, and listeners
當使用Spring boot的嵌入式servlet容器時,可以通過Spring bean或掃描Servlet組件的方式注冊Servlet、Filter和Servlet規范的所有監聽器(例如HttpSessionListener)。
當urlMapping不是很復雜時,可以通過ServletRegistrationBean、FilterRegistrationBean 和ServletListenerRegistrat<wbr>ionBean獲得完整控制。如果bean實現了ServletContextInitialize<wbr>r接口的話則可以直接注冊。
@Configuration
@ComponentScan(basePackages = "com.spring.boot.controller3")
public class WebConfigure extends WebMvcConfigurerAdapter {
@Bean
public ServletRegistrationBean getLogServlet(LogServlet logServlet) {
return new ServletRegistrationBean(logServlet, "/logServlet");
}
}
@Component
public class LogServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doGet(req, resp);
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
PrintWriter writer = resp.getWriter();
writer.print("Log Servlet welcome!");
writer.close();
}
}
當使用@ServletComponentScan掃描Servlet組件時,Servlet、過濾器和監聽器可以是通過@WebServlet、@WebFilter和@WebListener自動注冊
@Configuration
@ServletComponentScan(basePackages = "com.spring.boot.component")
public class WebConfigure extends WebMvcConfigurerAdapter {
}
@WebServlet(urlPatterns = {"/logServlet2"})
public class LogServlet2 extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doGet(req, resp);
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
PrintWriter writer = resp.getWriter();
writer.print("Log Servlet2 welcome!");
writer.close();
}
}
9.2 Servlet Context Initialization
對于這種內嵌的Servlet容器,在初始化的時候不會去執行javax.servlet.ServletContainerInitializer這個接口,而是執行spring的接口org.springframework.web.WebApplicationInitializer。如果你需要在spring-boot的應用中去處理初始化的工作,可以注冊一個Spring Bean實現接口org.springframework.boot.context.embedded.ServletContextInitializer
@Component
public class AppServletContextInitializer implements ServletContextInitializer {
@Override
public void onStartup(ServletContext servletContext) throws ServletException {
System.out.println("============ AppServletContextInitializer ===============");
}
}
9.3 Customizing embedded servlet containers(配置嵌入的Servlet容器)
-
在applicat-ion.properties中配置參數
server.port : 配置監聽的端口
server.address : 監聽地址
server.session.timeout : session過期時間
server.session.persistence : 是否需要持久化session
server.session.store-dir : session存儲位置
更多其他配置參考類 ServerProperties
-
通過編程的方式實現
import org.springframework.boot.context.embedded.*;
import org.springframework.stereotype.Component;
@Component
public class CustomizationBean implements EmbeddedServletContainerCustomizer {
@Override
public void customize(ConfigurableEmbeddedServletContainer container) {
container.setPort(9000);
}
}
實現EmbeddedServletContainerCustomizer接口,編程配置參數
-
如果以上兩種方式你覺得不靈活,你可以使用 TomcatEmbeddedServletContainerFactory,JettyEmbeddedServletContainerFactoryor UndertowEmbeddedServletContainerFactory
@Bean
public EmbeddedServletContainerFactory servletContainer() {
TomcatEmbeddedServletContainerFactory factory = new TomcatEmbeddedServletContainerFactory();
factory.setPort(9000);
factory.setSessionTimeout(10, TimeUnit.MINUTES);
factory.addErrorPages(new ErrorPage(HttpStatus.NOT_FOUND, "/notfound.html"));
return factory;
}
Working with SQL databases(使用SQL數據庫)
1. 配置數據庫連接池
1. Spring-boot能夠自動配置數據庫連接池DataSource,自動選擇的規則:
2. 因為Tomcat的連接池效率和并發性都比較高,所以如果允許,都會選擇使用
3. 否則,如果HikariCP允許,就會選擇HikariCP
4. 如果Tomcat pooling datasource和HikariCP都不能使用,那么將會選擇使用 DBCP
5. 最后,以上3中都不能使用,就會選擇使用DBCP2
如果你使用了spring-boot-starter-jdbc, spring-boot-starter-data-jpa ,那么Spring-boot將會自動配置tomcat-jdbc
也可以通過使用spring.datasource.type來手動配置使用哪種,比如:配置阿里巴巴開源項目druid
更多的數據庫參數配置,參考類DataSourceProperties
2. Using JdbcTemplate
Spring-boot會自動配置JdbcTemplate,可以直接使用@Autowire來注入使用
@Component
public class MyBean {
private final JdbcTemplate jdbcTemplate;
@Autowired
public MyBean(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}
// ...
}
3. JPA and ‘Spring Data’
在Spring-boot應用中,可以使用spring-boot-starter-data-jpa作為一個開始,會包含一下依賴:
Hibernate?—?One of the most popular JPA implementations.
Spring Data JPA?—?Makes it easy to implement JPA-based repositories.
Spring ORMs?—?Core ORM support from the Spring Framework.
3.1 Entity Classes And Spring Data JPA Repositories
默認情況下,Spring-boot會掃描主要配置類(有注解@EnableAutoConfiguration or@SpringBootApplication)下面的所有包,任何被@Entity, @Embeddable or @MappedSuperclass注解的類都會作為實體;任何繼承了Repository or CrudRepository的接口都會被作為 Repository,不需要任何@Component or Repository
如果你想要自定義尋找的Entity的存放位置,可以使用注解@EntityScan。
Caching 參考文檔
Sending email
Spring框架提供了一個發送郵件的類JavaMailSender。
如果在容器中找不到一個存在的JavaMailSender,配置了參數spring.mail.host并且相關包存在(spring-boot-starter-mail導入相關包),那么就會自動創建一個JavaMailSender。
郵件配置參數都是以spring.mail開頭,更多參數配置參考類: MailProperties
#發送郵件配置
spring.mail.host=smtp.sina.cn
spring.mail.username=silentwu@sina.cn
spring.mail.password=asdewq
@RestController
@RequestMapping("/mail")
public class MailController {
@Autowired
private JavaMailSender mailSender;
@RequestMapping("/send")
public String sendMail() {
SimpleMailMessage mailMessage = new SimpleMailMessage();
mailMessage.setTo("380303318@qq.com");
mailMessage.setFrom("silentwu@sina.cn");
mailMessage.setSubject(" 測試簡單文本郵件發送! ");
mailMessage.setText(" 測試我的簡單郵件發送機制!! ");
mailSender.send(mailMessage);
return "send mail success...";
}
}
Spring Session 參考文檔
Monitoring and management over JMX 參考文檔