feign+nacos+gateway调用服务的配置

前言:学习黑马java的黑马头条项目时,用到了gateway网关+nacos注册服务+feign的调用链,但是在实际使用中时遇到了一些问题,尤其是配置网关和feign的时候,一定要配置上 超时时间,否则会因为超时时间过短,导致服务调用的线程还未结束就报错,在此记录一下;

一、spring-Cloud-gateway和nacos相关配置

1.首先,我们在项目中常见gateway的模块,引入依赖包,注意引入nacos的依赖,将gateway服务注册到nacos中;
    <dependencies>
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-alibaba-nacos-discovery</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-gateway</artifactId>
        </dependency>
        <dependency>
            <groupId>io.jsonwebtoken</groupId>
            <artifactId>jjwt</artifactId>
        </dependency>
    </dependencies>
2.配置文件:

重点注意要配置网关的链接超时时间、网关的拦截规则;

server:
  port: 6001
spring:
  application:
    name: leadnews-admin-gateway # nacos注册到nacos上服务的名称
  # 设置项目中nacos注册中心的所在地址
  cloud:
    nacos:
      discovery:
        server-addr: xxx.xxx.xxx.xxx:8848 # nacos所部署服务器的ip
    gateway:
      httpclient:
        connect-timeout: 50000 # 设置连接打开超时时间(ms)
        response-timeout: 100000 # 设置响应超时时间(ms)
      globalcors:
        cors-configurations:
          '[/**]': #匹配所有的请求
            allowedOrigins: "*" #解决跨域问题,允许所有域访问
            allowedMethods:
              - GET
              - POST
              - PUT
              - DELETE
      routes: # 配置网关拦截器的规则
        - id: user #对外部请求的url进行拦截,并处理其中的字段
          uri: lb://leadnews-user
           #截取url中的user部分,
          predicates :
           #注意配置等号两边不能有空格
           - Path=/user/**
           #截取的部分,设定只有第一段,也就是只有将请求url中的/user/ 替换成/leadnews_user/,并且将访问的端口6001转换成配置服务对应的端口
          filters:
          - StripPrefix=1
        - id: author #对外部请求的url进行拦截,并处理其中的字段
          uri: lb://leadnews-article
            #截取url中的admin部分,
          predicates :
            #注意配置等号两边不能有空格
          - Path=/author/**
            #截取的部分,设定只有第一段,也就是只有将请求url中的/auth/ 替换成/leadnews_user/,并且将访问的端口6001转换成配置服务对应的端口
          filters:
          - StripPrefix=1
3.编写springboot启动类
@SpringBootApplication
//此注解为注册到nacos服务的意思
@EnableDiscoveryClient
public class AdminGatewayApplication {
    public static void main(String[] args) {
        SpringApplication.run(AdminGatewayApplication.class,args);
    }
4.编写拦截器
@Component
@Log4j2
public class AuthorizeFilter implements GlobalFilter, Ordered {
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        //1.获取请求对象和相应对象
        ServerHttpRequest request = exchange.getRequest();
        ServerHttpResponse response = exchange.getResponse();
        //2.验证其是否为登录请求,如果是登录请求则直接放行;
        if (request.getURI().getPath().contains("/login/in")){
            return chain.filter(exchange);
        }
        //3.如果不是登录,则获取jwt的数据,如果没有jwt,则返回报错给前台
        HttpHeaders headers = request.getHeaders();
        String token = headers.getFirst("token");
        if (StringUtils.isBlank(token)){
            response.setStatusCode(HttpStatus.UNAUTHORIZED);
            return response.setComplete();
        }
        try {
            //4.解析jwt数据中的参数
            Claims claims = AppJwtUtil.getClaimsBody(token);
            int result = AppJwtUtil.verifyToken(claims);
            if (result == -1|| result == 0){
                //判断token的有效期合法, 则蒋用户id赋值倒request中
                Integer id = (Integer) claims.get("id");
                log.info("获取到当前用户的id为:{},数据来源的url为:{}",id,request.getURI());
                ServerHttpRequest httpRequest = request.mutate().headers(httpHeaders -> {
                    httpHeaders.add("userId", id.toString());
                }).build();
                exchange.mutate().request(httpRequest).build();
            }
        } catch (Exception e){
            e.printStackTrace();
            response.setStatusCode(HttpStatus.UNAUTHORIZED);
            return response.setComplete();
        }
        //放行
        return chain.filter(exchange);
    }

    /**
     * 设置优先级的方法
     * 值越小,优先级越高
     * @return
     */
    @Override
    public int getOrder() {
        return 0;
    }
}

二、springboot 被调用服务的业务模块

1.首先创建模块,引入依赖包
<dependencies>
        <!-- 引入依赖模块 -->
        <!-- Spring boot starter -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <!-- 引入mybatis依赖-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-lang3</artifactId>
        </dependency>
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-alibaba-nacos-discovery</artifactId>
        </dependency>
    </dependencies>
