<dependency>
<groupId>com.alibaba.cloudgroupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discoveryartifactId>
dependency>
#spring
cloud:
nacos:
discovery:
server-addr: localhost:8848 # nacos服务地址
@EnableDiscoveryClient
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-openfeignartifactId>
dependency>
@Api(tags = "会员接口")
@RestController
@RequestMapping("/api/core/userInfo")
@Slf4j
@CrossOrigin
public class UserInfoController {
/**
* @param mobile:
* @return R
* @author Likejin
* @description 短信服务远程调用,在发短信前检测号码是否被注册
* @date 2023/4/14 9:33
*/
@ApiOperation("校验手机号是否注册")
@GetMapping("/checkMobile/{mobile}")
public Boolean checkMobile(@PathVariable String mobile){
boolean result = userInfoService.checkMobile(mobile);
return result;
}
}
/**
*
* 用户基本信息 服务类
*
*
* @author Likejin
* @since 2023-04-09
*/
public interface UserInfoService extends IService<UserInfo> {
boolean checkMobile(String mobile);
}
/**
*
* 用户基本信息 服务实现类
*
*
* @author Likejin
* @since 2023-04-09
*/
@Service
public class UserInfoServiceImpl extends ServiceImpl<UserInfoMapper, UserInfo> implements UserInfoService {
/**
* @param mobile:
* @return boolean
* @author Likejin
* @description 校验手机号是否存在
* @date 2023/4/14 9:38
*/
@Override
public boolean checkMobile(String mobile) {
QueryWrapper<UserInfo> userInfoQueryWrapper = new QueryWrapper<>();
userInfoQueryWrapper.eq("mobile",mobile);
Integer count = baseMapper.selectCount(userInfoQueryWrapper);
return count>0;
}
}
@SpringBootApplication
//项目直接的互相调用,可以直接扫描到(不要写到具体包下,写到项目下即可)
@ComponentScan({"com.atguigu.srb","com.atguigu.common"})
@EnableDiscoveryClient
@EnableFeignClients
public class ServiceSmsApplication {
public static void main(String[] args) {
SpringApplication.run(ServiceSmsApplication.class, args);
}
}
package com.atguigu.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/checkMobile/{mobile}")
//远程调用,此处必须加上@PathVariable("mobile") 否则运行不成功
Boolean checkMobile(@PathVariable("mobile") String mobile);
}
package com.atguigu.srb.sms.controller.api;
import com.atguigu.common.exception.Assert;
import com.atguigu.common.result.R;
import com.atguigu.common.result.ResponseEnum;
import com.atguigu.common.util.RandomUtils;
import com.atguigu.common.util.RegexValidateUtils;
import com.atguigu.srb.sms.client.CoreUserInfoClient;
import com.atguigu.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.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;
@RestController
@RequestMapping("/api/sms")
@Api(tags = "短信管理")
@CrossOrigin //跨域
@Slf4j
public class ApiSmsController {
@Resource
private SmsService smsService;
@Resource
private CoreUserInfoClient coreUserInfoClient;
@Resource
private RedisTemplate redisTemplate;
@ApiOperation("获取验证码")
@GetMapping("/send/{mobile}")
public R send(
@ApiParam(value = "手机号", required = true)
@PathVariable String mobile){
//MOBILE_NULL_ERROR(-202, "手机号不能为空"),
Assert.notEmpty(mobile, ResponseEnum.MOBILE_NULL_ERROR);
//MOBILE_ERROR(-203, "手机号不正确"),
Assert.isTrue(RegexValidateUtils.checkCellphone(mobile), ResponseEnum.MOBILE_ERROR);
//判断手机号是否已经注册(要操作service-core中的微服务)
Boolean result = coreUserInfoClient.checkMobile(mobile);
Assert.isTrue(result==false,ResponseEnum.MOBILE_EXIST_ERROR);
//希望能够看到远程调用的日志
log.info("result",result);
//生成验证码
String code = RandomUtils.getFourBitRandom();
//组装短信模板参数
Map<String,Object> param = new HashMap<>();
param.put("code", code);
//发送短信
//测试过程中停掉具体发送短信,只需要在redis中获得验证码即可
//smsService.send(mobile, SmsProperties.TEMPLATE_CODE, param);
//将验证码存入redis
redisTemplate.opsForValue().set("srb:sms:code:" + mobile, code, 5, TimeUnit.MINUTES);
return R.ok().message("短信发送成功");
}
}
feign:
client:
config:
default:
connectTimeout: 10000 #连接超时配置
readTimeout: 600000 #执行超时配置
package com.atguigu.srb.base.config;
import feign.Logger;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class OpenFeignConfig {
//指定最高级别的日志配置
@Bean
Logger.Level feignLoggerLevel(){
return Logger.Level.FULL;
}
}
logging:
level:
com.atguigu.srb.sms.client.CoreUserInfoClient: DEBUG #以什么级别监控哪个接口
<springProfile name="dev,test">
<logger name="com.atguigu" level="DEBUG">
<appender-ref ref="CONSOLE" />
<appender-ref ref="ROLLING_FILE" />
logger>
springProfile>
<dependency>
<groupId>com.alibaba.cloudgroupId>
<artifactId>spring-cloud-starter-alibaba-sentinelartifactId>
dependency>
#feign:
sentinel:
enabled: true
package com.atguigu.srb.sms.client;
import com.atguigu.srb.sms.client.fallback.CoreUserInfoClientFallback;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
//熔断功能没有使用
@FeignClient(value ="service-core",fallback = CoreUserInfoClientFallback.class)
public interface CoreUserInfoClient {
@GetMapping("/api/core/userInfo/checkMobile/{mobile}")
//远程调用,此处必须加上@PathVariable("mobile") 否则运行不成功
Boolean checkMobile(@PathVariable("mobile") String mobile);
}
package com.atguigu.srb.sms.client.fallback;
import com.atguigu.srb.sms.client.CoreUserInfoClient;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
@Service
@Slf4j
public class CoreUserInfoClientFallback implements CoreUserInfoClient {
@Override
public Boolean checkMobile(String mobile) {
log.error("远程调用失败,服务熔断");
return false;//手机号不重复
}
}
<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">
<parent>
<artifactId>srbartifactId>
<groupId>com.atguigugroupId>
<version>1.0-SNAPSHOTversion>
parent>
<modelVersion>4.0.0modelVersion>
<artifactId>service-gatewayartifactId>
<dependencies>
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-gatewayartifactId>
dependency>
<dependency>
<groupId>com.alibaba.cloudgroupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discoveryartifactId>
dependency>
dependencies>
project>
server:
port: 80 # 服务端口
spring:
profiles:
active: dev # 环境设置
application:
name: service-gateway # 服务名
cloud:
nacos:
discovery:
server-addr: localhost:8848 # nacos服务地址
gateway:
discovery:
locator:
enabled: true # gateway可以发现nacos中的微服务,并自动生成转发路由
routes:
- id: service-core #自动找service-core微服务
uri: lb://service-core #路由到service-core
predicates:
- Path=/*/core/** #如果地址第二个为core
- id: service-sms
uri: lb://service-sms
predicates:
- Path=/*/sms/**
- id: service-oss
uri: lb://service-oss
predicates:
- Path=/*/oss/**
package com.atguigu.srb.gateway;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
@EnableDiscoveryClient
@SpringBootApplication
public class ServiceGatewayApplication {
public static void main(String[] args) {
SpringApplication.run(ServiceGatewayApplication.class, args);
}
}
package com.atguigu.srb.gateway.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.reactive.CorsWebFilter;
import org.springframework.web.cors.reactive.UrlBasedCorsConfigurationSource;
@Configuration
public class CorsConfig {
//配置跨域请求,然后设置策略来是否允许跨域
@Bean
public CorsWebFilter corsFilter() {
CorsConfiguration config = new CorsConfiguration();
config.setAllowCredentials(true); //是否允许携带cookie,允许cookie跨域
config.addAllowedOrigin("*"); //可接受的域,是一个具体域名或者*(代表任意域名)
config.addAllowedHeader("*"); //允许携带的头
config.addAllowedMethod("*"); //允许访问的方式
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", config); //注册配置项config,针对所有url地址都用config的策略
return new CorsWebFilter(source);
}
}