「乾貨分享」為什麼使用 Spring Boot?

概要

在本文中,我們快速概述了各種Spring配置樣式,並瞭解了配置Spring應用程序的複雜性。此外,我們通過創建一個簡單的Web應用程序快速瀏覽了SpringBoot。

Spring 是一個非常流行的基於Java語言的開發框架,此框架用來構建web和企業應用程序。與許多其他僅關注一個領域的框架不同,Spring框架提供了廣泛的功能,通過其組合項目滿足現代業務需求。

Spring框架提供了以多種方式配置bean的靈活性,例如XML,註解和JavaConfig。隨著功能數量的增加,複雜性也會增加,配置Spring應用程序變得乏味且容易出錯。

Spring團隊創建了Spring Boot來解決配置的複雜性。

但在深入瞭解SpringBoot之前,我們將快速瀏覽一下Spring框架,看看SpringBoot試圖解決的問題是什麼。

「乾貨分享」為什麼使用 Spring Boot?

在本文中,我們將介紹:

  • Spring框架概述
  • 使用Spring MVC和JPA(Hibernate)的Web應用
  • 快速試用SpringBoot

Spring 框架概述

如果你是 Java 開發人員,那麼你多半聽說過 Spring 框架,甚至可能在項目中使用過這一框架。Spring 框架主要起源於一個依賴注入容器,但它遠不止於此。

Spring 之所以流行,是因為:

  • Spring 的依賴注入方法支持編寫可測試的代碼
  • 強大且易用的數據庫事務管理能力
  • Spring 非常容易與其它 Java 框架集成,如 JPA/Hibernate ORM、Struts、JSF等。
  • 使用前沿的 MVC 框架構建 Web 應用

Spring 除了框架之外,還有很多姊妹項目可以助力構建滿足現代業務需求的應用程序:

  • Spring Data:為訪問關係型數據庫或 NoSQL 數據庫提供便利。
  • Spring Batch:強大的批處理框架。
  • Spring Security:為安全應用而生的強健的安全框架。
  • Spring Social:支持整合社區網絡,比如 Facebook、Twitter、LinkedIn、Github 等。
  • Spring Integration:企業級集成模型的實現,使用輕量級的消息傳遞和聲明式適配器與其他企業應用集成。

還有不少其他有趣的項目,他們用於解決各種現代應用開發需求。欲知詳情,請看 http://spring.io/projects。

Spring 框架一開始提供了基於 XML 的方法來配置 Bean。之後 Spring 引入了基於 XML 的 DSL、註解和 JavaConfig 來配置 Bean 的方法。

「乾貨分享」為什麼使用 Spring Boot?

讓我們快速看看每種配置方式的樣子。

基於XML的配置

「乾貨分享」為什麼使用 Spring Boot?

基於註釋的配置

「乾貨分享」為什麼使用 Spring Boot?

基於JavaConfig的配置

「乾貨分享」為什麼使用 Spring Boot?

哇… Spring提供了很多方法來做同樣的事情,我們甚至可以混合使用這些方法,並在同一個應用程序中同時使用基於JavaConfig和註解的配置方式。

但是沒有一種適合所有類型的解決方案。必須根據自己的應用需求選擇方法。

好了,現在您已經看到了各種樣式的Spring bean配置的例子。

讓我們快速瀏覽一下典型的SpringMVC + JPA / Hibernate Web應用程序配置的樣子。

「乾貨分享」為什麼使用 Spring Boot?

使用Spring MVC和JPA(Hibernate)的Web應用程序

在瞭解SpringBoot是什麼以及提供了什麼樣的功能之前,讓我們先看看典型的Spring Web應用程序配置如何,難點又是什麼,其次我們論述SpringBoot將如何解決這些問題。

第1步:配置Maven依賴項

首要的是我們需要配置pom.xml中所需的所有依賴項。


xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/maven-v4_0_0.xsd">
4.0.0
com.sivalabs
springmvc-jpa-demo
war
1.0-SNAPSHOT
springmvc-jpa-demo

UTF-8
1.8
1.8
false



org.springframework
spring-webmvc
4.2.4.RELEASE


org.springframework.data
spring-data-jpa
1.9.2.RELEASE


org.slf4j
jcl-over-slf4j
1.7.13