2.配置application.yml
server:
  port: 9003
spring:
  application:
    name: leadnews-article
# 设置项目中nacos注册中心的所在地址
  cloud:
    nacos:
      discovery:
        server-addr: xxx.xxx.xxx.xxx:8848
  datasource:
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://xxx.xxx.xxx.xxx:3306/leadnews_article?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC
    username: ****
    password: ****
# 设置Mapper接口所对应的XML文件位置,如果你在Mapper接口中有自定义方法,需要进行该配置
mybatis-plus:
  mapper-locations: classpath*:mapper/*.xml
  # 设置别名包扫描路径,通过该属性可以给包中的类注册别名
  type-aliases-package: article.pojos
3.编写springboot启动类
@SpringBootApplication
@EnableDiscoveryClient
@MapperScan(value = "com.***.article.mapper")
public class ArticleApplication {
    public static void main(String[] args) {
        SpringApplication.run(ArticleApplication.class, args);
    }
    //引入mybatiesPlus的分页组件
    @Bean
    PaginationInterceptor paginationInterceptor() {
        return new PaginationInterceptor();
    }
}
4.编写业务代码,主要是controller的代码,controller一定要使用restful风格的格式;service和mapper实现就不写了,具体业务自己再去写
@RestController
@RequestMapping("/api/v1/author")
public class ArticleAuthorController implements ArticleAuthorControllerApi {
    @Autowired
    private ArticleAuthorService articleAuthorService;

    @Override
    @GetMapping(value = "/findByUserId/{id}")
    //get请求参数要使用PathVariable注解
    public ApAuthor findByUserId(@PathVariable(value = "id") Integer id) {
        return articleAuthorService.findByUserId(id);
    }

    @PostMapping("/save")
    @Override
    //post请求的参数要使用RequestBody的注解
    public ResponseResult save(@RequestBody ApAuthor apAuthor) {
        articleAuthorService.save(apAuthor);
        return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
    }
}

三、使用Feign的调用服务的模块

1.引入依赖包
 <dependencies>
        <!-- 引入依赖模块 -->
        <!-- Spring boot starter -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <!-- 引入mybatis依赖-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-lang3</artifactId>
        </dependency>
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
            <version>2.1.1.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-alibaba-nacos-discovery</artifactId>
        </dependency>
    </dependencies>
2.配置application.yml的配置
server:
  port: 9002
spring:
  cloud:
    nacos:
      discovery:
        server-addr: xxx.xx.xx.xx:8848
  application:
    name: leadnews-user
  datasource:
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://xxx.xxx.xx.xxx:3306/leadnews_user?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC
    username: ****
    password: ****
# 设置Mapper接口所对应的XML文件位置,如果你在Mapper接口中有自定义方法,需要进行该配置
mybatis-plus:
  mapper-locations: classpath*:mapper/*.xml
  # 设置别名包扫描路径,通过该属性可以给包中的类注册别名
  type-aliases-package: com.***.model.user.pojos
feign:
  client:
    config:
      default:
        # 配置feign的链接超时时间,一定要配置上此项配置
        connectTimeout: 60000
        readTimeout: 60000
3.编辑springboot启动类
@SpringBootApplication
@EnableDiscoveryClient
@MapperScan("com.***.user.mapper")
//启动类中的feign配置
@EnableFeignClients
public class ApUserApplication {
    public static void main(String[] args) {
        SpringApplication.run(ApUserApplication.class,args);
    }
    //添加mybatis-plus分页组件插件
    @Bean
    public PaginationInterceptor paginationInterceptor(){
        return new PaginationInterceptor();
    }
}
4.编写feign的调用类
//注解里的value是被调用服务注册在nacos中的服务名称
@FeignClient("leadnews-article")
public interface ArticleFeign {
    //与被调用服务的rest请求类型保持一致,且要把调用url在注解里写全
    @GetMapping("/api/v1/author/findByUserId/{id}")
    public ApAuthor findByUserId(@PathVariable("id") Integer id);
    //与被调用服务的rest请求类型保持一致,且要把调用url在注解里写全
    @PostMapping("/api/v1/author/save")
    public ResponseResult save(@RequestBody ApAuthor apAuthor);
}
5.在业务service的impl中使用feign调用接口
@Autowired
    private ArticleFeign  articleFeign;
    private void createAuthor(WmUser wmUser) {
        ApAuthor author = articleFeign.findByUserId(wmUser.getApUserId());
        if (author == null){
            author.setUserId(wmUser.getApUserId());
            author.setWmUserId(wmUser.getId());
            author.setType(UserConstants.WEMEDIA_PERSION);
            author.setCreatedTime(new Date());
            articleFeign.save(author);
        }
    }

  • 4
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

夏娜不懒惰

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值