欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

【SpringCloud微服务】第2章 微服务构建 Spring Boot

程序员文章站 2022-05-08 10:57:45
...

2章 微服务构建 Spring Boot


2.1 框架简介

Spring Boot是由Pivotal团队提供的全新框架,其设计目的是用来简化新Spring应用的初始搭建以及开发过程。该框架使用了特定的方式来进行配置,从而使开发人员不再需要定义样板化的配置。其具有如下特点:

快速构建

通过设计大量的自动化配置等方式,来简化Spring原有样板化的配置,使得开发者可以快速构建应用;

自动管理依赖

通过一些列Starter POMs的定义,使得依赖管理工作变得更为简单;

支持运行期内嵌容器

除了很好融入Docker之外,其自身还支持嵌入式的TomcatJetty等容器;

编码简单

可以使用GradleGroovy来开发。

2.2 快速入门

2.2.1 项目构建与解析

1.访问http://start.spring.io/  ,添加web依赖,构建Mavendemo项目。

 【SpringCloud微服务】第2章 微服务构建 Spring Boot

2.导入项目,熟悉目录结构。

<!--注意:Spring Boot 默认的打包方式为jar包,而非war -->

<packaging>jar</packaging>

3.创建com.example.demo.web包,编写测试类HelloController.java

package com.example.demo.web;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
 * 编写一个测试类
 * <p>Title: HelloController</p>  
 * @author  Liyan  
 * @date    2018年3月19日 下午7:00:20
 */
@RestController
public class HelloController {	
	@RequestMapping("/hello")
	public String index() {
		return "Hello Word!";
	}
}

注意:此处有一个小坑,如果你项目运行时报错:Whitelabel Error Page。原因是你的包结构有问题,简单理解:Application.java启动类,要放在Controller包结构的上一层。参见官网文档:

14.2 Locating the main application class

We generally recommend that you locate your main application class in a root package above other classes. The @EnableAutoConfiguration annotation is often placed on your main class, and it implicitly defines a base “search package” for certain items. For example, if you are writing a JPA application, the package of the @EnableAutoConfiguration annotated class will be used to search for @Entity items.

Using a root package also allows the @ComponentScan annotation to be used without needing to specify a basePackage attribute. You can also use the @SpringBootApplication annotation if your main class is in the root package.

Here is a typical layout:

com

 +- example

     +- myproject

         +- Application.java

         |

         +- domain

         |   +- Customer.java

         |   +- CustomerRepository.java

         |

         +- service

         |   +- CustomerService.java

         |

         +- web

             +- CustomerController.java

3.运行DemoApplication.java,访问htpp://localhost:8081/hello

2.2.2 编写单元测试

原著中所讲单元测试示例,受版本限制,已经过时,故本处不再赘述,直接上新代码:

1.修改HelloController.java类(方便单元测试中模拟多场景)

package com.example.demo.web;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
/**
 * 编写一个测试类
 * <p>Title: HelloController</p>  
 * @author  Liyan  
 * @date    2018年3月19日 下午7:00:20
 */
@RestController
public class HelloController {
	
	@RequestMapping("/hello")
	public String index() {
		return "Hello Word!";
	}
	
	@RequestMapping(value = "/user" , method = RequestMethod.GET)
	public String getUser(@RequestParam String username) {
		return "查询用户成功,账号:" + username ;
	}
	
	@RequestMapping(value = "/user" , method = RequestMethod.POST)
	public String insertUser(@RequestParam String username,@RequestParam String password) {
		return "新增用户成功,账号:" + username +";密码:"+ password;
	}
	
}

2.src/test/java中创建HelloControllerTest测试类

package com.example.demo.web;

import java.util.HashMap;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.web.client.TestRestTemplate;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import com.google.common.collect.Maps;
/**
 * Spring Boot的单元测试
 * <p>Title: HelloControllerTest</p>  
 * @author  Liyan  
 * @date    2018年3月19日 下午6:58:03
 * @RunWith(SpringRunner.class) SpringRunner是spring-test提供的测试执行单元类
 * (SpringJUnit4ClassRunner的新名字)
 */

@RunWith(SpringRunner.class) 
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class HelloControllerTest {
	
    /**
     * Spring RestTemplate的便利替代。你可以获取一个普通的或发送基本HTTP认证(使用用户名和密码)的模板
     */
    @Autowired
    private TestRestTemplate testRestTemplate;
    
    /**
     * 注入端口号 
     */
    @Value("${local.server.port}")
    private int port;

	@Test
	public void index() {
		String url = "http://localhost:"+port+"/hello";
		String string = testRestTemplate.getForObject(url, String.class);
		System.out.println(string);
	}
	
	@Test
	public void getUser() {
		String url = "http://localhost:"+port+"/user?username={username}";
		HashMap<String,Object> params = Maps.newHashMap();
		params.put("username", "张三");
		String string = testRestTemplate.getForObject(url, String.class, params);
		System.out.println(string);
	}
	
	@Test
	public void insertUser() {
		String url = "http://localhost:"+port+"/user";
		MultiValueMap<String, Object> params = new LinkedMultiValueMap<>();
		params.add("username", "张三");
		params.add("password", "123");
		String string = testRestTemplate.postForObject(url, params, String.class);
		System.out.println(string);
	}

}