org.slf4j
slf4j-api
1.7.13


org.slf4j
slf4j-log4j12
1.7.13


log4j
log4j
1.2.17


com.h2database
h2
1.4.190


commons-dbcp
commons-dbcp
1.4



mysql
mysql-connector-java
5.1.38


org.hibernate
hibernate-entitymanager
4.3.11.Final


javax.servlet
javax.servlet-api
3.1.0
provided


org.thymeleaf
thymeleaf-spring4
2.1.4.RELEASE



我們已經配置好了所有Maven jar依賴項,包括Spring MVC,Spring Data JPA,JPA / Hibernate,Thymeleaf和Log4j。

第 2 步:使用 JavaConfig 配置 Service/DAO 層的 Bean

@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(basePackages="com.sivalabs.demo")
@PropertySource(value = { "classpath:application.properties" })
public class AppConfig
{
@Autowired
private Environment env;

@Bean
public static PropertySourcesPlaceholderConfigurer placeHolderConfigurer()
{
return new PropertySourcesPlaceholderConfigurer();
}

@Value("${init-db:false}")
private String initDatabase;

@Bean
public PlatformTransactionManager transactionManager()
{
EntityManagerFactory factory = entityManagerFactory().getObject();
return new JpaTransactionManager(factory);
}

@Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory()
{

LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean();

HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
vendorAdapter.setGenerateDdl(Boolean.TRUE);
vendorAdapter.setShowSql(Boolean.TRUE);

factory.setDataSource(dataSource());
factory.setJpaVendorAdapter(vendorAdapter);
factory.setPackagesToScan("com.sivalabs.demo");

Properties jpaProperties = new Properties();
jpaProperties.put("hibernate.hbm2ddl.auto", env.getProperty("hibernate.hbm2ddl.auto"));
factory.setJpaProperties(jpaProperties);

factory.afterPropertiesSet();
factory.setLoadTimeWeaver(new InstrumentationLoadTimeWeaver());
return factory;
}

@Bean
public HibernateExceptionTranslator hibernateExceptionTranslator()
{
return new HibernateExceptionTranslator();
}

@Bean
public DataSource dataSource()
{
BasicDataSource dataSource = new BasicDataSource();
dataSource.setDriverClassName(env.getProperty("jdbc.driverClassName"));
dataSource.setUrl(env.getProperty("jdbc.url"));
dataSource.setUsername(env.getProperty("jdbc.username"));
dataSource.setPassword(env.getProperty("jdbc.password"));
return dataSource;
}

@Bean
public DataSourceInitializer dataSourceInitializer(DataSource dataSource)
{
DataSourceInitializer dataSourceInitializer = new DataSourceInitializer();
dataSourceInitializer.setDataSource(dataSource);
ResourceDatabasePopulator databasePopulator = new ResourceDatabasePopulator();
databasePopulator.addScript(new ClassPathResource("data.sql"));
dataSourceInitializer.setDatabasePopulator(databasePopulator);
dataSourceInitializer.setEnabled(Boolean.parseBoolean(initDatabase));
return dataSourceInitializer;
}
}

在 AppConfig.java 所描述的配置類中,我們做了下面的事情:

  • 使用 @Configuration 註解使之成為 Spring 配置類。
  • 使用 @EnableTransactionManagement 註解允許基於註解的事務管理。
  • 配置 @EnableJpaRepositories 指示在哪裡尋找 Spring Data JPA 庫。
  • Configured PropertyPlaceHolder bean u使用 @PropertySource 註解和 PropertySourcesPlaceholderConfigurer 定義來配置 PropertyPlaceHolder Bean。配置屬性來自 application.properties 文件。
  • DataSource、JPA EntityManagerFactory JpaTransactionManager 定義 Bean。
  • 配置 DataSourceInitializer Bean,使之在應用啟動時執行 data.sql 腳本,初始化數據庫。

我們需要在

application.properties 中配置佔位屬性值:

「乾貨分享」為什麼使用 Spring Boot?

創建簡單的 SQL 腳本,data.sql,將示例數據填入 USER 表中:

「乾貨分享」為什麼使用 Spring Boot?

創建 log4j.properties 文件,在其中寫一些基礎配置:

「乾貨分享」為什麼使用 Spring Boot?

