从技术角度来看,咱们要用Spring MVC来处理Web请求,用Thymeleaf来定义Web视图,用Spring Data JPA来把阅读列表持久化到数据库里,姑且先用嵌入式的H2数据库。
html
咱们能够进入到Spring 的官网:http://start.spring.io/
进入官网后,能够快速的构建Spring boot 的基础项目,这里能够选择Maven 项目或者Gradle 项目,而后设置项目相关的配置。java
在选择Generate Project 进行项目下载后,会生成对应的zip 文件。后续只须要将Zip 文件解压,添加到IDE 中便可。git
除了在SpringIO 官网进行项目初始化外,还能够经过IDEA 进行项目的搭建。以下图所示,项目的搭建也是引用了 http://start.spring.io/ github
在后续的页面中,咱们能够设置相关的配置信息,一些经常使用的依赖,也能够进行初始化。web
除了以上经常使用的项目建立方法之外,咱们还能够经过CLI 进行项目的建立:spring
spring init -dweb,data-jpa,h2,thymeleaf --build gradle readinglist
CLI的init命令是不能指定项目根包名和项目名的。包名默认是demo,项目名默认是Demo。sql
无论咱们采用哪一种方式进行项目的建立,在将项目导入IDE以后,咱们能够看到整个项目结构遵循传统Maven或Gradle项目的布局,即主要应用程序代码位于src/main/java目录里,资源都在src/main/resources目录里,测试代码则在src/test/java目录里。此刻尚未测试资源,但若是有的话,要放在src/test/resources里。数据库
Application 类在Spring boot应用程序中有两个做用:配置和启动引导。
express
import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication --开启组件扫描和自动配置 public class SpringBootWebApplication { public static void main(String[] args) { SpringApplication.run(SpringBootWebApplication.class, args); -- 负责启动引导应用程序 } }
咱们在使用Spring boot 进行开发时,Application 类是咱们启动服务的入口,起到关键做用的是 **@SpringBootApplication** 这一注解,实际上 @SpringBootApplication 包含了三个有用的注解:apache
这里使用到main 方法是须要提供一个@EnableAutoConfiguration 注解的引导类,来引导整个应用程序的启动。
项目建立时问咱们建立了一个带有上下文的测试类。
import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringRunner; @RunWith(SpringRunner.class) @SpringBootTest -- 经过SpringBoot 加载上下文 public class SpringBootWebApplicationTests { @Test public void contextLoads() { -- 测试加载的上下文 } }
实际上,这个文件是可选的,你能够删掉它而不影响应用程序的运行。
咱们能够经过向application.properties 中添加变量,从而改变程序的默认配置。例如:
server.port=8000
server.contextPath=SpringBootWeb
在上述代码中,咱们将程序的默认端口(8080) 修改为为使用 8000 端口,而且将应用程序的项目名修改成 SpringBootWeb。
原访问地址:
http://127.0.0.1:8080/
修改后:
http://127.0.0.1:8000/SpringBootWeb/
除此以外 还能够配置多环境的变量设置等一系列的设置:
spring.profiles.active = dev
在代码清单中,咱们引用了 spring-boot-starter-parent 做为上一级,这样一来就能利用到Maven 的依赖管理功能,集成不少经常使用库的依赖,而且不须要知道版本。除此以外,也使用到了开篇所提到过的起步依赖,咱们只须要引入 spring-boot-starter-web 这一依赖,就可使用到Web 中经常使用的包。
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.5.7.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> ... </dependencies>
以下图所示,咱们使用到的 spring-boot-starter-web 依赖中,已经集成了经常使用的mvc json 等相关依赖。
org.springframework.boot:spring-boot-starter-web:jar:1.5.7.RELEASE:compile
[INFO] | +- org.springframework.boot:spring-boot-starter-tomcat:jar:1.5.7.RELEASE:compile
[INFO] | | +- org.apache.tomcat.embed:tomcat-embed-core:jar:8.5.20:compile
[INFO] | | +- org.apache.tomcat.embed:tomcat-embed-el:jar:8.5.20:compile
[INFO] | | \- org.apache.tomcat.embed:tomcat-embed-websocket:jar:8.5.20:compile
[INFO] | +- org.hibernate:hibernate-validator:jar:5.3.5.Final:compile
[INFO] | | +- javax.validation:validation-api:jar:1.1.0.Final:compile
[INFO] | | \- com.fasterxml:classmate:jar:1.3.4:compile
[INFO] | +- com.fasterxml.jackson.core:jackson-databind:jar:2.8.10:compile
[INFO] | | +- com.fasterxml.jackson.core:jackson-annotations:jar:2.8.0:compile
[INFO] | | \- com.fasterxml.jackson.core:jackson-core:jar:2.8.10:compile
[INFO] | +- org.springframework:spring-web:jar:4.3.11.RELEASE:compile
[INFO] | \- org.springframework:spring-webmvc:jar:4.3.11.RELEASE:compile
[INFO] | \- org.springframework:spring-expression:jar:4.3.11.RELEASE:compile
如你所见,Book类就是简单的Java对象,其中有些描述书的属性,还有必要的访问方法。
@Entity注解代表它是一个JPA实体,id属性加了@Id和@GeneratedValue注解,说明这个字段
是实体的惟一标识,而且这个字段的值是自动生成的。
import lombok.AllArgsConstructor; import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; /** * Created by weijie_huang on 2017/9/20. */ @Entity @Getter @Setter @NoArgsConstructor @AllArgsConstructor public class Book { @Id @GeneratedValue(strategy = GenerationType.AUTO) private Long id; private String reader; private String isbn; private String title; private String author; private String description; }
经过扩展JpaRepository,ReadingListRepository直接继承了18个执行经常使用持久化操做
的方法。JpaRepository是个泛型接口,有两个参数:仓库操做的领域对象类型,及其ID属性的
类型。此外,我还增长了一个findByReader()方法,能够根据读者的用户名来查找阅读列表。
import com.jaycekon.demo.domain.Book; import org.springframework.data.jpa.repository.JpaRepository; import java.util.List; /** * Created by weijie_huang on 2017/9/20. */ public interface ReadRepository extends JpaRepository<Book,Long> { List<Book> findByReader(String reader); }
在定义好了应用程序的实体类,持久化接口后。咱们还须要建立一个MVC 控制器来处理HTTP请求。
import com.jaycekon.demo.dao.ReadRepository; import com.jaycekon.demo.domain.Book; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import java.util.List; /** * Created by weijie_huang on 2017/9/20. */ @Controller public class ReadController { @Autowired private ReadRepository readRepository; @RequestMapping(value="/{reader}", method= RequestMethod.GET) public String readersBooks( @PathVariable("reader") String reader, Model model) { List<Book> readingList = readRepository.findByReader(reader); if (readingList != null) { model.addAttribute("books", readingList); } return "readingList"; } @RequestMapping(value="/{reader}", method=RequestMethod.POST) public String addToReadingList( @PathVariable("reader") String reader, Book book) { book.setReader(reader); readRepository.save(book); return "redirect:/{reader}"; } }
使用了@Controller注解,这样组件扫描会自动将其注册为
Spring应用程序上下文里的一个Bean。经过@Autowired 将仓库接口注入到控制类中。
在开发完成后,咱们去到Application 类下,启动main 方法。便可将应用程序启动,而后进入到下述页面(html 文件不细述,可经过查看源码进行了解)。能够看到,咱们的服务已经成功启动。
你们可能会很疑惑,为何咱们没有配置数据库信息,却没有报异常。咱们明明建立了 ReadRepository 数据库接口,若是没有DataSource 的话,应该是会报异常的。可是Spring boot 却巧妙的避开了这种问题。
首先咱们须要来了解一下Spring-boot-autoconfigure 这个依赖包。这个Jar包下包含了不少的配置类。例如Thymeleaf,JPA以及Mvc的相关配置。
这里主要涉及到了Condition 接口,该接口的做用是,只有到某个条件达成后,才回对这个Bean 进行实例化。
注解:
上述程序之全部没有进行数据库操做,主要能够参考 DataSourceAutoConfiguratio 这个类的相应配置。
@Configuration @ConditionalOnClass({DataSource.class, EmbeddedDatabaseType.class}) @EnableConfigurationProperties({DataSourceProperties.class}) @Import({Registrar.class, DataSourcePoolMetadataProvidersConfiguration.class}) public class DataSourceAutoConfiguration
能够看到,只有DataSource 这个类实例化以后,这个Bean才会进行实例化。咱们再往下观察能够看到 JdbcTemplateConfiguratio 也有想相似的状况。
此处看到的只是DataSourceAutoConfiguration的冰山一角,Spring Boot提供的其余自
动配置类也有不少知识没有提到。但这已经足以说明SpringBoot如何利用条件化配置实现自动配置。
自动配置会作出如下配置决策,它们和以前的例子息息相关。
- 由于Classpath 里有H2 , 因此会建立一个嵌入式的H2 数据库Bean , 它的类型是
javax.sql.DataSource,JPA实现(Hibernate)须要它来访问数据库。
- 由于Classpath里有Hibernate(Spring Data JPA传递引入的)的实体管理器,因此自动配置
会配置与Hibernate 相关的Bean , 包括Spring 的LocalContainerEntityManager-
FactoryBean和JpaVendorAdapter。
- 由于Classpath里有Spring Data JPA,因此它会自动配置为根据仓库的接口建立仓库实现。
- 由于Classpath里有Thymeleaf,因此Thymeleaf会配置为Spring MVC的视图,包括一个
Thymeleaf的模板解析器、模板引擎及视图解析器。视图解析器会解析相对于Classpath根
目录的/templates目录里的模板。
- 由于Classpath 里有Spring MVC ( 归功于Web 起步依赖), 因此会配置Spring 的
DispatcherServlet并启用Spring MVC。
- 由于这是一个Spring MVC Web应用程序,因此会注册一个资源处理器,把相对于Classpath
根目录的/static目录里的静态内容提供出来。(这个资源处理器还能处理/public、/resources
和/META-INF/resources的静态内容。)
- 由于Classpath里有Tomcat(经过Web起步依赖传递引用),因此会启动一个嵌入式的Tomcat
容器,监听8080端口。
经过Spring Boot的起步依赖和自动配置,你能够更加快速、便捷地开发Spring应用程序。起步依赖帮助你专一于应用程序须要的功能类型,而非提供该功能的具体库和版本。与此同时,自动配置把你从样板式的配置中解放了出来。这些配置在没有Spring Boot的Spring应用程序里很是常见。
虽然自动配置很方便,但在开发Spring应用程序时其中的一些用法也有点武断。要是你在配置Spring时但愿或者须要有所不一样,该怎么办?在第3章,咱们将会看到如何覆盖Spring Boot自动配置,借此达成应用程序的一些目标,还有如何运用相似的技术来配置本身的应用程序组件。
github 地址:https://github.com/jaycekon/SpringBoot