ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

80-day03-网关校验,代码生成器的【使用】,app端用户实名认证(业务),feign的抽取

2022-04-25 01:03:32  阅读:217  来源: 互联网

标签:代码生成 网关 day03 server import leadnews com public itheima


第三章 app端用户认证

目标

  • 能够完成网关统一鉴权的功能

  • 能够完成认证用户列表查询

  • 能够熟悉app端用户认证审核流程

  • 能够完成app用户审核代码开发

1 网关校验jwt

1.1 微服务网关概述

不同的微服务一般会有不同的网络地址,而外部客户端可能需要调用多个服务的接口才能完成一个业务需求,如果让客户端直接与各个微服务通信,会有以下的问题:

  • 客户端会多次请求不同的微服务,增加了客户端的复杂性
  • 存在跨域请求,在一定场景下处理相对复杂
  • 认证复杂,每个服务都需要独立认证
  • 难以重构,随着项目的迭代,可能需要重新划分微服务。例如,可能将多个服务合并成一个或者将一个服务拆分成多个。如果客户端直接与微服务通信,那么重构将会很难实施
  • 某些微服务可能使用了防火墙 / 浏览器不友好的协议,直接访问会有一定的困难

以上这些问题可以借助网关解决。

网关是介于客户端和服务器端之间的中间层,所有的外部请求都会先经过 网关这一层。也就是说,API 的实现方面更多的考虑业务逻辑,而安全、性能、监控可以交由 网关来做,这样既提高业务灵活性又不缺安全性,典型的架构图如图所示:

1585846768368

优点如下:

  • 安全 ,只有网关系统对外进行暴露,微服务可以隐藏在内网,通过防火墙保护。
  • 易于监控。可以在网关收集监控数据并将其推送到外部系统进行分析。
  • 易于认证。可以在网关上进行认证,然后再将请求转发到后端的微服务,而无须在每个微服务中进行认证。
  • 减少了客户端与各个微服务之间的交互次数
  • 易于统一授权。

总结:微服务网关就是一个系统,通过暴露该微服务网关系统,方便我们进行相关的鉴权,安全控制,日志统一处理,易于监控的相关功能。

实现微服务网关的技术有很多,

  • nginx Nginx (engine x) 是一个高性能的HTTP反向代理web服务器,同时也提供了IMAP/POP3/SMTP服务
  • zuul ,Zuul 是 Netflix 出品的一个基于 JVM 路由和服务端的负载均衡器。
  • spring-cloud-gateway, 是spring 出品的 基于spring 的网关项目,集成断路器,路径重写,性能比Zuul好。

我们使用gateway这个网关技术,无缝衔接到基于spring cloud的微服务开发中来。

gateway官网:

https://spring.io/projects/spring-cloud-gateway

1.2 搭建gatway网关微服务

(1)创建itheima-leadnews-gateway-admin微服务

<?xml version="1.0" encoding="UTF-8"?>
<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>itheima-leadnews-gateway</artifactId>
        <groupId>com.itheima</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>itheima-leadnews-gateway-admin</artifactId>

    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-gateway</artifactId>
        </dependency>
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>
         <dependency>
            <groupId>com.itheima</groupId>
            <artifactId>itheima-leadnews-common</artifactId>
            <version>1.0-SNAPSHOT</version>
            <exclusions>
                <exclusion>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-starter-web</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
    </dependencies>
</project>

1614046040247

启动类:

package com.itheima;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;

/**
 * @author ljh
 * @version 1.0
 * @date 2021/2/23 10:21
 * @description 标题
 * @package com.itheima
 */
@SpringBootApplication
@EnableDiscoveryClient
public class GatewayAdminApplication {
    public static void main(String[] args) {
        SpringApplication.run(GatewayAdminApplication.class,args);
    }
}

application.yml

spring:
  profiles:
    active: dev
---
server:
  port: 6001
