Spring Boot (1): Quick Start
This series of articles is designed to help beginners quickly master the components of Spring Boot using the minimal dependency and simplest configuration to get started.The sample code used in all articles synchronizes the Github and Gitee repositories.
1. What is Spring Boot?
Spring Boot is a new framework provided by the Pivotal team and is designed to simplify the initial build and development of new Spring applications.The framework is configured in a specific way so that developers no longer need to define a template configuration.
The general point is that Spring Boot is not a new framework, it just integrates and implements many of the frameworks by default.
2. What are the benefits?
The big advantage is that it's simple, fast and convenient. Before Spring Boot, what do we need to do if we want to build a framework?
- Configure web.xml, load Spring and Spring MVC, load various filters, interceptors
- Configure the database, configuration cache, configuration connection pool, etc. in the configuration file application.xml
- configure log files
- Configure reading of various profiles
- Configure context, configure timer tasks
- ...
- Various configurations
- ...
The author has a project that happened to exist a long time ago, Spring 3.x was still used at that time. I can show you how many configuration files there were for a project at that time:
And if I need to create a new project, a lot of the configuration files are copied in the past and re-debugged, which is inconvenient and time-consuming, and these nightmares are over when Spring Boot comes out.
Advantages of Spring Boot:
- Getting started faster for all Spring developers
- Out of the box, provides various default configurations to simplify project configuration
- Embedded Containers Simplify Web Projects
- No redundant code generation and XML configuration requirements
3. Quick Start
Targeting: Build a simple RESTful API and implement corresponding unit tests
3.1 How to Build a Project
Spring Boot provides two ways to build projects:
There are currently two more convenient options for creating a springcloud project, the core of which is the same, so you can choose your own convenience for use.
Mode 1:
Open spring's official link:
Fill in your organization in Group s, typically by writing your company's domain name, such as com.jd or com
baidu, here I'm writing com.springboot directly
Fill in the name of the project in Artifact, where I write spring-boot-quick-start directly.
package chooses jar, java chooses 11 (the latest version of LTS so far), so the basic choices are all selected, and now we're going to start choosing the components of the Spring Boot we're using.
Find the Spring Web in Dependencies and select the Spring Web with the following results:
Finally, click on the green bar button Generate the project below to download, wait until the download is complete, and then decompress the package directly into our editing tool idea.
Mode 2:
Create based on idea, open the idea, first file->new->project, select Spring Initializr, then you can see on the right let's select an initialized service url, the default is the official link above. https://start.spring.io/
Click Next Next, fill in the same information as above about Group, Artifact, java version, package way, etc. to continue Next Next, select dependencies, as in the previous method, find Spring Web in Dependencies, select Spring Web, click next, select project name and storage path, pointClick finish and wait a moment. The first item, spring-boot-quick-start, is fresh ~~
I typically choose the first way to create a Spring Boot project, which does not rely on IDE tools.
3.2 Engineering Structure Analysis
First, let's look at the structure of the project we created, as shown below:
- pom.xml:maven project configuration file, which configures some basic information about the current project, including the components, versions, etc. that we are currently using.
- Program entry under src/main/java: Chapter1Application.
- Configuration file under src/main/resources: application.properties.
- Test entry under src/test/Chapter1ApplicationTests.
3.3 pom.xml
Here we focus on the <dependencies>tag, which describes the components we introduced
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies>
- spring-boot-starter-web:Web module
- spring-boot-starter-test: Test modules, including JUnit, Hamcrest, Mockito
3.4 Implement a set of RESTful API s for User objects using Spring MVC
The RESTful API is designed as follows:
Request Type | URL | function |
---|---|---|
GET | / | Query User List |
POST | / | Create User |
GET | /{id} | Get user information based on id in url |
PUT | /{id} | Update user information based on id |
DELETE | /{id} | Delete user information based on id |
Note: RESTful interfaces should be designed with standard methods and semantics that incorporate security and idempotency considerations, such as GET and HEAD requests, which are secure and do not change the state of the server no matter how many requests are made.GET, HEAD, PUT, and DELETE requests are all idempotent, and the results are always the same no matter how many times the resource is operated on, and subsequent requests will not have more impact than the first one.
Typical uses of GET, DELETE, PUT, and POST are listed below:
GET
- Safe and idempotent
- Get Representation
- Get Representation on Change (Cache)
POST
- Unsafe and not idempotent
- Create resources using server-side managed (auto-generated) instance numbers
- Create subresources
- Partial Update Resources
- If it is not modified, the resource is updated (optimistic lock)
PUT
- Unsafe but idempotent
- Create a resource with the instance number of client management
- Update resources by replacement
- Update resources if not modified (Optimistic lock)
DELETE
- Unsafe but idempotent
- Delete resources
The user Model classes are as follows:
public class UserModel { private Long id; private String name; private int age; // Omit getter s and setter s }
The REST API implementation classes are as follows:
@RestController public class UserController { // Create a thread-safe Map to use as a data store static Map<Long, UserModel> users = new ConcurrentHashMap<>(); /** * Query User List * @return */ @GetMapping("/") public List<UserModel> getUserList() { List<UserModel> list = new ArrayList<UserModel>(users.values()); return list; } /** * Create User * @param userModel * @return */ @PostMapping("/") public UserModel postUser(@ModelAttribute UserModel userModel) { users.put(userModel.getId(), userModel); return users.get(userModel.getId()); } /** * {id} Get user information based on id in url * url The id in can be bound to the parameters of a function through @PathVariable * @param id * @return */ @GetMapping("/{id}") public UserModel getUser(@PathVariable Long id) { return users.get(id); } /** * Update user information based on id * @param id * @param userModel * @return */ @PutMapping("/{id}") public UserModel putUser(@PathVariable Long id, @ModelAttribute UserModel userModel) { UserModel u = users.get(id); u.setName(userModel.getName()); u.setAge(userModel.getAge()); users.put(id, u); return users.get(userModel.getId()); } /** * Delete user information based on id * @param id * @return */ @DeleteMapping("/{id}") public String deleteUser(@PathVariable Long id) { users.remove(id); return "success"; } }
- @Controller: Decorates the class to create an object that handles http requests
- Annotations added after @RestController:Spring4 that originally returned json in @Controller require @ResponseBody to work with. If @RestController is directly used instead of @Controller, the @ResponseBody will no longer need to be configured and json format will be returned by default.
Looking at @RestController, you can see that @RestController itself consists of @ResponseBody and @Controller with the following source code:
@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented @Controller @ResponseBody public @interface RestController { /** * The value may indicate a suggestion for a logical component name, * to be turned into a Spring bean in case of an autodetected component. * @return the suggested component name, if any (or empty String otherwise) * @since 4.0.1 */ @AliasFor(annotation = Controller.class) String value() default ""; }
The unit test classes are as follows:
@RunWith(SpringRunner.class) @SpringBootTest public class SpringBootQuickStartApplicationTests { private MockMvc mvc; @Before public void setUp() throws Exception { mvc = MockMvcBuilders.standaloneSetup(new UserController()).build(); } @Test public void contextLoads() throws Exception { RequestBuilder request = null; // 1. get checks the list of user s and should be empty request = MockMvcRequestBuilders.get("/") .contentType(MediaType.APPLICATION_JSON); mvc.perform(request) .andExpect(MockMvcResultMatchers.status().isOk()) .andDo(MockMvcResultHandlers.print()) .andReturn(); // 2. post submits a user request = MockMvcRequestBuilders.post("/") .param("id", "1") .param("name", "Spring Boot") .param("age", "18") .contentType(MediaType.APPLICATION_JSON); mvc.perform(request) .andExpect(MockMvcResultMatchers.status().isOk()) .andDo(MockMvcResultHandlers.print()) .andReturn(); // 3. get get a list of user s, there should be data just inserted request = MockMvcRequestBuilders.get("/") .contentType(MediaType.APPLICATION_JSON); mvc.perform(request) .andExpect(MockMvcResultMatchers.status().isOk()) .andDo(MockMvcResultHandlers.print()) .andReturn(); // 4. user whose put modifies id 1 request = MockMvcRequestBuilders.put("/1") .param("name", "Spring Boot Test") .contentType(MediaType.APPLICATION_JSON); mvc.perform(request) .andExpect(MockMvcResultMatchers.status().isOk()) .andDo(MockMvcResultHandlers.print()) .andReturn(); // 5. get a user with id 1 request = MockMvcRequestBuilders.get("/1") .contentType(MediaType.APPLICATION_JSON); mvc.perform(request) .andExpect(MockMvcResultMatchers.status().isOk()) .andDo(MockMvcResultHandlers.print()) .andReturn(); // 6. Delete user with id 1 request = MockMvcRequestBuilders.delete("/1") .contentType(MediaType.APPLICATION_JSON); mvc.perform(request) .andExpect(MockMvcResultMatchers.status().isOk()) .andDo(MockMvcResultHandlers.print()) .andReturn(); // 7. get checks the list of user s and should be empty request = MockMvcRequestBuilders.get("/") .contentType(MediaType.APPLICATION_JSON); mvc.perform(request) .andExpect(MockMvcResultMatchers.status().isOk()) .andDo(MockMvcResultHandlers.print()) .andReturn(); } }
Launch the test class, and the console prints as follows, capturing only one section for demonstration:
MockHttpServletRequest: HTTP Method = POST Request URI = / Parameters = {id=[1], name=[Spring Boot], age=[18]} Headers = [Content-Type:"application/json"] Body = <no character encoding set> Session Attrs = {} Handler: Type = com.springboot.springbootquickstart.controller.UserController Method = public com.springboot.springbootquickstart.model.UserModel com.springboot.springbootquickstart.controller.UserController.postUser(com.springboot.springbootquickstart.model.UserModel) Async: Async started = false Async result = null Resolved Exception: Type = null ModelAndView: View name = null View = null Model = null FlashMap: Attributes = null MockHttpServletResponse: Status = 200 Error message = null Headers = [Content-Type:"application/json;charset=UTF-8"] Content type = application/json;charset=UTF-8 Body = {"id":1,"name":"Spring Boot","age":18} Forwarded URL = null Redirected URL = null Cookies = []
From console printing, you can see the entire simulation request process as well as the parameters.
Sample Code-Github
Sample Code-Gitee
4. Reference
Spring Boot(1): Introduction
Spring Boot Build RESTful API and Unit Testing