nacos 服务发现
- 下载 略
- 启动略
微服务端配置
依赖倒入
- 未提供版本,根据自身项目去选用,或者交给spring自动进行版本仲裁
```java
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<a name="rJEtC"></a>
## 配置
- 首先在要注册到服务发现,也就是nacos中的微服务下进行配置
```java
server:
port: 8120
spring:
application:
name: service-sms # 服务名 注册到nacos 中会作为该微服务模块标示
cloud:
nacos:
discovery:
server-addr: localhost:8848 # nacos 服务地址
logging:
level:
com.addicated.srb.sms.client.CoreUserInfoClient: DEBUG #以什么级别监控哪个接口
注解添加
package com.addicated.srb.core;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.context.annotation.ComponentScan;
@SpringBootApplication
@EnableDiscoveryClient
@ComponentScan({"com.addicated.srb","com.addicated.common"})
public class ServiceCoreApplication {
public static void main(String[] args) {
SpringApplication.run(ServiceCoreApplication.class,args);
}
}
检查结果
OpenFeign使用场景
当微服务之间需要进行调用的时候进行使用,需要配合服务发现来进行使用,否则微服务之间无法发现彼此。
openFegin简单使用
需求背景:
- 用户注册,需要走验证码服务,
- 原始逻辑为点击下一步的时候才进行 查库请求,例如查询该用户是否已经注册。这样对用户体验不够友好,同时会造成验证码发送的使用浪费,要知道,这些都是钱
架构介绍
- sms 为 发送验证码的单独模块
- core 为 核心逻辑模块
综上所述,设想逻辑为,在sms模块得到前端点击发送验证码的请求之后,直接请求 core 模块的服务,去查库进行校验, 如果已存在,则不去发送验证码,否则再进行发送。
简单开发
导入依赖 ```java
<!--服务调用--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</artifactId> </dependency>
- 被调用目标接口开发
```java
@ApiOperation("校验账号是否已经被注册")
@GetMapping("/checkEmail/{email}")
public boolean checkEmail(@PathVariable("email") String email){
return userInfoService.checkMail(email);
}
- sms 模块下,即调用发起者
- 启动类上添加 enableFeignClients注解 标示启用openfeign调用 ```java package com.addicated.srb.sms;
import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.openfeign.EnableFeignClients; import org.springframework.context.annotation.ComponentScan;
@SpringBootApplication @EnableFeignClients @ComponentScan({“com.addicated.srb”, “com.addicated.common”}) public class ServiceSmsApplication {
public static void main(String[] args) {
SpringApplication.run(ServiceSmsApplication.class, args);
}
}
- 在 sms 模块下 创建接口类
```java
package com.addicated.srb.sms.client;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
@FeignClient(value="service-core") // 声明要调用哪个模块下的功能
public interface CoreUserInfoClient {
@GetMapping("/api/core/userInfo/checkEmail/{email}") // 声明要调用哪个接口路径 仅声明即可
boolean checkEmail(@PathVariable String email);
}
- 在 sms controller 层进行注入调用 ```java package com.addicated.srb.sms.controller.api;
import com.addicated.common.exception.Assert; import com.addicated.common.result.R; import com.addicated.common.result.ResponseEnum; import com.addicated.common.util.RandomUtils; import com.addicated.common.util.RegexValidateUtils; import com.addicated.srb.sms.client.CoreUserInfoClient; import com.addicated.srb.sms.service.SmsService; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiParam; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.web.bind.annotation.*;
import java.util.HashMap; import java.util.Map; import java.util.concurrent.TimeUnit;
@RestController @RequestMapping(“/api/sms”) @Api(tags = “短信管理”) @CrossOrigin //跨域 @Slf4j public class ApiSmsController {
@Autowired
private SmsService smsService;
@Autowired
private RedisTemplate redisTemplate;
@Autowired
private CoreUserInfoClient coreUserInfoClient;
@Value("${mail.subject}")
private String SUBJECT;
@Value("${mail.content}")
private String CONTENT;
@ApiOperation("获取验证码,发送到填写邮箱")
@GetMapping("/send/{email}")
public R send(
@ApiParam(value = "邮箱地址", required = true)
@PathVariable(value="email") String email) {
// 使用断言来进行异常处理
Assert.notEmpty(email, ResponseEnum.MAIL_NULL_ERROR);
// 邮箱格式校验
Assert.isTrue(RegexValidateUtils.checkEmail(email),ResponseEnum.MAIL_ERROR);
// FIXME 在发送之前对 账号是否已经注册进行判断 | 判断逻辑在另外一个core 微服务下, 需要跨微服务进行调用,引出openFeign
// 对应的要在core 微服务下进行 接口定义
boolean result = coreUserInfoClient.checkEmail(email);
System.out.println("result = " + result);
// 断言 如果为fasle 则抛出异常
Assert.isTrue(result == false, ResponseEnum.MAIL_EXIST_ERROR);
// 调用工具类生成验证码
String code = RandomUtils.getFourBitRandom();
// 进行短信模板组装
Map<String,Object> param = new HashMap<>();
param.put("code", code);
// 发送验证码到目标邮箱
smsService.sendMail(email,SUBJECT,String.format(CONTENT,code));
// 验证码押入 redis
redisTemplate.opsForValue().set("srb:sms:code:" + email, code, 5, TimeUnit.MINUTES);
return R.ok().message("短信发送成功");
}
}
查看结果
- 前端页面未修改,提示信息不用在意。
- 已经注册,被拦截到了,同样邮箱也未收到验证码,调用成功,功能实现。