spring:
  application:
    name: leadnews-admin-gateway
  profiles: dev
  cloud:
    nacos:
      server-addr: 192.168.211.136:8848
      discovery:
        server-addr: ${spring.cloud.nacos.server-addr}
    gateway:
      globalcors:
        cors-configurations:
          '[/**]': # 匹配所有请求
            allowedOrigins: "*" #跨域处理 允许所有的域
            allowedHeaders: "*"
            allowedMethods: # 支持的方法
              - GET
              - POST
              - PUT
              - DELETE
      routes:
        # 平台管理
        - id: admin
          uri: lb://leadnews-admin
          predicates:
            - Path=/admin/**
          filters:
            - StripPrefix= 1
---
server:
  port: 6001
spring:
  application:
    name: leadnews-admin-gateway
  profiles: test
  cloud:
    nacos:
      server-addr: 192.168.211.136:8848
      discovery:
        server-addr: ${spring.cloud.nacos.server-addr}
    gateway:
      globalcors:
        cors-configurations:
          '[/**]': # 匹配所有请求
            allowedOrigins: "*" #跨域处理 允许所有的域
            allowedHeaders: "*"
            allowedMethods: # 支持的方法
              - GET
              - POST
              - PUT
              - DELETE
      routes:
        # 平台管理
        - id: admin
          uri: lb://leadnews-admin
          predicates:
            - Path=/admin/**
          filters:
            - StripPrefix= 1
---
server:
  port: 6001
spring:
  application:
    name: leadnews-admin-gateway
  profiles: pro
  cloud:
    nacos:
      server-addr: 192.168.211.136:8848
      discovery:
        server-addr: ${spring.cloud.nacos.server-addr}
    gateway:
      globalcors:
        cors-configurations:
          '[/**]': # 匹配所有请求
            allowedOrigins: "*" #跨域处理 允许所有的域
            allowedHeaders: "*"
            allowedMethods: # 支持的方法
              - GET
              - POST
              - PUT
              - DELETE
      routes:
        # 平台管理
        - id: admin
          uri: lb://leadnews-admin
          predicates:
            - Path=/admin/**
          filters:
            - StripPrefix= 1

重点解释:

- Path=/admin/**  表示以/admin开头的路径全部路由到admin微服务中
例如:http://localhost:6001/admin/xxx/yyy --->路由到http://9001/xxx/yyy

1.3 全局过滤器实现jwt校验

有了网关之后,我们应当从网关开始访问,并通过网关实现权限校验等功能,结构图和流程图如下

1614048743302

思路分析:

  1. 用户进入网关开始登陆,网关过滤器进行判断,如果是登录,则路由到后台管理微服务进行登录
  2. 用户登录成功,后台管理微服务签发JWT TOKEN信息返回给用户
  3. 用户再次进入网关开始访问,网关过滤器接收用户携带的TOKEN
  4. 网关过滤器解析TOKEN ,判断是否有权限,如果有,则放行,如果没有则返回未认证错误

在网关微服务中新建全局过滤器:

(1)编写全局过滤器

package com.itheima.gatewayadmin.filter;

import com.itheima.common.constants.SystemConstants;
import com.itheima.common.util.AppJwtUtil;
import org.checkerframework.checker.units.qual.A;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

/**
 * @author ljh
 * @version 1.0
 * @date 2021/8/1 09:06
 * @description 标题
 * @package com.itheima.gatewayadmin.filter
 */
@Component
public class AuthorizeFilter implements GlobalFilter, Ordered {

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        //+ 1.先获取请求和响应对象
        ServerHttpRequest request = exchange.getRequest();

        ServerHttpResponse response = exchange.getResponse();
        // /get /a  post /a

        //+ 2.判断当前的请求 是否 是登录的请求 如果是 ,则放行
        String path = request.getURI().getPath();
        if(path.startsWith("/admin/admin/login")){
            return chain.filter(exchange);
        }

        //+ 3.获取页面传递过来的请求头中的令牌数据 如果获取不到 返回错误(401)
        String token = request.getHeaders().getFirst("token");
        if(StringUtils.isEmpty(token)){
            response.setStatusCode(HttpStatus.UNAUTHORIZED);
            return  response.setComplete();//完成响应 返回 后面就不执行了
        }

        //+ 4.校验令牌 校验失败 返回错误401
        //通过jwt 来校验
        if(SystemConstants.JWT_OK!=AppJwtUtil.verifyToken(token)){
            response.setStatusCode(HttpStatus.UNAUTHORIZED);
            return  response.setComplete();//完成响应 返回 后面就不执行了
        }
        //+ 5.校验成功 放行
        return chain.filter(exchange);
    }


    //过滤器的执行的优先级的设置 值越低 优先级越高
    @Override
    public int getOrder() {
        return 0;
    }
}

测试:注意,从网关开始访问:

1614048847043

先登录:

1614049027664

携带token再进行访问:

1614049110201

2 APP端用户实名认流程说明

2.1 需求分析

APP端用户在app端进行实名认证

1614060639792

平台后台管理系统可以查看实名认证的信息,便于进行审核。

1614060753555

当用户在app前端进行了实名认证请求之后会自动往ap_user_realname表中加入数据

1605943271408

我们的需求是:

需要实现平台的用户实名认证的列表信息查询,如下图:

1614060753555

2.2 搭建user微服务

(1)新建微服务工程:itheima-leadnews-service-user和对应api工程

1614069837655

itheima-leadnews-service-user工程的pom.xml:

<?xml version="1.0" encoding="UTF-8"?>
<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>itheima-leadnews-service</artifactId>
        <groupId>com.itheima</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>itheima-leadnews-service-user</artifactId>

    <dependencies>
        <dependency>
            <groupId>com.itheima</groupId>
            <artifactId>itheima-leadnews-user-api</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
        <dependency>
            <groupId>com.itheima</groupId>
            <artifactId>itheima-leadnews-common-db</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
         <dependency>
            <groupId>com.itheima</groupId>
            <artifactId>itheima-leadnews-core-controller</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
    </dependencies>
</project>

(2)创建启动类

package com.itheima;

import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.context.annotation.Bean;

/**
 * @author ljh
 * @version 1.0
 * @date 2021/2/23 16:45
 * @description 标题
 * @package com.itheima
 */
