• SpringCloud微服务(注册发现Nacos、服务调用SSM、网关gateway)项目环境搭建(项目概况,SSM细节总结)


    1.nacos环境搭建

    nacos安装

    ①:docker拉取镜像

    docker pull nacos/nacos-server:1.2.0
    
    • 1

    ②:创建容器

    docker run --env MODE=standalone --name nacos --restart=always  -d -p 8848:8848 nacos/nacos-server:1.2.0
    
    • 1
    • MODE=standalone 单机版

    • –restart=always 开机启动

    • -p 8848:8848 映射端口

    • -d 创建一个守护式容器在后台运行

    ③:访问地址:http://192.168.200.130:8848/nacos
    在这里插入图片描述

    2.项目主体结构

    在这里插入图片描述
    在这里插入图片描述

    6.2)表结构分析

    关于app端用户相关的内容较多,可以单独设置一个库leadnews_user

    表名称说明
    ap_userAPP用户信息表
    ap_user_fanAPP用户粉丝信息表
    ap_user_followAPP用户关注信息表
    ap_user_realnameAPP实名认证信息表

    从当前资料中找到对应数据库并导入到mysql中
    项目中的持久层使用的mybatis-plus,一般都使用mybais-plus逆向生成对应的实体类

    app_user表对应的实体类如下:

    package com.heima.model.user.pojos;
    
    import com.baomidou.mybatisplus.annotation.IdType;
    import com.baomidou.mybatisplus.annotation.TableField;
    import com.baomidou.mybatisplus.annotation.TableId;
    import com.baomidou.mybatisplus.annotation.TableName;
    import lombok.Data;
    
    import java.io.Serializable;
    import java.util.Date;
    
    /**
     * 

    * APP用户信息表 *

    * * @author itheima */
    @Data @TableName("ap_user") public class ApUser implements Serializable { private static final long serialVersionUID = 1L; /** * 主键 */ @TableId(value = "id", type = IdType.AUTO) private Integer id; /** * 密码、通信等加密盐 */ @TableField("salt") private String salt; /** * 用户名 */ @TableField("name") private String name; /** * 密码,md5加密 */ @TableField("password") private String password; /** * 手机号 */ @TableField("phone") private String phone; /** * 头像 */ @TableField("image") private String image; /** * 0 男 1 女 2 未知 */ @TableField("sex") private Boolean sex; /** * 0 未 1 是 */ @TableField("is_certification") private Boolean certification; /** * 是否身份认证 */ @TableField("is_identity_authentication") private Boolean identityAuthentication; /** * 0正常 1锁定 */ @TableField("status") private Boolean status; /** * 0 普通用户 1 自媒体人 2 大V */ @TableField("flag") private Short flag; /** * 注册时间 */ @TableField("created_time") private Date createdTime; }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103

    手动加密(md5+随机字符串)

    md5是不可逆加密,md5相同的密码每次加密都一样,不太安全。在md5的基础上手动加盐(salt)处理

    注册->生成盐在这里插入图片描述
    登录->使用盐来配合验证在这里插入图片描述
    1,用户输入了用户名和密码进行登录,校验成功后返回jwt(基于当前用户的id生成)

    2,用户游客登录,生成jwt返回(基于默认值0生成)‘

    6.4)运营端微服务搭建

    在heima-leadnews-service下创建工程heima-leadnews-user在这里插入图片描述
    引导类

    package com.heima.user;
    
    import org.mybatis.spring.annotation.MapperScan;
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
    
    @SpringBootApplication
    @EnableDiscoveryClient
    @MapperScan("com.heima.user.mapper")
    public class UserApplication {
    
        public static void main(String[] args) {
            SpringApplication.run(UserApplication.class,args);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    bootstrap.yml

    server:
      port: 51801
    spring:
      application:
        name: leadnews-user
      cloud:
        nacos:
          discovery:
            server-addr: 192.168.200.130:8848
          config:
            server-addr: 192.168.200.130:8848
            file-extension: yml
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    在nacos中创建配置文件

    spring:
      datasource:
        driver-class-name: com.mysql.jdbc.Driver
        url: jdbc:mysql://localhost:3306/leadnews_user?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC
        username: root
        password: root
    # 设置Mapper接口所对应的XML文件位置,如果你在Mapper接口中有自定义方法,需要进行该配置
    mybatis-plus:
      mapper-locations: classpath*:mapper/*.xml
      # 设置别名包扫描路径,通过该属性可以给包中的类注册别名
      type-aliases-package: com.heima.model.user.pojos
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    logback.xml

    
    
        
            
            %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
            utf8
        
    
    
    
    
        
            
            ${LOG_HOME}/leadnews.%d{yyyy-MM-dd}.log
        
        
            %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
        
    
    
    
    
        
        0
        
        512
        
        
    
    
    
    
        
    
    
    
        
        
        
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40

    6.4)登录功能实现

    ①:接口定义

    @RestController
    @RequestMapping("/api/v1/login")
    public class ApUserLoginController {
    
        @PostMapping("/login_auth")
        public ResponseResult login(@RequestBody LoginDto dto) {
            return null;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    ②:持久层mapper

    package com.heima.user.mapper;
    
    import com.baomidou.mybatisplus.core.mapper.BaseMapper;
    import com.heima.model.user.pojos.ApUser;
    import org.apache.ibatis.annotations.Mapper;
    
    @Mapper
    public interface ApUserMapper extends BaseMapper<ApUser> {
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    ③:业务层service

    package com.heima.user.service;
    
    import com.baomidou.mybatisplus.extension.service.IService;
    import com.heima.model.common.dtos.ResponseResult;
    import com.heima.model.user.dtos.LoginDto;
    import com.heima.model.user.pojos.ApUser;
    
    public interface ApUserService extends IService<ApUser>{
    
        /**
         * app端登录
         * @param dto
         * @return
         */
        public ResponseResult login(LoginDto dto);
        
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    实现类:

    package com.heima.user.service.impl;
    
    import com.baomidou.mybatisplus.core.toolkit.Wrappers;
    import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
    import com.heima.model.common.dtos.ResponseResult;
    import com.heima.model.common.enums.AppHttpCodeEnum;
    import com.heima.model.user.dtos.LoginDto;
    import com.heima.model.user.pojos.ApUser;
    import com.heima.user.mapper.ApUserMapper;
    import com.heima.user.service.ApUserService;
    import com.heima.utils.common.AppJwtUtil;
    import org.apache.commons.lang3.StringUtils;
    import org.springframework.stereotype.Service;
    import org.springframework.util.DigestUtils;
    
    import java.util.HashMap;
    import java.util.Map;
    
    
    @Service
    public class ApUserServiceImpl extends ServiceImpl<ApUserMapper, ApUser> implements ApUserService {
    
        @Override
        public ResponseResult login(LoginDto dto) {
    
            //1.正常登录(手机号+密码登录)
            if (!StringUtils.isBlank(dto.getPhone()) && !StringUtils.isBlank(dto.getPassword())) {
                //1.1查询用户
                ApUser apUser = getOne(Wrappers.<ApUser>lambdaQuery().eq(ApUser::getPhone, dto.getPhone()));
                if (apUser == null) {
                    return ResponseResult.errorResult(AppHttpCodeEnum.DATA_NOT_EXIST,"用户不存在");
                }
    
                //1.2 比对密码
                String salt = apUser.getSalt();
                String pswd = dto.getPassword();
                pswd = DigestUtils.md5DigestAsHex((pswd + salt).getBytes());
                if (!pswd.equals(apUser.getPassword())) {
                    return ResponseResult.errorResult(AppHttpCodeEnum.LOGIN_PASSWORD_ERROR);
                }
                //1.3 返回数据  jwt
                Map<String, Object> map = new HashMap<>();
                map.put("token", AppJwtUtil.getToken(apUser.getId().longValue()));
                apUser.setSalt("");
                apUser.setPassword("");
                map.put("user", apUser);
                return ResponseResult.okResult(m"ap);
            } else {
                //2.游客  同样返回token  id = 0
                Map<String, Object> map = new HashMap<>();
                map.put("token", AppJwtUtil.getToken(0l));
                return ResponseResult.okResult(map);
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55

    ④:控制层controller

    package com.heima.user.controller.v1;
    
    import com.heima.model.common.dtos.ResponseResult;
    import com.heima.model.user.dtos.LoginDto;
    import com.heima.user.service.ApUserService;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.web.bind.annotation.PostMapping;
    import org.springframework.web.bind.annotation.RequestBody;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;
    
    @RestController
    @RequestMapping("/api/v1/login")
    public class ApUserLoginController {
    
        @Autowired
        private ApUserService apUserService;
    
        @PostMapping("/login_auth")
        public ResponseResult login(@RequestBody LoginDto dto) {
            return apUserService.login(dto);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    7)接口工具postman、swagger、knife4j

    7.1)postman

    7.2)swagger

    (1)简介

    Swagger 是一个规范和完整的框架,用于生成、描述、调用和可视化 RESTful 风格的 Web 服务(https://swagger.io/)。 它的主要作用是:

    1. 使得前后端分离开发更加方便,有利于团队协作

    2. 接口的文档在线自动生成,降低后端开发人员编写接口文档的负担

    3. 功能测试

      Spring已经将Swagger纳入自身的标准,建立了Spring-swagger项目,现在叫Springfox。通过在项目中引入Springfox ,即可非常简单快捷的使用Swagger。

    (2)SpringBoot集成Swagger

    • 引入依赖,在heima-leadnews-model和heima-leadnews-common模块中引入该依赖

      <dependency>
          <groupId>io.springfoxgroupId>
          <artifactId>springfox-swagger2artifactId>
      dependency>
      <dependency>
          <groupId>io.springfoxgroupId>
          <artifactId>springfox-swagger-uiartifactId>
      dependency>
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8

    只需要在heima-leadnews-common中进行配置即可,因为其他微服务工程都直接或间接依赖即可。

    • 在heima-leadnews-common工程中添加一个配置类

    新增:com.heima.common.swagger.SwaggerConfiguration

    package com.heima.common.swagger;
    
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    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;
    
    @Configuration
    @EnableSwagger2
    public class SwaggerConfiguration {
    
       @Bean
       public Docket buildDocket() {
          return new Docket(DocumentationType.SWAGGER_2)
                  .apiInfo(buildApiInfo())
                  .select()
                  // 要扫描的API(Controller)基础包
                  .apis(RequestHandlerSelectors.basePackage("com.heima"))
                  .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();
       }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37

    在heima-leadnews-common模块中的resources目录中新增以下目录和文件

    文件:resources/META-INF/Spring.factories

    org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
      com.heima.common.swagger.SwaggerConfiguration
    
    • 1
    • 2

    (3)Swagger常用注解

    在Java类中添加Swagger的注解即可生成Swagger接口文档,常用Swagger注解如下:

    @Api:修饰整个类,描述Controller的作用

    @ApiOperation:描述一个类的一个方法,或者说一个接口

    @ApiParam:单个参数的描述信息

    @ApiModel:用对象来接收参数

    @ApiModelProperty:用对象接收参数时,描述对象的一个字段

    @ApiResponse:HTTP响应其中1个描述

    @ApiResponses:HTTP响应整体描述

    @ApiIgnore:使用该注解忽略这个API

    @ApiError :发生错误返回的信息

    @ApiImplicitParam:一个请求参数

    @ApiImplicitParams:多个请求参数的描述信息

    @ApiImplicitParam属性:

    属性取值作用
    paramType查询参数类型
    path以地址的形式提交数据
    query直接跟参数完成自动映射赋值
    body以流的形式提交 仅支持POST
    header参数在request headers 里边提交
    form以form表单的形式提交 仅支持POST
    dataType参数的数据类型 只作为标志说明,并没有实际验证
    Long
    String
    name接收参数名
    value接收参数的意义描述
    required参数是否必填
    true必填
    false非必填
    defaultValue默认值

    我们在ApUserLoginController中添加Swagger注解,代码如下所示:

    @RestController
    @RequestMapping("/api/v1/login")
    @Api(value = "app端用户登录", tags = "ap_user", description = "app端用户登录API")
    public class ApUserLoginController {
    
        @Autowired
        private ApUserService apUserService;
    
        @PostMapping("/login_auth")
        @ApiOperation("用户登录")
        public ResponseResult login(@RequestBody LoginDto dto){
            return apUserService.login(dto);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    LoginDto

    @Data
    public class LoginDto {
    
        /**
         * 手机号
         */
        @ApiModelProperty(value="手机号",required = true)
        private String phone;
    
        /**
         * 密码
         */
        @ApiModelProperty(value="密码",required = true)
        private String password;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    启动user微服务,访问地址:http://localhost:51801/swagger-ui.html

    7.3)knife4j

    (1)简介

    knife4j是为Java MVC框架集成Swagger生成Api文档的增强解决方案,前身是swagger-bootstrap-ui,取名kni4j是希望它能像一把匕首一样小巧,轻量,并且功能强悍!

    gitee地址:https://gitee.com/xiaoym/knife4j

    官方文档:https://doc.xiaominfo.com/

    效果演示:http://knife4j.xiaominfo.com/doc.html

    (2)核心功能

    该UI增强包主要包括两大核心功能:文档说明 和 在线调试

    • 文档说明:根据Swagger的规范说明,详细列出接口文档的说明,包括接口地址、类型、请求示例、请求参数、响应示例、响应参数、响应码等信息,使用swagger-bootstrap-ui能根据该文档说明,对该接口的使用情况一目了然。
    • 在线调试:提供在线接口联调的强大功能,自动解析当前接口参数,同时包含表单验证,调用参数可返回接口响应内容、headers、Curl请求命令实例、响应时间、响应状态码等信息,帮助开发者在线调试,而不必通过其他测试工具测试接口是否正确,简介、强大。
    • 个性化配置:通过个性化ui配置项,可自定义UI的相关显示信息
    • 离线文档:根据标准规范,生成的在线markdown离线文档,开发者可以进行拷贝生成markdown接口文档,通过其他第三方markdown转换工具转换成html或pdf,这样也可以放弃swagger2markdown组件
    • 接口排序:自1.8.5后,ui支持了接口排序功能,例如一个注册功能主要包含了多个步骤,可以根据swagger-bootstrap-ui提供的接口排序规则实现接口的排序,step化接口操作,方便其他开发者进行接口对接

    (3)快速集成

    • 在heima-leadnews-common模块中的pom.xml文件中引入knife4j的依赖,如下:
    <dependency>
         <groupId>com.github.xiaoymingroupId>
         <artifactId>knife4j-spring-boot-starterartifactId>
    dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 创建Swagger配置文件

    在heima-leadnews-common模块中新建配置类

    新建Swagger的配置文件SwaggerConfiguration.java文件,创建springfox提供的Docket分组对象,代码如下:

    package com.heima.common.knife4j;
    
    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.spi.DocumentationType;
    import springfox.documentation.spring.web.plugins.Docket;
    import springfox.documentation.swagger2.annotations.EnableSwagger2;
    
    @Configuration
    @EnableSwagger2
    @EnableKnife4j
    @Import(BeanValidatorPluginsConfiguration.class)
    public class Swagger2Configuration {
    
        @Bean(value = "defaultApi2")
        public Docket defaultApi2() {
            Docket docket=new Docket(DocumentationType.SWAGGER_2)
                    .apiInfo(apiInfo())
                    //分组名称
                    .groupName("1.0")
                    .select()
                    //这里指定Controller扫描包路径
                    .apis(RequestHandlerSelectors.basePackage("com.heima"))
                    .paths(PathSelectors.any())
                    .build();
            return docket;
        }
        private ApiInfo apiInfo() {
            return new ApiInfoBuilder()
                    .title("黑马头条API文档")
                    .description("黑马头条API文档")
                    .version("1.0")
                    .build();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42

    以上有两个注解需要特别说明,如下表:

    注解说明
    @EnableSwagger2该注解是Springfox-swagger框架提供的使用Swagger注解,该注解必须加
    @EnableKnife4j该注解是knife4j提供的增强注解,Ui提供了例如动态参数、参数过滤、接口排序等增强功能,如果你想使用这些增强功能就必须加该注解,否则可以不用加
    • 添加配置

    在Spring.factories中新增配置

    org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
      com.heima.common.swagger.Swagger2Configuration, \
      com.heima.common.swagger.SwaggerConfiguration
    
    • 1
    • 2
    • 3
    • 访问

    在浏览器输入地址:http://host:port/doc.html

    8)网关

    (1)在heima-leadnews-gateway导入以下依赖

    pom文件

    <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>
         <dependency>
                <groupId>com.alibaba.cloudgroupId>
                <artifactId>spring-cloud-starter-alibaba-nacos-configartifactId>
            dependency>
        <dependency>
            <groupId>io.jsonwebtokengroupId>
            <artifactId>jjwtartifactId>
        dependency>
    dependencies>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    (2)在heima-leadnews-gateway下创建heima-leadnews-app-gateway微服务

    引导类:

    package com.heima.app.gateway;
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
    
    @SpringBootApplication
    @EnableDiscoveryClient  //开启注册中心
    public class AppGatewayApplication {
    
        public static void main(String[] args) {
            SpringApplication.run(AppGatewayApplication.class,args);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    bootstrap.yml

    server:
      port: 51601
    spring:
      application:
        name: leadnews-app-gateway
      cloud:
        nacos:
          discovery:
            server-addr: 192.168.200.130:8848
          config:
            server-addr: 192.168.200.130:8848
            file-extension: yml
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    在nacos的配置中心创建dataid为leadnews-app-gateway的yml配置

    spring:
      cloud:
        gateway:
          globalcors:
            add-to-simple-url-handler-mapping: true
            corsConfigurations:
              '[/**]':
                allowedHeaders: "*"
                allowedOrigins: "*"
                allowedMethods:
                  - GET
                  - POST
                  - DELETE
                  - PUT
                  - OPTION
          routes:
            # 平台管理
            - id: user
              uri: lb://leadnews-user
              predicates:
                - Path=/user/**
              filters:
                - StripPrefix= 1
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    环境搭建完成以后,启动项目网关和用户两个服务,使用postman进行测试

    请求地址:http://localhost:51601/user/api/v1/login/login_auth

    1.3 全局过滤器实现jwt校验在这里插入图片描述
    思路分析:

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

    具体实现:

    第一:

    ​ 在认证过滤器中需要用到jwt的解析,所以需要把工具类拷贝一份到网关微服务

    第二:

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

    package com.heima.app.gateway.filter;
    
    
    import com.heima.app.gateway.util.AppJwtUtil;
    import io.jsonwebtoken.Claims;
    import lombok.extern.slf4j.Slf4j;
    import org.apache.commons.lang.StringUtils;
    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.web.server.ServerWebExchange;
    import reactor.core.publisher.Mono;
    
    @Component
    @Slf4j
    public class AuthorizeFilter implements Ordered, GlobalFilter {
        @Override
        public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
            //1.获取request和response对象
            ServerHttpRequest request = exchange.getRequest();
            ServerHttpResponse response = exchange.getResponse();
    
            //2.判断是否是登录
            if(request.getURI().getPath().contains("/login")){
                //放行
                return chain.filter(exchange);
            }
    
    
            //3.获取token
            String token = request.getHeaders().getFirst("token");
    
            //4.判断token是否存在
            if(StringUtils.isBlank(token)){
                response.setStatusCode(HttpStatus.UNAUTHORIZED);
                return response.setComplete();
            }
    
            //5.判断token是否有效
            try {
                Claims claimsBody = AppJwtUtil.getClaimsBody(token);
                //是否是过期
                int result = AppJwtUtil.verifyToken(claimsBody);
                if(result == 1 || result  == 2){
                    response.setStatusCode(HttpStatus.UNAUTHORIZED);
                    return response.setComplete();
                }
            }catch (Exception e){
                e.printStackTrace();
                response.setStatusCode(HttpStatus.UNAUTHORIZED);
                return response.setComplete();
            }
    
            //6.放行
            return chain.filter(exchange);
        }
    
        /**
         * 优先级设置  值越小  优先级越高
         * @return
         */
        @Override
        public int getOrder() {
            return 0;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70

    测试:

    启动user服务,继续访问其他微服务,会提示需要认证才能访问,这个时候需要在heads中设置设置token才能正常访问。

    9)前端集成

    9.1)前端项目部署思路

    在这里插入图片描述
    通过nginx来进行配置,功能如下

    • 通过nginx的反向代理功能访问后台的网关资源
    • 通过nginx的静态服务器功能访问前端静态页面

    9.2)配置nginx

    ①:解压资料文件夹中的压缩包nginx-1.18.0.zip

    ②:解压资料文件夹中的前端项目app-web.zip

    ③:配置nginx.conf文件

    在nginx安装的conf目录下新建一个文件夹leadnews.conf,在当前文件夹中新建heima-leadnews-app.conf文件

    heima-leadnews-app.conf配置如下:

    upstream  heima-app-gateway{
        server localhost:51601;
    }
    
    server {
    	listen 8801;
    	location / {
    		root D:/workspace/app-web/;
    		index index.html;
    	}
    	
    	location ~/app/(.*) {
    		proxy_pass http://heima-app-gateway/$1;
    		proxy_set_header HOST $host;  # 不改变源请求头的值
    		proxy_pass_request_body on;  #开启获取请求体
    		proxy_pass_request_headers on;  #开启获取请求头
    		proxy_set_header X-Real-IP $remote_addr;   # 记录真实发出请求的客户端IP
    		proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;  #记录代理信息
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    nginx.conf 把里面注释的内容和静态资源配置相关删除,引入heima-leadnews-app.conf文件加载

    #user  nobody;
    worker_processes  1;
    
    events {
        worker_connections  1024;
    }
    http {
        include       mime.types;
        default_type  application/octet-stream;
        sendfile        on;
        keepalive_timeout  65;
    	# 引入自定义配置文件
    	include leadnews.conf/*.conf;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    ④ :启动nginx

    ​ 在nginx安装包中使用命令提示符打开,输入命令nginx启动项目

    ​ 可查看进程,检查nginx是否启动

    ​ 重新加载配置文件:nginx -s reload

    ⑤:打开前端项目进行测试 – > http://localhost:8801

  • 相关阅读:
    CoinGecko 播客:与 Cartesi 联合创始人 Erick 一起构建 Layer-2
    技巧篇:Mac 环境PyCharm 配置 python Anaconda
    17.4、JavaWeb-HTML、W3C、基本标签、html的各种标签
    RT-Thread 项目工程搭建和配置--(Env Kconfig)
    为vscode配置clangd
    java计算机毕业设计苗木购销系统源码+系统+mysql数据库+lw文档
    Python编程学习:深度剖析shap.datasets.adult()源码中的X,y和X_display,y_display输出数区别
    Editplus同步阅览两个文件
    批量插入【对新数据进行插入操作,已存在的记录进行更新操作】
    S3E:用于协作SLAM的大规模多模态数据集
  • 原文地址:https://blog.csdn.net/qq_59708493/article/details/133917477