Chapter 2: Microservice Construction: Spring Boot (Spring cloud microservices in action)

The main content of this chapter:

1. How to build a Spring Boot project

2. How to implement the RESTful API interface

3. How to implement multi-environment Spring Boot application configuration

4. In-depth understanding of the startup mechanism of Spring Boot configuration


Introduction to the framework

Spring Boot simplifies Spring's original template configuration by designing a large number of automated configurations, so that developers can quickly build applications. In addition to solving configuration problems, it also defines a series of Starter POMs to integrate various functions. References are made through template-like Starter template definitions, making dependency management easier.

The project built by Spring Boot only needs to package the Spring Boot application into a jar package and run it through the java -jar command to start a standardized web application. There is no need to package it into a war package and deploy it to run under tomcat.


Quick start

Environment preparation:

      java 7 and above

      Spring framework 

      maven 


build maven project

Visit the official address to quickly build the project, address: http://start.spring.io/


Click Generate Project to download the zip package, unzip it, and import it into the development tool.

 

Engineering structure analysis:

The entry of src/main/java main program: DemoApplication, you can directly run this class to start the Spring Boot application.

src/main/resources: Configuration directory, which is used to store some configuration information of the application, such as static resources, configuration files, etc.

src/test/ : Unit test directory


Maven configuration analysis:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>

	<groupId>com.example</groupId>
	<artifactId>demo</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<!-- The application is packaged as a jar by default. The default web dependency will include the embedded tomcat -->
	<packaging>jar</packaging>

	<name>demo</name>
	<description>Demo project for Spring Boot</description>

	<!-- The parent project defines the basic dependencies of the Spring Boot version and some default configuration content, such as the location of application.properties, etc. -->
	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.0.1.RELEASE</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>

	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
		<java.version>1.8</java.version>
	</properties>

	<dependencies>
		<!-- Full stack web development module, including embedded tomcat, spring MVC -->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
		<!-- Universal test module, including Junit, Hamcrest, Mockito -->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
	</dependencies>

	<build>
		<!-- Plug-in, can help to start and stop the service conveniently -->
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>


</project>


Implement RESTful APIs


package com.example.demo.controller;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class HelloController {
	
	@RequestMapping("/hello")
	public String index(){
		return "Hello World !";
	}

}

Start the app and visit http://localhost:8080/hello we can see that the expected result is returned



Three ways to start a Spring Boot application:

1. Start directly by running the class of the main function

2. Use the maven command: mvn spring-boot:run 

3. When deploying and running on the server, first use mvn install to package the application into a jar package, and then start the application through the java -jar ***.jar package


Write unit tests

package com.example.demo;

import static org.hamcrest.Matchers.equalTo;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.http.MediaType;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;

import com.example.demo.controller.HelloController;

@RunWith(SpringRunner.class)
@SpringBootTest
public class DemoApplicationTests {
	
	private MockMvc mvc;
	
	@Before
	public void setUp(){
		mvc = MockMvcBuilders.standaloneSetup(new HelloController()).build();
	}

	@Test
	public void hello() throws Exception {
		mvc.perform(MockMvcRequestBuilders.get("/hello").accept(MediaType.APPLICATION_JSON))
		.andExpect (status (). isOk ())
		.andExpect(content().string(equalTo("Hello World !")));
	}

}

Detailed configuration

The default configuration file of spring Boot is Lujin: src/main/resources/application.properties, the configuration content of spring Boot application can be concentrated in this file, such as container port number, application name, etc., data source, log level

server.port=8888
spring.application.name=hello

In addition to the properties file, the configuration file of springBoot can also use YMAL.

In addition to configuring the predefined configuration properties in each Starter template, you can also customize the properties, or directly refer to each parameter through PlaceHolder.

book.name=SpringCloudInAction
book.author=zhaiyongchao
book.desc=${book.author} is writing <<${book.name}>>
package com.example.demo.model;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

@Component
public class Book {
	
	@Value("${book.name}")
	private String name;
	
	@Value("${book.author}")
	private String author;
	
	@Value("${book.desc}")
	private String desc;

	/**
	 * @return the name
	 */
	public String getName() {
		return name;
	}

	/**
	 * @param name the name to set
	 */
	public void setName(String name) {
		this.name = name;
	}

	/**
	 * @return the author
	 */
	public String getAuthor() {
		return author;
	}

	/**
	 * @param author the author to set
	 */
	public void setAuthor(String author) {
		this.author = author;
	}

	/**
	 * @return the desc
	 */
	public String getDesc() {
		return desc;
	}

	/**
	 * @param desc the desc to set
	 */
	public void setDesc(String desc) {
		this.desc = desc;
	}
	
}