@SpringBootApplication
@EnableDiscoveryClient
@MapperScan(basePackages = "com.itheima.user.mapper")
public class UserApplication {
    public static void main(String[] args) {
        SpringApplication.run(UserApplication.class,args);
    }
    @Bean
    public PaginationInterceptor paginationInterceptor() {
        return new PaginationInterceptor();
    }
}

(3)在resources下新建application.yml

spring:
  profiles:
    active: dev
---
server:
  port: 9002
spring:
  application:
    name: leadnews-user
  profiles: dev
  datasource:
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://192.168.211.136:3306/leadnews_user?useSSL=false&useUnicode=true&characterEncoding=UTF-8&serverTimezone=&serverTimezone=Asia/Shanghai
    username: root
    password: 123456
  cloud:
    nacos:
      server-addr: 192.168.211.136:8848
      discovery:
        server-addr: ${spring.cloud.nacos.server-addr}

# 设置Mapper接口所对应的XML文件位置,如果你在Mapper接口中有自定义方法,需要进行该配置
mybatis-plus:
  mapper-locations: classpath*:mapper/*.xml
  # 设置别名包扫描路径,通过该属性可以给包中的类注册别名
  type-aliases-package: com.itheima.user.pojo
---
server:
  port: 9002
spring:
  application:
    name: leadnews-user
  profiles: pro
  datasource:
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://192.168.211.136:3306/leadnews_user?useSSL=false&useUnicode=true&characterEncoding=UTF-8&serverTimezone=&serverTimezone=Asia/Shanghai
    username: root
    password: 123456
  cloud:
    nacos:
      server-addr: 192.168.211.136:8848
      discovery:
        server-addr: ${spring.cloud.nacos.server-addr}
# 设置Mapper接口所对应的XML文件位置,如果你在Mapper接口中有自定义方法,需要进行该配置
mybatis-plus:
  mapper-locations: classpath*:mapper/*.xml
  # 设置别名包扫描路径,通过该属性可以给包中的类注册别名
  type-aliases-package: com.itheima.user.pojo
---
server:
  port: 9002
spring:
  application:
    name: leadnews-user
  profiles: test
  datasource:
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://192.168.211.136:3306/leadnews_user?useSSL=false&useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai
    username: root
    password: 123456
  cloud:
    nacos:
      server-addr: 192.168.211.136:8848
      discovery:
        server-addr: ${spring.cloud.nacos.server-addr}
# 设置Mapper接口所对应的XML文件位置,如果你在Mapper接口中有自定义方法,需要进行该配置
mybatis-plus:
  mapper-locations: classpath*:mapper/*.xml
  # 设置别名包扫描路径,通过该属性可以给包中的类注册别名
  type-aliases-package: com.itheima.user.pojo

(4)使用代码生成器生成相关的controller service mapper pojo

1614070188103

执行生成动作,生成如下:

1614070346903

copy代码到对应工程中,该操作不在文档中演示了。copy之后查询的功能就已经实现了。

此时用户实名认证列表查询功能已经完成。启动服务并测试如下

1614070765126

3 app端用户认证后审核

3.1 需求分析

当用户提交了实名认证之后,认证信息便已经存储到了数据库表中。我们平台需要进行审核。

审核流程说明如下:

  • 在app端的个人中心用户可以实名认证,需要材料为:姓名、身份证号、身份证正面照、身份证反面照、手持照片、活体照片(通过微笑、眨眼、张嘴、摇头、点头等组合动作,确保操作的为真实活体人脸。),当用户提交审核后就到了后端让运营管理人员进行审核
  • 平台运营端查看用户认证信息,进行审核,其中审核包括了用户身份审核,需要对接公安系统校验身份证信息
  • 用户通过审核后需要开通自媒体账号(该账号的用户名和密码与app一致)
  • 用户通过审核后需要在article中在作者表中新建一个作者信息

如图刚才的流程对应的微服务的数据库为如下图所示:

1614071194740

3.2 实现思路分析

1614071590563

上图解释:

1.当平台管理审核人员进行点击审核通过的按钮之后
2.用户微服务接收到请求进行数据操作 实名认证状态
3.并同时通过Feign调用实现自媒体微服务的业务操作 创建自媒体账号
4.并同时通过Feign调用实现文章微服务创建作者信息。

操作步骤说明:

1.搭建 自媒体微服务 和 文章微服务

2.实现审核通过 用户微服务 修改状态

3.创建feign 分别远程调用 自媒体和文章

4 搭建微服务

4.1 搭建自媒体微服务

(1)创建自媒体微服务

1614072668110

pom.xml:

<?xml version="1.0" encoding="UTF-8"?>
<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>itheima-leadnews-service</artifactId>
        <groupId>com.itheima</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>itheima-leadnews-service-wemedia</artifactId>
    <dependencies>
        <dependency>
            <groupId>com.itheima</groupId>
            <artifactId>itheima-leadnews-common-db</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
        <dependency>
            <groupId>com.itheima</groupId>
            <artifactId>itheima-leadnews-wemedia-api</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
        <dependency>
            <groupId>com.itheima</groupId>
            <artifactId>itheima-leadnews-core-controller</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
    </dependencies>
</project>

(2)创建启动类和yml及相关配置

package com.itheima;

import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.context.annotation.Bean;

/**
 * @author ljh
 * @version 1.0
 * @date 2021/2/25 15:22
 * @description 标题
 * @package com.itheima
 */
