Build the project
From a technical point of view, we’ll use Spring MVC to handle Web requests, Thymeleaf to define Web views, and Spring Data JPA to persist reading lists to a database, let’s start with an embedded H2 database.
1. Project construction
Build the official website of Spring IO
IO/After entering the official website, you can quickly build the basic project of Spring Boot. Here you can choose Maven project or Gradle project, and then set the configuration related to the project.
After you select Generate Project for Project download, the corresponding ZIP file will be generated. All you need to do is unzip the Zip file and add it to the IDE.
IDEA quick build
In addition to project initialization on SpringIO’s official website, project construction can also be carried out through IDEA. As you can see in the figure below, the setup of the project also references start.spring. IO /
In the following pages, we can set the configuration information, some common dependencies, and also initialize them.
Spring Boot CLI
In addition to the above common project creation methods, we can also use the CLI to create projects:
spring init -dweb,data-jpa,h2,thymeleaf --build gradle readinglistCopy the code
The CLI init command cannot specify the root package name or project name. The default package name is Demo, and the default project name is Demo.
2. Directory structure
No matter which way we create the project, after importing the project into the IDE, we can see that the entire project structure follows the layout of a traditional Maven or Gradle project, where the main application code is located in the SRC /main/ Java directory and the resources are located in the SRC /main/ Resources directory. The test code is in the SRC /test/ Java directory. There are no test resources available at the moment, but if there are, place them in SRC /test/ Resources.
Introduction to the document:
- SpringBootWebApplication: application startup guide class (the bootstrap class), is also a major Spring configuration classes.
- Appliction.properties: Used to configure the properties of the application and Spring Boot
- SpringBootWebApplicationTests: a basic integration test class.
- Pom.xml: Project dependency file
3. Document introduction
SpringBootWebApplication
The Application class has two roles in a Spring Boot Application: configuration and boot.
import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; Public class SpringBootWebApplication {public static void main(String[] args) {public static void main(String[] args) { SpringApplication.run(SpringBootWebApplication.class, args); -- Responsible for starting the boot application}}Copy the code
When we’re developing with SpringBoot, the Application class is our entry point to start the service. The key is the @SpringBootApplication annotation, In fact, @SpringBootApplication contains three useful annotations:
- @Configuration: indicates that the class uses Spring’s Java-based Configuration.
- @componentscan: enable component scanning so that your Web controller classes and other ComponentScan be automatically discovered and registered as beans in the context of your Spring application.
- @enableAutoConfiguration: This configuration enables automatic configuration of Spring Boot.
The main method is used to provide a bootstrap class annotated with @enableAutoConfiguration to bootstrap the entire application.
SpringBootWebApplicationTests
At project creation we create a test class with a context.
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 - through SpringBoot loading context public class SpringBootWebApplicationTests {@ Test public voidcontextLoads() {-- Test load context}}Copy the code
application.properties
In fact, this file is optional, and you can delete it without affecting the application. You can change the default configuration of your application by adding variables to application.properties. Such as:
server.port=8000
server.contextPath=SpringBootWebCopy the code
In the code above, we changed the default port of the program (8080) to use port 8000 and changed the project name of the application to SpringBootWeb.
Original address: http://127.0.0.1:8080/
Revised: http://127.0.0.1:8000/SpringBootWeb/
In addition, you can also configure a series of Settings such as variable Settings for multiple environments:
spring.profiles.active = devCopy the code
pom.xml
In the code listing, we refer to spring-boot-starter-parent as the upper level, so that we can take advantage of Maven’s dependency management capabilities and integrate many common library dependencies without knowing the version. In addition, we also use the starter dependency mentioned in the beginning. We only need to introduce the spring-boot-starter-web dependency to use the packages commonly used in the Web.
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> The < 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>Copy the code
As shown in the figure below, the spring-boot-starter-Web dependency we use has been integrated with commonly used MVC JSON and other related dependencies.
Org. Springframework. The boot: spring - the boot - starter - web: jar: 1.5.7. RELEASE: the compile [INFO] | + - Org. Springframework. The boot: spring - the boot - starter - tomcat: jar: 1.5.7. RELEASE: the 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.mail. Validation: validation - API: jar: 1.1.0. Final: compile [INFO] | | \ - com fasterxml: classmate: jar: 1.3.4: compile the 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: the compile | \ [INFO] - Org. Springframework: spring - webmvc: jar: 4.3.11. RELEASE: the compile | \ [INFO] - Org. Springframework: spring - expression: jar: 4.3.11. RELEASE: the compileCopy the code
4. Develop functions
4.1 Defining the entity class Book
As you can see, the Book class is a simple Java object, with some describing the properties of the Book and the necessary access methods. The @Entity annotation indicates that it is a JPA Entity, and the ID attribute is annotated with @ID and @GeneratedValue, indicating that this field is the unique identification of the Entity and that the value of this field is automatically generated.
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;
}Copy the code
4.2 Defining the ReadRepository interface
By extending JpaRepository, ReadingListRepository directly inherits 18 methods that perform common persistence operations. JpaRepository is a generic interface that takes two parameters: the domain object type of the repository operation, and the type of its ID attribute. In addition, I’ve added a findByReader() method to find a reading list based on a reader’s username.
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);
}Copy the code
4.3 Defining the ReadController at the control layer
After defining the application’s entity classes and persisting interfaces. We also need to create an MVC controller to handle HTTP requests.
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}"; }}Copy the code
The @Controller annotation is used so that the component scan automatically registers it as a Bean in the Spring application context. Inject the warehouse interface into the control class via @Autowired.
4.4 Starting the Service
After development is complete, we go to the Application class and start the main method. Launch the application and take you to the following page (the HTML file is not detailed, but you can read the source code). As you can see, our service has started successfully.
4.5 Process Analysis
You might wonder why we didn’t report an exception when we didn’t configure the database. We created the ReadRepository database interface. If there is no DataSource, we should report an exception. But Spring Boot cleverly avoids this problem.
The spring-boot-autoconfigure dependency package needs to be looked at first. This Jar package contains a number of configuration classes. Examples include Thymeleaf, JPA, and Mvc configurations.
The main concern here is the Condition interface, which does nothing to instantiate the Bean until a Condition is reached.
Comments: ConditionalOnBean ConditionalOnMissingBean ConditionalOnMissingBean ConditionalOnMissingBean ConditionalOnMissingBean ConditionalOnClass Classpath @ ConditionalOnMissingClass Classpath in lack of the specified class @ ConditionalOnExpression given Spring Expression Language (SpEL) Expression calculating result is true ConditionalOnJava The Java version matches a specific value or a range of values. The @conditionalonJNDI parameter must have one of the JNDI locations given. ConditionalOnProperty has an explicit value for the configuration property specified by JNDI @conditionalonResource Classpath
All of the above procedure without database operations, the main can reference DataSourceAutoConfiguratio corresponding configuration of the class.
@Configuration
@ConditionalOnClass({DataSource.class, EmbeddedDatabaseType.class})
@EnableConfigurationProperties({DataSourceProperties.class})
@Import({Registrar.class, DataSourcePoolMetadataProvidersConfiguration.class})
public class DataSourceAutoConfigurationCopy the code
As you can see, the DataSource Bean is instantiated only after the class is instantiated. If we look further down we can see a similar situation with JdbcTemplateConfiguratio.
See only the tip of the iceberg of DataSourceAutoConfiguration here, Spring Boot other since dynamic configuration class also has a lot of knowledge didn’t mention. But this is enough to illustrate how SpringBoot can use conditional configuration for automatic configuration.
Automatic configuration makes the following configuration decisions, which are closely related to the previous example.
-
Because THERE is H2 in the Classpath, we create an embedded H2 database Bean of type Javax.sql.datasource that the JPA implementation (Hibernate) needs to access the database.
-
Since there is an entity manager for Hibernate (introduced by Spring Data JPA delivery) in your Classpath, automatic configuration will configure Hibernate related beans, Including LocalContainerEntityManager – FactoryBean and JpaVendorAdapter Spring.
-
Because the Classpath has the Spring Data JPA, it is automatically configured to create the repository implementation based on the repository’s interface.
-
Because Thymeleaf is in the Classpath, Thymeleaf is configured as a Spring MVC view, including a Thymeleaf template parser, template engine, and view parser. The view parser parses templates in the/Templates directory relative to the root of the Classpath.
-
Because you have Spring MVC in your Classpath (thanks to the Web startup dependency), Spring’s DispatcherServlet is configured and Spring MVC is enabled.
-
Since this is a Spring MVC Web application, a resource handler is registered to provide static content in the /static directory relative to the root of the Classpath. (This resource handler can also handle static content for /public, /resources, and/meta-INF /resources.)
-
Because Tomcat is in the Classpath (starting dependency passing references via the Web), an embedded Tomcat container is started, listening on port 8080.
conclusion
With Spring Boot’s startup dependencies and automatic configuration, you can develop Spring applications faster and more easily. Starting dependencies help you focus on the type of functionality your application needs, rather than the specific libraries and versions that provide that functionality. At the same time, autoconfiguration frees you from boilerplate configuration. These configurations are common in Spring applications without Spring Boot.
While automatic configuration is convenient, some of its uses can be a little arbitrary when developing Spring applications. What if you want or need to configure Spring differently? In Chapter 3, we’ll see how to override Spring Boot automatic configuration to achieve some of your application’s goals, and how to configure your own application components using similar techniques.
Github address: github.com/jaycekon/Sp…