第3步:配置Spring MVC Web層Beans

我們必須配置Thymeleaf ViewResolver,靜態ResourceHandlers,適用於國際化的MessageSource,等等。

@Configuration
@ComponentScan(basePackages = { "com.sivalabs.demo"})
@EnableWebMvc
public class WebMvcConfig extends WebMvcConfigurerAdapter

{
@Bean
public TemplateResolver templateResolver() {
TemplateResolver templateResolver = new ServletContextTemplateResolver();
templateResolver.setPrefix("/WEB-INF/views/");
templateResolver.setSuffix(".html");
templateResolver.setTemplateMode("HTML5");
templateResolver.setCacheable(false);
return templateResolver;
}

@Bean
public SpringTemplateEngine templateEngine() {
SpringTemplateEngine templateEngine = new SpringTemplateEngine();
templateEngine.setTemplateResolver(templateResolver());
return templateEngine;
}

@Bean
public ThymeleafViewResolver viewResolver() {
ThymeleafViewResolver thymeleafViewResolver = new ThymeleafViewResolver();
thymeleafViewResolver.setTemplateEngine(templateEngine());
thymeleafViewResolver.setCharacterEncoding("UTF-8");
return thymeleafViewResolver;
}

@Override
public void addResourceHandlers(ResourceHandlerRegistry registry)
{
registry.addResourceHandler("/resources/**").addResourceLocations("/resources/");
}

@Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer)
{
configurer.enable();
}

@Bean(name = "messageSource")
public MessageSource configureMessageSource()
{
ReloadableResourceBundleMessageSource messageSource = new ReloadableResourceBundleMessageSource();
messageSource.setBasename("classpath:messages");
messageSource.setCacheSeconds(5);
messageSource.setDefaultEncoding("UTF-8");
return messageSource;
}
}