@SpringBootApplication
@EnableDiscoveryClient
@MapperScan(basePackages = "com.itheima.media.mapper")
public class MediaApplication {
    public static void main(String[] args) {
        SpringApplication.run(MediaApplication.class, args);
    }
    @Bean
    public PaginationInterceptor paginationInterceptor() {
        return new PaginationInterceptor();
    }
}

application.yml

spring:
  profiles:
    active: dev
---
server:
  port: 9004
spring:
  profiles: dev
  application:
    name: leadnews-wemedia
  cloud:
    nacos:
      discovery:
        server-addr: 192.168.211.136:8848
  datasource:
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://192.168.211.136:3306/leadnews_wemedia?useSSL=false&useUnicode=true&characterEncoding=UTF-8&serverTimezone=&serverTimezone=Asia/Shanghai
    username: root
    password: 123456
# 设置Mapper接口所对应的XML文件位置,如果你在Mapper接口中有自定义方法,需要进行该配置
mybatis-plus:
  mapper-locations: classpath*:mapper/*.xml
  # 设置别名包扫描路径,通过该属性可以给包中的类注册别名
  type-aliases-package: com.itheima.media.pojo
---
server:
  port: 9004
spring:
  profiles: test
  application:
    name: leadnews-wemedia
  cloud:
    nacos:
      discovery:
        server-addr: 192.168.211.136:8848
  datasource:
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://192.168.211.136:3306/leadnews_wemedia?useSSL=false&useUnicode=true&characterEncoding=UTF-8&serverTimezone=&serverTimezone=Asia/Shanghai
    username: root
    password: 123456
# 设置Mapper接口所对应的XML文件位置,如果你在Mapper接口中有自定义方法,需要进行该配置
mybatis-plus:
  mapper-locations: classpath*:mapper/*.xml
  # 设置别名包扫描路径,通过该属性可以给包中的类注册别名
  type-aliases-package: com.itheima.media.pojo
---
server:
  port: 9004
spring:
  profiles: pro
  application:
    name: leadnews-wemedia
  cloud:
    nacos:
      discovery:
        server-addr: 192.168.211.136:8848
  datasource:
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://192.168.211.136:3306/leadnews_wemedia?useSSL=false&useUnicode=true&characterEncoding=UTF-8&serverTimezone=&serverTimezone=Asia/Shanghai
    username: root
    password: 123456
# 设置Mapper接口所对应的XML文件位置,如果你在Mapper接口中有自定义方法,需要进行该配置
mybatis-plus:
  mapper-locations: classpath*:mapper/*.xml
  # 设置别名包扫描路径,通过该属性可以给包中的类注册别名
  type-aliases-package: com.itheima.media.pojo

(3)使用代码生成器生成相关代码放到对应位置,copy步骤略,最终效果如下
1614238372887

4.2 搭建文章微服务

(1)创建文章微服务

1614239135229

pom.xml:

<?xml version="1.0" encoding="UTF-8"?>
<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>itheima-leadnews-service</artifactId>
        <groupId>com.itheima</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>itheima-leadnews-service-article</artifactId>
    <dependencies>
        <dependency>
            <groupId>com.itheima</groupId>
            <artifactId>itheima-leadnews-article-api</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
        <dependency>
            <groupId>com.itheima</groupId>
            <artifactId>itheima-leadnews-common-db</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
        <dependency>
            <groupId>com.itheima</groupId>
            <artifactId>itheima-leadnews-core-controller</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
    </dependencies>
</project>

(2)新建启动类和yaml配置

package com.itheima;

import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.context.annotation.Bean;

/**
 * @author ljh
 * @version 1.0
 * @date 2021/2/25 15:48
 * @description 标题
 * @package com.itheima
 */
@SpringBootApplication
@EnableDiscoveryClient
@MapperScan(basePackages = "com.itheima.article.mapper")
public class ArticleApplication {
    public static void main(String[] args) {
        SpringApplication.run(ArticleApplication.class, args);
    }

    @Bean
    public PaginationInterceptor paginationInterceptor() {
        return new PaginationInterceptor();
    }
}
spring:
  profiles:
    active: dev
---
server:
  port: 9003
spring:
  application:
    name: leadnews-article
  profiles: dev
  datasource:
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://192.168.211.136:3306/leadnews_article?useSSL=false&useUnicode=true&characterEncoding=UTF-8&serverTimezone=&serverTimezone=Asia/Shanghai
    username: root
    password: 123456
  cloud:
    nacos:
      server-addr: 192.168.211.136:8848
      discovery:
        server-addr: ${spring.cloud.nacos.server-addr}