Test class:

package com.example.demo.model;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

@RunWith(SpringRunner.class)
@SpringBootTest
public class BookTest {

	@Autowired
	private Book book;
	
	@Test
	public void test(){
		String name = book.getName();
		String author = book.getAuthor();
		String desc = book.getDesc();
		System.out.println(name);
		System.out.println(author);
		System.out.println(desc);
	}
	
}

Test Results:

SpringCloudInAction
zhaiyongchao
zhaiyongchao is writing <<SpringCloudInAction>>

use random numbers

A random int value, long value or String can be generated through the ${random} configuration.

#random string
com.example.demo.blog.value=${random.value}
#random int
com.example.demo.blog.number=${random.int}
#random long
com.example.demo.blog.bignumber=${random.long}
Random numbers within #10
com.example.demo.blog.test1=${random.int(10)}
#10-20 random numbers
com.example.demo.blog.test2=${random.int[10,20]}
package com.example.demo.model;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

@RunWith(SpringRunner.class)
@SpringBootTest
public class BlogTest {
	
	@Autowired
	private Blog blog;
	
	@Test
	public void test(){
		System.out.println(blog.getName());
		System.out.println(blog.getCount());
		System.out.println(blog.getTotolCount());
		System.out.println(blog.getTest1());
		System.out.println(blog.getTest2());
	}

}

package com.example.demo.model;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

@Component
public class Blog {
	
	@Value("${com.example.demo.blog.value}")
	private String name;
	@Value("${com.example.demo.blog.number}")
	private int count ;
	@Value("${com.example.demo.blog.bignumber}")
	private long totolCount;
	@Value("${com.example.demo.blog.test1}")
	private int test1;
	@Value("${com.example.demo.blog.test2}")
	private int test2;

	/**
	 * @return the name
	 */
	public String getName() {
		return name;
	}

	/**
	 * @param name the name to set
	 */
	public void setName(String name) {
		this.name = name;
	}

	/**
	 * @return the count
	 */
	public int getCount() {
		return count;
	}

	/**
	 * @param count the count to set
	 */
	public void setCount(int count) {
		this.count = count;
	}

	/**
	 * @return the totolCount
	 */
	public long getTotolCount() {
		return totolCount;
	}

	/**
	 * @param totolCount the totolCount to set
	 */
	public void setTotolCount(long totolCount) {
		this.totolCount = totolCount;
	}

	/**
	 * @return the test1
	 */
	public int getTest1() {
		return test1;
	}

	/**
	 * @param test1 the test1 to set
	 */
	public void setTest1(int test1) {
		this.test1 = test1;
	}

	/**
	 * @return the test2
	 */
	public int getTest2() {
		return test2;
	}

	/**
	 * @param test2 the test2 to set
	 */
	public void setTest2(int test2) {
		this.test2 = test2;
	}
	
	

}
package com.example.demo.model;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

@RunWith(SpringRunner.class)
@SpringBootTest
public class BlogTest {
	
	@Autowired
	private Blog blog;
	
	@Test
	public void test(){
		System.out.println(blog.getName());
		System.out.println(blog.getCount());
		System.out.println(blog.getTotolCount());
		System.out.println(blog.getTest1());
		System.out.println(blog.getTest2());
	}

}

Test Results:

6c1bed71d6302dd92b05ea042f664e00
1494119158
7481639510420907711
4
13

Multi-environment configuration


The file name of the multi-environment configuration needs to meet the format of application-{profile}.properties, where the environment identifier corresponding to {profile} is

Configure the property spring.profiles.active in application.properties to choose to load the corresponding configuration file.


spring.profiles.active=dev

application-dev.properties file content:

server.port=8080

The port 8080 used for service startup.


load order

1. Parameters passed in the command line

2. Properties in spring_application_json. spring_application_json is the content configured in the system environment variable in JSON format.

3. java: JNDI properties in comp/env

4. Java system properties, which can be obtained through System.getProperties()

5. Operating system environment variables

6. Random properties configured through random.*

7. The content of configuration files for different ${profile} environments outside the current application jar package, such as application-{profile}.properties or YMAL configuration content.

8. Located in the current application jar package, the content of the configuration file for different ${profile} environments, such as application-{profile}.properties or YMAL configuration content.

9. Applicaiton.properties and YMAL configuration content outside the current jar package

10. The applicaiton.properties and YMAL configuration content located in the current jar package

11. In the class modified by the @Configuration annotation, the properties defined by the @PropertySource annotation.

12. Apply default properties, using what is defined by SpringApplication.setDefaultProperties





Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324407703&siteId=291194637