注意:如果粘贴后代码报错,是因为笔者引入了GoogleGuava包,当然你可以将报错的HashMap<String,Object> params = Maps.newHashMap()”替换为“HashMap<String,Object> params = new HashMap<String,Object> ()”,也可以在pom文件中,引入Guava的依赖,当然,笔者更推荐后一种,毕竟Guava包还是很好用的,值得一试。

<!-- 引入google的guava包 -->
<dependency>
	<groupId>com.google.guava</groupId>
	<artifactId>guava</artifactId>
	 <version>19.0</version>
</dependency>

3.逐个运行单元测试即可,不再赘述。

2.3 配置详解

2.3.1 配置文件

①默认位置 src/main/resources/application.properties

②除了支持传统的properties文件外,还广泛支持YAML文件

YAML文件

properties文件

environments:

   dev:

      url: http://dev.bar.com

      name: Developer Setup

   prod:

      url: http://foo.bar.com

      name: My Cool App

environments.dev.url = http://dev.bar.com

environments.dev.name = Developer Setup

environments.prod.url = http://foo.bar.com

environments.prod.name = My Cool App

③注意:YAML目前还有一些不足,它无法通过@PropertySource注解来加载配置,但是YAML将属性加载到内存中保存的时候是有序的,所以当配置文件中信息需要具备顺序含义时,YAML的配置方式比起properties配置文件更有优势。

2.3.2 自定义参数

①在application.properties中添加:book.name = SpringCloudInAction;

②在应用中可以通过@Value注解来加载这些自定义的参数,比如:

@Value(""${book.name}"")

private String name;

③@Value注释加载属性值的时候可以支持两种表达式来进行配置:

一种是PlaceHolder方式,格式为 ${....}

另一种是SpEL表达式,格式为 #{...}

 

2.3.3 参数引用

在application.properties中,各个参数之间可以直接通过使用PlaceHolder的方式进行引用:

book.name=SpringCloud

book.author=ZhaiYongChao

book.desc=${book.author} is writing 《 ${book.name} 》

2.3.4 使用随机数

①格式为 ${random},具体类型:

随机字符串  XXX.value=${random.value}

随机int  XXX.number=${random.int}

随机long  XXX.bignumber=${random.long}

10以内的随机数  XXX.test1=${random.int(10)}

10~20的随机数  XXX.test2=${random.int[10,20]}

②场景:该配置方式可以设置应用端口等场景,以免在本地调试时出现端口冲突的麻烦。

2.3.5 命令行参数

①格式为连续两个减号--就是对application.properties中的属性进行赋值的标识:

java -jar xxx.jar--service.port=8888 命令

等价于

在application.properties中添加属性service.port=8888

2.4 多环境配置

1.格式要求

①文件名要满足application-{profile}.properties的格式,其中{profile}为对应的环境标识

②在application.properties文件中通过spring.profiles.active={profile}设置生效

2.简单测试

①在src/main/resources目录下创建2个文件,名字分别为:

   aapplication-test.properties  [内容为:server.port=8081]

   bapplication-online.properties [内容为:server.port=8082]

②在application.properties中先配置spring.profiles.active = test

③启动后发现端口为8081,再修改spring.profiles.active = online,启动后端口为8082

2.5 加载顺序

Spring Boot的属性加载顺序,由优先级高到优先级低:

①在命令行中传入的参数;

SPRING_APPLICATION_JSON中的属性,SPRING_APPLICATION_JSON是以JSON格式配置

  在系统环境变量中的内容;

java:comp/env中的JNDI属性;

Java的系统属性,可以通过System.getProperties()获得的内容;

⑤操作系统的环境变量;

⑥通过random.*配置的随机属性;

⑦位于当前应用Jar包之外,针对不同{profile}环境的配置文件内容,例如

  application-{profile}.properties或者yaml定义的配置文件;

⑧位于当前应用Jar包之内,针对不同{profile}环境的配置文件内容,例如

  application-{profile}.properties或是yaml定义的配置文件;

⑨位于当前应用Jar包之外的application.propertiesyaml配置内容;

⑩位于当前应用Jar包之内的application.propertiesyaml配置内容;

⑪在@Configuration注解修改类中,通过@PropertySource注解定义的属性;

⑫应用默认属性,使用SpringApplication.setDefaultProperties定义的内容。

2.6 监控与管理

2.6.1 简介

①依赖于Starter POMs 中提供了一个特殊模块 spring-boot-starter-actuator

②该模块能自动为Spring Boot构建的应用提供一系列用于监控的端点(该模板本身做了不少扩展,同时根据不同组件,还提供了更多空端点)

2.6.2 初识 actuator

1.引入maven依赖

<dependency>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-starter-actuator</artifactId>

</dependency>

2.启动后发现多了很多mapper映射

 【SpringCloud微服务】第2章 微服务构建 Spring Boot

3.访问localhost:8081/actuator/health看一下效果,有个初步印象

2.6.3 原生端点

根据作用,分为三类(具体作用,后面会补充):

①应用配置类:获取应用程序中加载的应用配置、环境变量、自动化配置报告等与SpringBoot应用密切相关的配置类信息;

②度量指标类:获取应用程序运行过程中用于监控的度量指标,比如内存信息、线程池信息、HTTP请求统计等;

③操作控制类:提供了对应用的关闭等操作类功能。