# 设置Mapper接口所对应的XML文件位置,如果你在Mapper接口中有自定义方法,需要进行该配置
mybatis-plus:
  mapper-locations: classpath*:mapper/*.xml
  # 设置别名包扫描路径,通过该属性可以给包中的类注册别名
  type-aliases-package: com.itheima.article.pojo
---
server:
  port: 9003
spring:
  application:
    name: leadnews-user
  profiles: pro
  datasource:
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://192.168.211.136:3306/leadnews_article?useSSL=false&useUnicode=true&characterEncoding=UTF-8&serverTimezone=&serverTimezone=Asia/Shanghai
    username: root
    password: 123456
  cloud:
    nacos:
      server-addr: 192.168.211.136:8848
      discovery:
        server-addr: ${spring.cloud.nacos.server-addr}
# 设置Mapper接口所对应的XML文件位置,如果你在Mapper接口中有自定义方法,需要进行该配置
mybatis-plus:
  mapper-locations: classpath*:mapper/*.xml
  # 设置别名包扫描路径,通过该属性可以给包中的类注册别名
  type-aliases-package: com.itheima.article.pojo
---
server:
  port: 9003
spring:
  application:
    name: leadnews-user
  profiles: test
  datasource:
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://192.168.211.136:3306/leadnews_article?useSSL=false&useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai
    username: root
    password: 123456
  cloud:
    nacos:
      server-addr: 192.168.211.136:8848
      discovery:
        server-addr: ${spring.cloud.nacos.server-addr}
# 设置Mapper接口所对应的XML文件位置,如果你在Mapper接口中有自定义方法,需要进行该配置
mybatis-plus:
  mapper-locations: classpath*:mapper/*.xml
  # 设置别名包扫描路径,通过该属性可以给包中的类注册别名
  type-aliases-package: com.itheima.article.pojo

(3)代码生成器生成代码放到对应位置,copy步骤省略 ,最终效果如下

1614240113794

5 实现业务功能

5.1 实现审核用户通过和驳回

5.1.1 需求分析

通过:

1614240743081

点击通过之后,直接发送请求到后台 后台接收到请求之后更新状态即可,我们可以定义一个controller 和service dao 接收该请求的处理即可。

请求:/apUserRealname/pass/{id}  PUT
参数:id 用户实名认证的记录的ID
返回值:Result 返回成功与否即可

驳回:

1614241131805

点击提交之后,直接发送请求 携带拒绝的原因信息到后台 后台接收到请求之后更新状态即可。

我们可以定义一个controller 和service dao 接收该请求的处理即可。

表结构如下:

1614258279963

5.1.2 功能实现

(1)编写controller

1614241490563

//审核通过
@PutMapping("/pass/{id}")
public Result pass(@PathVariable(name="id") Integer id){
    apUserRealnameService.pass(id);
    return Result.ok();
}

//驳回
@PutMapping("/reject/{id}")
public Result reject(@PathVariable(name="id")Integer id,@RequestParam(required = true,name="reason") String reason){
    apUserRealnameService.reject(id,reason);
    return Result.ok();
}

(2)编写业务代码

实现驳回功能

业务接口:

public interface ApUserRealnameService extends IService<ApUserRealname> {

    
   

    void reject(Integer id, String reason);

}

实现类:

@Service
public class ApUserRealnameServiceImpl extends ServiceImpl<ApUserRealnameMapper, ApUserRealname> implements ApUserRealnameService {


    @Autowired
    private ApUserRealnameMapper apUserRealnameMapper;
  

    @Override
    public void reject(Integer id, String reason) {
        ApUserRealname apUserRealname = new ApUserRealname();
        apUserRealname.setId(id);
        apUserRealname.setReason(reason);
        //更新时间
        apUserRealname.setUpdatedTime(LocalDateTime.now());
        //设置状态为审核失败
        apUserRealname.setStatus(BusinessConstants.ApUserRealnameConstants.SHENHE_FAILE);
        apUserRealnameMapper.updateById(apUserRealname);
    }
}

创建常量接口:

1614244841396

public interface BusinessConstants {
    //实名认证相关
   public static class ApUserRealnameConstants{
        //创建中
        public static final Integer SHENHE_ING=0;
        //待审核
        public static final Integer SHENHE_WARTING=1;
        //审核失败
        public static final Integer SHENHE_FAILE=2;
        //审核通过
        public static final Integer SHENHE_SUCESS=9;
    }

}

常量接口 用于 做业务常量 由于有许多的业务,所以在接口中添加静态内部类进行设置。用来区分不同的业务。

实现审核通过功能

业务接口:

public interface ApUserRealnameService extends IService<ApUserRealname> {

    //审核通过
    void pass(Integer id);

    //略
    

}

实现类:

@Autowired
private ApUserRealnameMapper apUserRealnameMapper;

@Override
public void pass(Integer id) {
    ApUserRealname entity = new ApUserRealname();
    entity.setId(id);
    //审核通过
    entity.setStatus(BusinessConstants.ApUserRealnameConstants.SHENHE_SUCESS);
    apUserRealnameMapper.updateById(entity);

    //todo feign远程调用 自媒体服务 创建自媒体账号

    //todo feign远程调用 文章微服务 创建作者账号

}

1614248534953

5.2 实现Feign远程调用

1614257716124

相关表如下:

自媒体表:

1614258332480

作者表:

1614258361359

5.2.1 实现自媒体远程调用

操作步骤如下:

(1) 添加依赖

(2) 创建feign接口

(3) 实现feign接口(业务实现)

(4) 调用Feign接口实现创建自媒体账号

(1) 添加依赖

由于feign 每一个都要用到,以及还需要用到common中的result类,所以在itheima-leadnews-api下添加依赖如下:

1614257849619

<?xml version="1.0" encoding="UTF-8"?>
<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>itheima-leadnews</artifactId>
        <groupId>com.itheima</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>itheima-leadnews-api</artifactId>
    <packaging>pom</packaging>
    <description>所有feign pojo所在父工程</description>
    <modules>
        <module>itheima-leadnews-admin-api</module>
        <module>itheima-leadnews-user-api</module>
        <module>itheima-leadnews-wemedia-api</module>
        <module>itheima-leadnews-article-api</module>
    </modules>
    <dependencies>
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>

        <dependency>
            <groupId>com.itheima</groupId>
            <artifactId>itheima-leadnews-common</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
    </dependencies>

</project>

(2) 创建feign接口(位置如图)

1614257954582

@FeignClient(name="leadnews-wemedia",path = "/wmUser")
public interface WmUserFeign {
    //创建自媒体账户信息
    @PostMapping
    public Result save(@RequestBody WmUser wmUser);

    /**
     * 根据apUserId获取
     * @param apUserId
     * @return
     */
    @GetMapping("/one/{apUserId}")
    public WmUser getByApUserId(@PathVariable(name="apUserId") Integer apUserId);
}