在我們的WebMvcConfig.java配置類中我們完成以下操作:

  • 使用@Configuration註解將其標記為Spring配置類。
  • 使用@EnableWebMvc啟用基於註解的Spring MVC配置,
  • 通過註冊TemplateResolver, SpringTemplateEngine, ThymeleafViewResolver Bean來配置Thymeleaf ViewResolver。
  • 註冊ResourceHandlers Bean表明URI/resources/**靜態資源請求將由本地/resources/目錄提供服務。
  • 配置MessageSource Bean通過ResourceBundle加載classpath下的messages-{country-code}.properties國際化信息。

目前我們沒有要配置的信息,所以在src/main/resources文件夾下創建一個空的messages.properties文件。

第4步:註冊Spring MVC FrontController Servlet DispatcherServlet

在Servlet 3.x規範之前我們必須在web.xml註冊Servlets/Filters。自從Servlet 3.x規範出臺我們能夠使用ServletContainerInitializer以編程方式註冊Servlets/Filters。

Spring MVC提供了一個方便的類AbstractAnnotationConfigDispatcherServletInitializer用於註冊DispatcherServlet.

public class SpringWebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer
{

@Override
protected Class>[] getRootConfigClasses()
{
return new Class>[] { AppConfig.class};
}

@Override
protected Class>[] getServletConfigClasses()
{
return new Class>[] { WebMvcConfig.class };
}

@Override
protected String[] getServletMappings()
{
return new String[] { "/" };
}

@Override
protected Filter[] getServletFilters() {
return new Filter[]{ new OpenEntityManagerInViewFilter() };
}
}

SpringWebAppInitializer.java中我們已經完成了以下的事情:

  • 配置了AppConfig.class 作為 RootConfirationClasses ,它將成為包含所有子上下文(DispatcherServlet)共享的bean定義的父ApplicationContext
  • 配置WebMvcConfig.class作為ServletConfigClasses,它是包括WebMvc bean定義的子ApplicationContext
  • 配置ServletMapping為”/”,讓DispatcherServlet處理所有請求。
  • 註冊OpenEntityManagerInViewFilter過濾器,用於展開視圖時懶加載JPA實體集合。

第五步:創建JPA實體和Spring Data JPA repository

創建JPA實體User.java

和User實體對應的Spring Data JPA repository。

@Entity
public class User
{
@Id @GeneratedValue(strategy=GenerationType.AUTO)
private Integer id;
private String name;

//setters and getters
}
public interface UserRepository extends JpaRepository
{
}

第六步:創建Spring MVC控制器

創建SpringMVC控制器來處理”/”URL請求並返回用戶列表。

@Controller
public class HomeController
{
@Autowired UserRepository userRepo;

@RequestMapping("/")
public String home(Model model)
{
model.addAttribute("users", userRepo.findAll());
return "index";
}
}

第七步:創建Thymeleaf視圖:/WEB-INF/views/index.html來展示用戶列表


xmlns:th="http://www.thymeleaf.org">


Home















Id Name
Id Name



我們準備好運行程序啦。但在此之前,我們需要下載和配置諸如Tomcat或者Jetty

或者Wilddfly等容器。

你可以下載Tomcat 8並在你喜歡使用的IDE中配置並運行。然後打開瀏覽器訪問http://localhost:8080/springmvcjpa-demo。你可以看到user的詳細列表。

耶…我們做到了。

但是等一下~這不是花了非常多的工作量才能做一個從數據庫中讀取並顯示用戶列表信息嗎?

我們公正公平來看問題。所有的這種配置並不只是一個用戶案例。這個配置也是應用程序其它部分的基礎。

回過頭來,如果你只是想快速獲得和運行一個應用來說這是在是太麻煩太複雜了。

另一個問題是,如果你想開發另一個有類似技術棧的 SpringMVC 應用嗎?

好的,你可能為了拷貝粘貼這些配置而感到苦惱。是嗎?提出一個記憶深刻的問題:如果你要做類似的事情重複一遍又一遍,那麼你是不是想尋找一個能自動處理的方式解決問題。

各種分散的配置寫了一遍又一遍,你會想到這裡會有一些其他的麻煩問題嗎?

好的,在這讓我把這些我能想到的問題列出。

  • 你需要注意所有的類庫的兼容性與 Spring 版本搭配和配置。
  • 在配置裡面有 95% 的時間我們都是在配置 DataSourceEntityManagerFactoryTransactionManger 之類的實體。但如果 Spring 能夠自動的為我們完成這些配置豈不是更好啊。
  • 類似的配置 SpringMVC 實體類比如 ViewResolverMessageSource 等又需要花更多的工作時間了。

想一想,要怎樣才能讓 Spring 能夠自動化的完成配置實體?怎麼樣你才可以快速簡單的使用基於可定製的屬性完成自動的配置呢?

比如,將 DispacherServlet 的 url-pattern 映射 “/” 映射到 “/app/”。將 “/WEB-INF/views” 目錄 替換為在 “/WEB-INF/templates/” 目錄加入 Thymeleaf 視圖。

所以基本上,你希望 Spring 自動執行一些操作,但是又能夠提供更簡單的方式靈活的提供重寫默認配置?

好的,現在你正在走進 Spring Boot 的世界在裡面你所期待已久的那些東西都已經有了!!!

快速上手品味 Spring Boot

歡迎來到 Spring Boot 世界!Spring Boot 並不是需要你完全地關注和掌握很多東西。它可以默認的完成自動化的配置但是你又可以按自己的需要去重新配置任意配置。

相比我更喜歡用一個例子來說明而不是更多的解析。

所以讓我們現在開始用 Spring Boot 來快速構建一個應用。

Step 1:創建一個 Spring Boot 的 Maven 項目

創建一個 Maven 項目和(在 pom.xml 裡面)配置項目 jar 包依賴如下:


xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/maven-v4_0_0.xsd">
4.0.0
com.sivalabs
hello-springboot
jar

1.0-SNAPSHOT
hello-springboot


org.springframework.boot
spring-boot-starter-parent
1.3.2.RELEASE



UTF-8
1.8





org.springframework.boot
spring-boot-starter-test


org.springframework.boot

spring-boot-starter-data-jpa


org.springframework.boot
spring-boot-starter-web


org.springframework.boot
spring-boot-starter-thymeleaf


org.springframework.boot
spring-boot-devtools


mysql
mysql-connector-java



哇原來 pom.xml 的配置這麼少感覺簡單多了!

Step 2:在 application.properties 中配置數據源或JPA 屬性配置如下:

spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/test
spring.datasource.username=root
spring.datasource.password=admin
spring.datasource.initialize=true
spring.jpa.hibernate.ddl-auto=update
spring.jpa.show-sql=true

你可以拷貝一些類似 data.sql 的文件到 src/main/resources 目錄中。

Step 3:創建一些 JAP 實體類和實體類所需要的 Spring Data JAP Repository 接口

springmvc-jpa-demo 應用項目中創建 User.javaUserRepository.javaHomeController.java 之類所需的東西。

Step 4:用 Thymeleaf 模板語言創建一個顯示用戶列表的視圖

springmvc-jap-demo 應用拷貝 /WEB-INF/views/index.html

到我們的新項目的 src/main/resources/templates 目錄中。

Step 5:創建一個 SpringBoot 啟動入口實體的類

創建一個有 main 函數的 Java 類 Application.java 如下:

@SpringBootApplication
public class Application
{
public static void main(String[] args)
{
SpringApplication.run(Application.class, args);
}
}

現在用 Java Application 的方式開始啟動運行 Application.java 之後打開瀏覽器訪問 http://localhost:8080/

你就可以在頁面的表格上看到用戶列表的顯示。這感覺實在太酷了!!!

OK 好的,我想你會大聲說”這裡邊到底發生了做了些什麼???”。

讓我說明下剛才發生了什麼

1. 輕鬆地依賴管理

  • 首要察覺一點是我們用的是一些名為spring-boot-starter-*.的依賴項。要記得我說過 “95%的時間裡用的配置相同”。因此當默認添加springboot-starter-web依賴項時,它將在開發Spring-webmvcjackson-jsonvalidation-apitomcatSpring MVC應用程序中提取所有常用庫。
  • 我們添加了spring-boot-starter-data-jpa依賴項。這會拉取所有spring-data-jpa依賴項並添加Hibernate庫,因為大多數應用程序都把Hibernate作為JPA實施。

2. 自動配置

  • spring-boot-starter-web不僅添加了所有這些庫,還配置了常見的bean,例如
    DispatcherServletResourceHandlersMessageSourcebean,具有合理的缺省值。
  • 我們還添加了spring-boot-starter-Thymeleaf,它不僅添加了Thymeleaf庫依賴項,還自動配置了ThymeleafViewResolver bean
  • 我們並沒有定義任何的DataSourceEntityManagerFactoryTransactionManageretc bean,但是它們會自動地創建。如何?如果我們的類路徑中有任何像H2或是HSQL的內存數據庫驅動程序,那麼SpringBoot將自動創建一個內存中的DataSource,然後自動註冊EntityManagerFactory,以及擁有合理的缺省值TransactionManager bean。但我們在用MySQL,所以我們需要提供明確的
    MySQL連接細節。我們在application.propertiesfile中配置了這些MySQL連接細節,並且SpringBoot使用了這些屬性來創建一個DataSource

3.嵌入式Servlet容器支持

最重要也是最驚奇的是我們創建了一個簡單的Java類,註釋了一些神奇的註解@SpringApplication,它有一個main方法,通過運行main,我們可以運行應用程序並在http:// localhost:8080 /上訪問它。

servlet容器從何而來?

我們已經添加了spring-boot-starter-web,它自動拉出spring-boot-starter-tomcat,當我們運行main()方法時,它為嵌入式容器啟動了tomcat,這樣我們就不必在任何外部安裝的tomcat服務器上部署我們的應用程序了。

另外而言,你注意到我們在pom.xml中的打包類型是’jar’而不是’war’。 極其有趣!

好吧,但如果我想使用Jetty服務器而不用tomcat呢?

很簡單,從spring-boot-starter-web中將spring-bootstarter-tomcat排除,只留有spring-boot-starter-jetty。

就是這樣。

但是,這看起來很神奇!我可以想象你在想什麼。你覺得SpringBoot看起來很酷,它會自動為我做很多事情。但我仍然沒有完全理解它是如何真正在幕後工作的。對麼?

我明白。觀看魔術表演通常很有趣,但在軟件開發中卻沒有。別擔心,未來文章中我們將會查看這些內容,並詳細解釋幕後發生的事情。但是現在我不想在此文中將所有內容都轉發給你,從而壓倒你。

來源:http://codebay.cn/post/10067.html


分享到:


相關文章: