㈠ 微服务SpringCloudAlibaba配置汇总
在 pom.xml 中添加 spring-cloud-alibaba-dependencies 统一管理版本:
Nacos 致力于帮助您发现、配置和管理微服务。Nacos 提供了一组简单易用的特性集,帮助您快速实现动态服务发现、服务配置、服务元数据及流量管理。
通过 @EnableDiscoveryClient 注解表明是一个 Nacos 客户端,该注解是 Spring Cloud 提供的原生注解
注:server-addr为Nacos Server 网址
Sentinel 以流量为切入点,从流量控制、熔断降级、系统负载保护等多个维度保护服务的稳定性。
Sentinel 以流量为切入点,从流量控制、熔断降级、系统负载保护等多个维度保护服务的稳定性。
使用 Spring Cloud Alibaba Nacos Config,您可以在 Nacos Server 集中管理你 Spring Cloud 应用的外部属性配置。
注意:Spring Boot 配置文件的加载顺序,依次为 bootstrap.properties -> bootstrap.yml -> application.properties -> application.yml ,其中 bootstrap.properties 配置为最高优先级
RocketMQ 是一款开源的分布式消息系统,基于高可用分布式集群技术,提供低延时的、高可靠的消息发布与订阅服务。
配置 Output(Source.class) 的 Binding 信息并配合 @EnableBinding 注解使其生效
运行成功后即可在 RocketMQ 控制台的 消息 列表中选择 test-topic 主题即可看到发送的消息
配置 Input(Sink.class) 的 Binding 信息并配合 @EnableBinding 注解使其生效
RPC框架分为提供方和消费方,提供方提供服务,消费方消费服务。这里采用nacos注册中心和Dubbo框架配置。
㈡ Spring Boot如何整合Redis
Spring Boot是目前非常流行的java Web开发框架,Redis是非关系型数据库的一种,以键值对的形式存储。Spring对Redis的支持是通过Spring Data Redis来实现的,给我们提供了RedisTemplate和StringRedisTemplate两种模板来操作数据。Spring Boot框架也提供了对Redis的支持,下面我们来讲一下Spring Boot框架整合Redis的步骤。
IntelliJ IDEA
Spring Boot整合Redis我们需要添加依赖的jar包,spring-boot-starter-data-redis中包含spring和redis相关的jar包,jedis作为redis的客户端也需要添加到工程中,Spring Boot的版本信息在父pom中已指定,子模块中的spring相关的jar包无需另外指定。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>3.0.0-m1</version>
</dependency>
Spring Boot会根据application.properties中的配置对Redis的属性进行自动配置,并注入到RedisProperties类中。在application.properties配置文件中这些属性都是以spring.redis为前缀的,值得注意的是在Spring Boot 1.5.x版本中默认的Redis客户端是jedis,因此在配置文件中无需指定,如下图所示。
Spring Boot 1.5.x版本的整合配置网上可以搜索大量的文章,然而Spring Boot 2.x版本的整合资料却非常少,甚至提供的配置不能正常使用,因此本文主要讲解Spring Boot 2.x整合Redis以及Redis的使用情况。spring-boot 2.x版本有jedis和lettuce两种客户端,因此我们必须要去指定使用哪一种客户端,两个客户端的配置如下图所示,本文使用的是Jedis客户端连接池,具体的配置如下。
# Redis数据库索引(默认为0)
spring.redis.database=0
# Redis服务器地址
spring.redis.host=127.0.0.1
# Redis服务器连接端口
spring.redis.port=6379
# Redis服务器连接密码(默认为空)
spring.redis.password=xylx1.t!@#
# 配置jedis连接池
# 连接池最大连接数(使用负值表示没有限制)
spring.redis.jedis.pool.max-active=8
# 连接池最大阻塞等待时间(使用负值表示没有限制)
spring.redis.jedis.pool.max-wait=-1ms
# 连接池中的最大空闲连接
spring.redis.jedis.pool.max-idle=8
# 连接池中的最小空闲连接
spring.redis.jedis.pool.min-idle=0
# 连接超时时间(毫秒)
spring.redis.timeout=5000ms
由配置我们可以看到spring-boot 2.x版本时间设置需要加单位ms,因为参数的类型为Duration。另外spring.redis.timeout尽量不要配置0,否则可能会出现io.lettuce.core.RedisCommandTimeoutException: Command timed out超时错误。
配置文件编辑完成后,我们开始编写代码实现Redis数据的存储和读取。我们创建一个RedisUtil工具类,该类使用@Component注解表示交由Spring管理,StringRedisTemplate是Spring提供的,可以使用@Autowired注解直接注入,接下来便可以书写存和取的代码了。
@Component
public class RedisUtil {
@Autowired
private StringRedisTemplate redisTemplate;
/**
* 存字符串
* @param key 缓存键
* @param value 缓存值
* @param expireTime 过期时间(s)
*/
public void setString(String key, String value, int expireTime){
ValueOperations<String, String> ops = redisTemplate.opsForValue();
if (expireTime != 0) {
ops.set(key, value, expireTime, TimeUnit.SECONDS);
} else {
ops.set(key,value);
}
}
/**
* 取字符串
* @param key 缓存键
* @return 缓存值
*/
public String getString(String key){
ValueOperations<String, String> ops = this.redisTemplate.opsForValue();
return ops.get(key);
}
接下来我们编写Controller层代码去调用RedisUtil工具类,实现数据的存储和读取,代码比较简单可以参考下图。若想验证Redis是否可用,还需要编写启动类,如下图所示。
由上图可看到我们编写了一个post请求用于存储字符串,get请求用于取出字符串。启动类通过main方法启动应用,接下来我们使用postman去模拟浏览器调用post和get请求,由下图可以看到Redis存储的数据成功被取出。
接下来我们介绍Jedis,这是一个封装了Redis的客户端,在Spring Boot整合Redis的基础上,可以提供更简单的API操作。因此我们需要配置JedisPool的Bean,代码如下,其中@Configuration注解表明这是一个配置类,我们在该类中注入RedisProperties,并且使用@Bean注解指定JedisPool。
@Configuration
public class RedisConfiguration {
@Autowired
private RedisProperties properties;
@Bean
public JedisPool getJedisPool(){
JedisPoolConfig config = new JedisPoolConfig();
config.setMaxIdle(properties.getJedis().getPool().getMaxIdle());
config.setMaxTotal(properties.getJedis().getPool().getMaxActive());
config.setMaxWaitMillis(properties.getJedis().getPool().getMaxWait().toMillis());
JedisPool pool = new JedisPool(config,properties.getHost(),
properties.getPort(),100,
properties.getPassword(), properties.getDatabase());
return pool;
}
}
接下来我们编辑JedisUtil工具类,通过SpringBoot容器的@Component注解来自动创建,并且注入JedisPool,使用jedisPool.getResource()方法来获取Jedis,并最终实现操作redis数据库,其代码如下。
@Component
public class JedisUtil {
@Autowired
JedisPool jedisPool;
//获取key的value值
public String get(String key) {
Jedis jedis = jedisPool.getResource();
String str = "";
try {
str = jedis.get(key);
} finally {
try {
jedis.close();
} catch (Exception e) {
e.printStackTrace();
}
}
return str;
}
public String set(String key, String value) {
Jedis jedis = jedisPool.getResource();
String str = "";
try {
str = jedis.set(key, value);
} finally {
try {
jedis.close();
} catch (Exception e) {
e.printStackTrace();
}
}
return str;
}
}
JedisUtil工具类编写完成后,我们修改之前的RedisController,并注入JedisUtil,代码如下图所示。然后再用postman分别调用post和get接口,我们可以看到成功取到了新的key的value值。
在Spring Boot整合Redis前本机需安装Redis,另外可以使用RedisDesktopManager这个Redis这个桌面管理工具查看Redis中的数据。
㈢ 6、CXF与spring的整合(WebService的整合)
web.xml
说明: 这里主要配置了 spring 的配置文件地址, spring 监听器、 CXF 核心控制器。
applicationContext.xml
说明:
在 spring 的配置文件中使用 jaxws:endpoint 元素来暴露 WebService ,这里有两种方式:
然后我们就可以将工程部署到 tomcat 中,在浏览器中使用
地址 http://localhost:8080/cxf_spring/myService 访问我们的 WebService 工程。
MyClient.java
注意: myService 指定我们的服务名字(在 web.xml 中配置),而 fkjava 指定服务提供者的地址(在 applicationContext.xml 中配置)。同时这种集成不好,因为将地址写死了,没有使用 spring 的注入方式。
我们看 HelloWorldWs.java 这个服务类:
可以看到其中的实际业务处理类还是使用的手工方法进行实例化,没有使用 spring 的注入方式。
在 spring 的配置文件中改变暴露 WebService 的方式:
说明: 加 # 号是为了让服务器知道这个名字不是一个类 ,而只是一个 id 。
然后改造 HelloWorldWs.java 服务类:
然后我们再次使用之前的地址进行访问,发现效果还是一样的。
在上面配置的基础上进行添加,在 applicationContext.xml 中:
此时,和以前一样我们需要在客户端(工程 Call_CXFSpring )那边加上拦截器,添加上用户名和密码的头,然后对服务器进行访问。以此来进行验证。客户端中我们运行类:
MyClient.java
访问服务端。
传统的 SSH 项目中,一般在本地是有相关的数据的,但是有一种场景是我们需要调用别人的数据,但是别人的数据不可能让我们进行修改等操作,那么别人只会暴露一个 WebService ,而我们就需要去调用别人的 WebService 服务器。我们在访问别人时,只能得到 WSDL 文档。此时我们的项目中就不需要业务逻辑组件了,直接去调用别人的 WebService 的一个代理即可。
首先我们拷贝上面的工程,改名为 cxf_springClient ,然后需要增加 struts2 的相关 jar 包:
将原有的一些包删掉,留下权限包 org.fkjava.cxf.ws.auth 。然后我们启动工程 Auth_Server 提供远程服务。在 web 工程中生成相应的包及程序。
web.xml
说明: 这里我们不再需要 CXF 的 servlet 了,因为不需要业务类了,我们直接调用远程业务即可。同时配置 struts2 的核心控制器。
applicationContext.xml
说明: 这里我们同样不需要业务类了,但是需要配置远程业务代理类( serviceClass )。同时注意:不要将端口设置为8080,会冲突。可以看到我们使用 serviceClass 将接口配置进去,而这里的 id 不能随便写,要和 action 中定义的接口名一致。由于远程服务器设置了权限拦截,所以这里使用过滤器将用户名和密码设置到 wsdl 文档的头中。然后在这个类中我们需要使用 execute 方法去获取相应的数据。
struts.xml
ListCatsAction .java
说明: 此时我们就可以使用地址 http://localhost:8080/cxf_springClient/listCats 进行访问了,当然会报找不到 jsp 的错误。
content/listCats.jsp
说明: 此时访问就可以看到
㈣ 浜屻乻pringboot閰嶇疆鏂囦欢
鍦ㄩ」鐩鐩褰曚笅鍒涘缓涓涓猚onfig鐨勬枃浠跺す锛屽苟鍦ㄤ腑鍒涘缓application.yaml閰嶇疆鏂囦欢锛岀洿鎺ュ湪椤圭洰鐩褰曚笅鍒涘缓application.yaml鏂囦欢銆傚湪resources鐩褰曚笅鍒涘缓config鏂囦欢澶癸紝骞跺垱寤洪厤缃鏂囦欢銆
SpringBoot瀹樻柟鎻愪緵浜嗕袱绉嶅父鐢ㄧ殑閰嶇疆鏂囦欢鏍煎紡锛屽垎鍒鏄痯roperties銆乊ML鏍煎紡銆傜浉姣斾簬properties鏉ヨ达紝YML鏇村姞骞磋交锛屽眰绾т篃鏄鏇村姞鍒嗘槑銆
棣栧厛锛屽湪SpringBoot涓锛屾湁涓ょ嶉厤缃鏂囦欢鐨勬柟寮忋備竴绉嶆槸application.properties锛屽彟涓绉峚pplication.yaml(鎴栬呮槸application.yml)銆
渚濊禆绠$悊锛歋pringBoot鏀鎸佽嚜鍔ㄩ厤缃鍜屼緷璧栫$悊锛岄渶瑕佹敞鎰忓煎叆鐨勪緷璧栨槸鍚︽g‘锛屼互閬垮厤鍑虹幇鍐茬獊鎴栫増鏈涓嶅吋瀹圭瓑闂棰樸
榛樿ょ殑閰嶇疆鏂囦欢鏄痑pplication.properties銆
㈤ springboot配置文件总结
springboot 本身支持多种灵活的配置方式,为开发 springboot 程序带来了很大的灵活性和扩展性,但是同时由于太灵活,经常会导致明明配置了相关属性,却没有生效。
本文总结了 springboot 配置文件的原理以及多个配置文件生效的顺序。
springboot 配置文件支持灵活的路径,以及灵活的文件名,用一个变量表达式总结如下:
部分源码如下:
当满足上述变量表达式的配置文件有多个时,会有一个配置的优先级。假设
上面每个条件组合起来,则最多有配置文件如下,且顺序从上到下:
获取属性时,按从上到下的顺序遍历由上述文件生成的属性资源对象 PropertySource ,如果遇到匹配的key直接返回。
总结一下:就是如果同一个key的属性只出现一次,则直接取该值即可。如果同一个key的属性出现多次,则取顺序靠前的属性资源对象。另外其中每个文件都是可选的。
需要注意的一点是:如果在同一个 location 下配置了多个文件名一样的文件,则只会取一个,比如在 classpath:/ ,有如下两个文件 application.yml :
则只会根据 classloader 的 classpath 列表,选取第一个出现的文件。因为 springboot 加载配置文件时最底层是使用的下面的方法:
这两个方法只会获取 classloader 类的 ucp 属性里面第一个匹配到的值。如果对 springboot 自身的机制不满意,想获取所有的classpath:/路径下面的 applicaiton.yml 文件,可以使用下面的方法:
本文总结了 springboot 配置文件的原理以及多个配置文件生效的顺序。如果存在增加了配置文件或者在配置文件里面增加了属性却没有生效,可以参考上面的 springboot 配置文件表达式和配置文件生效顺序进行排查。
后面还会有一篇文章讨论基于 springboot 配置原理如何实现自定义的配置读取方式。