(3) 实现feign接口(业务实现)在controller中

1614258007377

@GetMapping("/one/{apUserId}")
public WmUser getByApUserId(@PathVariable(name="apUserId") Integer apUserId){
    QueryWrapper<WmUser> queryWrapper = new QueryWrapper<WmUser>();
    queryWrapper.eq("ap_user_id",apUserId);
    WmUser wmUser = wmUserService.getOne(queryWrapper);
    return wmUser;
}

还有一个接口不需要实现:因为抽象类中早已实现了:

1614258082737

(4)调用Feign接口实现创建自媒体账号

itheima-leadnews-service-user微服中添加使用到的依赖并Feign开启接口扫描:

<dependency>
    <groupId>com.itheima</groupId>
    <artifactId>itheima-leadnews-wemedia-api</artifactId>
    <version>1.0-SNAPSHOT</version>
</dependency>

XML如下图:

1614259084265

开启扫描如下图:*** 号代表占位符,表示任意的包名**

1614258120346

通过审核业务实现类中实现远程调用:

private static final Logger logger = LoggerFactory.getLogger(ApUserRealnameServiceImpl.class);

@Autowired
private ApUserRealnameMapper apUserRealnameMapper;

@Autowired
private WmUserFeign wmUserFeign;

@Autowired
private ApUserMapper apUserMapper;
@Override
public void pass(Integer id) {
    ApUserRealname entity = new ApUserRealname();
    entity.setId(id);
    //审核通过
    entity.setStatus(BusinessConstants.ApUserRealnameConstants.SHENHE_SUCESS);
    apUserRealnameMapper.updateById(entity);

    //todo feign远程调用 自媒体服务 创建自媒体账号
    ApUserRealname apUserRealname = apUserRealnameMapper.selectById(id);
    if (apUserRealname != null) {
        ApUser apUser = apUserMapper.selectById(apUserRealname.getUserId());
        //判断是否已经存在
        WmUser wmUser = wmUserFeign.getByApUserId(apUser.getId());
        if (wmUser == null) {
             wmUser = new WmUser();
            //copy数据到wmUser中
            BeanUtils.copyProperties(apUser, wmUser);
            //设置状态
            wmUser.setStatus(BusinessConstants.WmUserConstants.WM_USER_OK);
            //设置APP用户的ID
            wmUser.setApUserId(apUser.getId());
            //设置创建时间
            wmUser.setCreatedTime(LocalDateTime.now());
            Result result = wmUserFeign.save(wmUser);
            if (result.isSuccess()) {
                logger.info("自媒体账号创建成功");
            }
        }
        //todo feign远程调用 文章微服务 创建作者账号
    }

}

在业务接口常量接口中 创建静态内部常量类:

public static class WmUserConstants{
       //有效
       public static final Integer WM_USER_OK= 9;
       //冻结
       public static final Integer WM_USER_LOCKED= 0;
       //永久失效
       public static final Integer WM_USER_INVALID= 1;
 }

1614258447396

5.2.2 实现文章远程调用

操作步骤如下:

(1) 添加依赖

(2) 创建feign接口

(3) 实现feign接口(业务实现)

(4)调用Feign接口实现创建作者账号

(1) 添加依赖

忽略,上一个步骤已经做了。就是添加openfeign

(2) 创建feign接口

1614260217043

@FeignClient(name="leadnews-article",path = "/apAuthor")
public interface ApAuthorFeign {
    //保存作者账号
    @PostMapping
    public Result save(@RequestBody ApAuthor apAuthor);

    /**
     * 根据APP用户的ID 获取 作者信息
     * @param apUserId
     * @return
     */
    @GetMapping("/one/{apUserId}")
    public ApAuthor getByApUserId(@PathVariable(name="apUserId")Integer apUserId);
}

(3) 实现feign接口(业务实现)

1614260284662

   /**
     * 根据app用户的ID 获取作者信息
     * @param apUserId
     * @return
     */
    @GetMapping("/one/{apUserId}")
    public ApAuthor getByApUserId(@PathVariable(name="apUserId")Integer apUserId){
        QueryWrapper<ApAuthor> queryWrapper = new QueryWrapper<ApAuthor>();
        queryWrapper.eq("user_id",apUserId);
        ApAuthor apAuthor = apAuthorService.getOne(queryWrapper);
        return apAuthor;
    }

还有一个保存作者 不需要实现了,因为咱们抽象类中已经完成,你只需要进行声明即可。

(4)添加依赖并调用Feign接口实现创建作者账号

1614260359900

<dependency>
    <groupId>com.itheima</groupId>
    <artifactId>itheima-leadnews-wemedia-api</artifactId>
    <version>1.0-SNAPSHOT</version>
</dependency>

在通过审核的业务代码的实现类中进行远程调用:

private static final Logger logger = LoggerFactory.getLogger(ApUserRealnameServiceImpl.class);

@Autowired
private ApUserRealnameMapper apUserRealnameMapper;

@Autowired
private WmUserFeign wmUserFeign;


@Autowired
private ApAuthorFeign apAuthorFeign;

@Autowired
private ApUserMapper apUserMapper;

@Override
public void pass(Integer id) {
    ApUserRealname entity = new ApUserRealname();
    entity.setId(id);
    //审核通过
    entity.setStatus(BusinessConstants.ApUserRealnameConstants.SHENHE_SUCESS);
    apUserRealnameMapper.updateById(entity);

    //todo feign远程调用 自媒体服务 创建自媒体账号
    ApUserRealname apUserRealname = apUserRealnameMapper.selectById(id);
    if (apUserRealname != null) {
        ApUser apUser = apUserMapper.selectById(apUserRealname.getUserId());
        //判断是否已经存在
        WmUser wmUser = wmUserFeign.getByApUserId(apUser.getId());
        if (wmUser == null) {
            //copy数据到wmUser中
            wmUser = new WmUser();
            BeanUtils.copyProperties(apUser, wmUser);
            //设置状态
            wmUser.setStatus(BusinessConstants.WmUserConstants.WM_USER_OK);
            //设置APP用户的ID
            wmUser.setApUserId(apUser.getId());
            //设置创建时间
            wmUser.setCreatedTime(LocalDateTime.now());
             Result<WmUser> result = wmUserFeign.save(wmUser);
            if (result.isSuccess()) {
                logger.info("自媒体账号创建成功");
                wmUser = result.getData();
            }
        }
        //todo feign远程调用 文章微服务 创建作者账号
        ApAuthor apAuthor = apAuthorFeign.getByApUserId(apUser.getId());
        if(apAuthor==null){
            apAuthor = new ApAuthor();
            //作者名称就是登录名
            apAuthor.setName(apUser.getName());
            apAuthor.setType(BusinessConstants.ApAuthorConstants.A_MEDIA_USER);
            apAuthor.setCreatedTime(LocalDateTime.now());
            apAuthor.setUserId(apUser.getId());
            apAuthor.setWmUserId(wmUser.getId());
            apAuthorFeign.save(apAuthor);
        }
    }

}

创建常量类:

1614260433486

public static class ApAuthorConstants{
    /**
         * 平台自媒体人
         */
    public static final Integer A_MEDIA_USER= 2;
    //合作商
    public static final Integer A_MEDIA_SELLER= 1;
    //普通作者
    public static final Integer A_MEDIA_ZERO= 0;
}

5.2.3 网关对接user微服务

在admin网关的yml文件中进行配置如下:

1622776532161

        - id: user
          uri: lb://leadnews-user
          predicates:
            - Path=/user/**
          filters:
            - StripPrefix= 1

5.3 测试

通过网关登录,登录之后再进行测试校验。

6 feign抽取

6.1 分析

我们发现,如果每一个feign都有相关的针对单表的操作,那么每一个都写一个样的代码是不合理的而且是麻烦的,那么我们可以参考抽取controller一样的方式去抽取feign ,我们不搞那么复杂,因为feign只是接口声明,

子类继承接口即可。

1616247864736

如图,就是 每一个业务接口 继承 定义了抽取了通用的方法的接口 ,然后每一个业务接口如果是基本的CRUD,都不用进行声明了。直接调用即可。

6.2 代码实现抽取

创建核心feign接口

1614302046920

代码如下:

package com.itheima.core.feign;

import com.itheima.common.pojo.PageInfo;
import com.itheima.common.pojo.PageRequestDto;
import com.itheima.common.pojo.Result;
import org.springframework.web.bind.annotation.*;

import java.io.Serializable;
import java.util.List;

/**
 * @author ljh
 * @version 1.0
 * @date 2021/2/26 09:06
 * @description 标题
 * @package com.itheima.core.feign
 */
public interface CoreFeign<T> {

    @DeleteMapping("/{id}")
    public Result deleteById(@PathVariable(name = "id") Serializable id) ;
    /**
     * 添加记录
     *
     * @param record
     * @return
     */
    @PostMapping
    public Result<T> save(@RequestBody T record) ;

    //更新数据
    @PutMapping
    public Result updateByPrimaryKey(@RequestBody T record) ;


    @GetMapping("/{id}")
    public Result<T> findById(@PathVariable(name = "id") Serializable id) ;

    @GetMapping
    public Result<List<T>> findAll() ;


    /**
     * 通用条件分页查询
     *
     * @param pageRequestDto
     * @return
     */
    @PostMapping(value = "/search")
    public Result<PageInfo<T>> findByPage(@RequestBody PageRequestDto<T> pageRequestDto) ;


}

添加依赖:

1614302347605

修改Feign接口:

1614302396689

1614302427561

再测试也是一样的效果,这样就不用重复编写了,

但是要注意的是:请求路径不能和父接口(coreFeign)中的一样。

7 使用okhttp(可选项)

​ 在使用默认的feign的时候,feign底层实际上是使用restTemplete 而restTemplate底层又使用到了httpclient,默认使用java自带的httpUrlConnection。我们是可以使用okhttp ,默认的feign调用httpUrlConnection每次都会创建一个链接对象。效率较低。所以使用okhttp来替换,它可以使用连接池。调用效率较高。

在itheima-leadnews-core-feign微服务中的pom.xml中添加依赖

<dependency>
    <groupId>io.github.openfeign</groupId>
    <artifactId>feign-okhttp</artifactId>
</dependency>

1616247691225

在需要用到feign的微服务中配置如下即可

feign:
  client:
    config:
      default: # default指定的是所有的 被调用方  都设置为该配置超时时间,可以设置为某一个微服务对应的服务名
        connectTimeout: 5000 # 链接超时时间
        readTimeout: 5000 # 读取的超时时间
  okhttp:
    enabled: true
  httpclient:
    enabled: false

8 网关整合knife4j

每次我们测试都需要通过POSTMAN 结合网关来测试,这样麻烦,我们可以集成到knife4j上去进行测试。如下:

(1)创建三个类在网关中

1622007474256

从此处copy

1622007530472

(2)admin微服务中创建配置类:如果有则不用创建了。

package com.itheima.admin.config;

import com.github.xiaoymin.knife4j.spring.annotations.EnableKnife4j;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import springfox.bean.validators.configuration.BeanValidatorPluginsConfiguration;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.Contact;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;

import java.util.HashSet;

@Configuration
@EnableSwagger2//启用swagger
@EnableKnife4j//启用Knife4j
@Import(BeanValidatorPluginsConfiguration.class)
public class SwaggerConfiguration {

   /*@Bean
   public Docket buildDocket() {
      HashSet<String> strings = new HashSet<>();
      strings.add("application/json");

      return new Docket(DocumentationType.SWAGGER_2)
              .apiInfo(buildApiInfo())
              //设置返回值数据类型为json
              .produces(strings)//设置响应的结果的数据类型 变成JSON
              .select()
              // 要扫描的API(Controller)基础包
              .apis(RequestHandlerSelectors.basePackage("com.itheima.admin.controller"))
              //针对那些路径生成API文档 /**
              .paths(PathSelectors.any())
              .build();
   }

   private ApiInfo buildApiInfo() {
      Contact contact = new Contact("黑马程序员","","");
      return new ApiInfoBuilder()
              .title("黑马头条-平台管理API文档")
              .description("平台管理服务api")
              .contact(contact)
              .version("1.0.0").build();
   }*/
   @Bean
   public Docket buildDocket() {
      HashSet<String> strings = new HashSet<>();
      strings.add("application/json");
      Docket docket=new Docket(DocumentationType.SWAGGER_2)
              .apiInfo(buildApiInfo())
              //设置返回数据类型
              .produces(strings)
              //分组名称
              //.groupName("1.0")
              .select()
              //这里指定Controller扫描包路径
              .apis(RequestHandlerSelectors.basePackage("com.itheima.admin.controller"))
              //**
              .paths(PathSelectors.any())
              .build();
      return docket;
   }
   private ApiInfo buildApiInfo() {
      Contact contact = new Contact("黑马程序员","","");
      return new ApiInfoBuilder()
              .title("黑马头条-平台管理API文档")
              .description("平台管理服务api")
              .contact(contact)
              .version("1.0.0").build();
   }
}

(3)过滤器中添加如下代码

1622007637109

(4)启动网关 和微服务测试:通过网关地址进行访问

1622007663814

登录:

1622007722836

根据登录之后获取到的token 在全局参数中添加之后,就可以直接测试了:

1622007790772

测试访问:

1622007857581

标签:代码生成,网关,day03,server,import,leadnews,com,public,itheima
来源: https://www.cnblogs.com/ofanimon/p/16188460.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有