SpringCloud微服务项目实战 - 2.App登录及网关

news2024/10/6 22:26:51

如果你追求一个局部的更好甚至完美,你有可能花费巨大的资源和时间;
从总体上看,这往往意味着总体的浪费和失败,这是传说中的“打赢了战役打输了战争”。

在这里插入图片描述



系列文章目录

  1. 项目搭建
  2. App登录及网关

文章目录

  • 系列文章目录
  • 一、App登录
    • 1. 需求分析
    • 2. 表结构分析
      • ⑴. 导入数据库
      • ⑵. 库表
      • ⑶. 用户表(登录)
      • ⑷. 实体类
    • 3. 手动加密(md5+随机字符串)
    • 4. 运营端微服务搭建
      • ⑴. 创建模块
      • ⑵. 引导类
      • ⑶. 微服务配置文件
      • ⑷. 日志配置文件
      • ⑸. Nacos配置文件
      • ⑹. 微服务标准包结构
    • 5. 接口定义
      • ⑴. 接口返回类分析
        • ①. HttpCode枚举
        • ②. 通用的结果返回类
        • ③. 上面的返回类测试
        • ④. 分页返回类
      • ⑵. 实体类
      • ⑶. Controller
      • ⑷. Mapper
      • ⑸. service
      • ⑹. 实现类Impl
      • ⑺. Controller
  • 二、接口测试工具
    • 1. Postman
    • 2. Swagger
      • ⑴. 配置
        • ①. 引入依赖
        • ②. 配置类
        • ③. 自动配置
      • ⑵. 注解
        • ①. 常用注解
        • ②. 接口注解
        • ③. 参数注解
        • ④. 在线API文档
    • 3. Knife4j
      • ⑴. 配置
        • ①. 引入依赖
        • ②. 配置类
        • ③. 自动配置
      • ⑵. 文档(可下载离线文档)
  • 三、App网关
    • 1. gateway网关微服务
      • ⑴. 服务工程结构
      • ⑵. 配置
        • ①. 导入依赖
        • ②. 引导类
        • ③. 配置文件
        • ④. nacos配置
      • ⑶. 测试
    • 2. 认证过滤器
      • ⑴. 思路分析
      • ⑵. 全局过滤器
      • ⑶. 断点调试
  • 四、App前端项目集成
    • 1. nginx包
    • 2. 前端项目
    • 3. 配置nginx.conf文件1
    • 4. 配置nginx.conf文件2
    • 5. 重新加载nginx
    • 6. 运行测试


一、App登录

1. 需求分析

在这里插入图片描述

  • 登录: 登录后的用户权限较大,可以查看,也可以操作(点赞,关注,评论)
  • 不登录,先看看: 游客只有查看的权限

2. 表结构分析

⑴. 导入数据库

sql文件链接:https://pan.baidu.com/s/11ITsQZQkR0Yl20lT10omwQ?pwd=abcd

在这里插入图片描述

⑵. 库表

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

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

⑶. 用户表(登录)

登录需要用到的是 ap_user 表,表结构如下:
在这里插入图片描述

DDL文件:

CREATE TABLE `ap_user` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',
  `salt` varchar(32) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '密码、通信等加密盐',
  `name` varchar(20) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '用户名',
  `password` varchar(32) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '密码,md5加密',
  `phone` varchar(11) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '手机号',
  `image` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '头像',
  `sex` tinyint(1) unsigned DEFAULT NULL COMMENT '0 男\r\n            1 女\r\n            2 未知',
  `is_certification` tinyint(1) unsigned DEFAULT NULL COMMENT '0 未\r\n            1 是',
  `is_identity_authentication` tinyint(1) DEFAULT NULL COMMENT '是否身份认证',
  `status` tinyint(1) unsigned DEFAULT NULL COMMENT '0正常\r\n            1锁定',
  `flag` tinyint(1) unsigned DEFAULT NULL COMMENT '0 普通用户\r\n            1 自媒体人\r\n            2 大V',
  `created_time` datetime DEFAULT NULL COMMENT '注册时间',
  PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci ROW_FORMAT=DYNAMIC COMMENT='APP用户信息表';

tinyint类型: 占1个字节,不指定unsigned(非负数),值范围(-128,127),指定了unsigned,值范围(0,255)
tinyint 通常表示小范围的数值,或者表示true或false,通常值为0表示false,值为1表示true


⑷. 实体类

新建 src/main/java/com/heima/model/user/pojos/ApUser.java 文件(app_user表对应的实体类):

/**
 * <p>
 * APP用户信息表
 * </p>
 *
 * @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;

}

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

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

注册(生成盐)
在这里插入图片描述

登录(使用盐来配合验证)
在这里插入图片描述


4. 运营端微服务搭建

⑴. 创建模块

在这里插入图片描述

⑵. 引导类

新建 src/main/java/com/heima/user/UserApplication.java 文件:

@SpringBootApplication
@EnableDiscoveryClient // 集成当前的注册中心
@MapperScan("com.heima.user.mapper") // 集成myBatisPlus 扫描mapper
public class UserApplication {
    public static void main(String[] args) {
        SpringApplication.run(UserApplication.class,args);
    }
}

⑶. 微服务配置文件

新建 heima-leadnews-service/heima-leadnews-user/src/main/resources/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

⑷. 日志配置文件

新建 heima-leadnews-service/heima-leadnews-user/src/main/resources/logback.xml 文件:

<?xml version="1.0" encoding="UTF-8"?>

<configuration>
    <!--定义日志文件的存储地址,使用绝对路径-->
    <property name="LOG_HOME" value="e:/logs"/>

    <!-- Console 输出设置 -->
    <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符-->
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
            <charset>utf8</charset>
        </encoder>
    </appender>

    <!-- 按照每天生成日志文件 -->
    <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <!--日志文件输出的文件名-->
            <fileNamePattern>${LOG_HOME}/leadnews.%d{yyyy-MM-dd}.log</fileNamePattern>
        </rollingPolicy>
        <encoder>
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
        </encoder>
    </appender>

    <!-- 异步输出 -->
    <appender name="ASYNC" class="ch.qos.logback.classic.AsyncAppender">
        <!-- 不丢失日志.默认的,如果队列的80%已满,则会丢弃TRACT、DEBUG、INFO级别的日志 -->
        <discardingThreshold>0</discardingThreshold>
        <!-- 更改默认的队列的深度,该值会影响性能.默认值为256 -->
        <queueSize>512</queueSize>
        <!-- 添加附加的appender,最多只能添加一个 -->
        <appender-ref ref="FILE"/>
    </appender>


    <logger name="org.apache.ibatis.cache.decorators.LoggingCache" level="DEBUG" additivity="false">
        <appender-ref ref="CONSOLE"/>
    </logger>
    <logger name="org.springframework.boot" level="debug"/>
    <root level="info">
        <!--<appender-ref ref="ASYNC"/>-->
        <appender-ref ref="FILE"/>
        <appender-ref ref="CONSOLE"/>
    </root>
</configuration>

⑸. Nacos配置文件

在这里插入图片描述

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

⑹. 微服务标准包结构

在这里插入图片描述


5. 接口定义

在这里插入图片描述

⑴. 接口返回类分析

①. HttpCode枚举

查看 com/heima/model/common/enums/AppHttpCodeEnum.java 文件:

public enum AppHttpCodeEnum {

    // 成功段固定为200
    SUCCESS(200,"操作成功"),
    // 登录段1~50
    NEED_LOGIN(1,"需要登录后操作"),
    LOGIN_PASSWORD_ERROR(2,"密码错误"),
    // TOKEN50~100
    TOKEN_INVALID(50,"无效的TOKEN"),
    TOKEN_EXPIRE(51,"TOKEN已过期"),
    TOKEN_REQUIRE(52,"TOKEN是必须的"),
    // SIGN验签 100~120
    SIGN_INVALID(100,"无效的SIGN"),
    SIG_TIMEOUT(101,"SIGN已过期"),
    // 参数错误 500~1000
    PARAM_REQUIRE(500,"缺少参数"),
    PARAM_INVALID(501,"无效参数"),
    PARAM_IMAGE_FORMAT_ERROR(502,"图片格式有误"),
    SERVER_ERROR(503,"服务器内部错误"),
    // 数据错误 1000~2000
    DATA_EXIST(1000,"数据已经存在"),
    AP_USER_DATA_NOT_EXIST(1001,"ApUser数据不存在"),
    DATA_NOT_EXIST(1002,"数据不存在"),
    // 数据错误 3000~3500
    NO_OPERATOR_AUTH(3000,"无权限操作"),
    NEED_ADMIND(3001,"需要管理员权限");

    int code;
    String errorMessage;

    AppHttpCodeEnum(int code, String errorMessage){
        this.code = code;
        this.errorMessage = errorMessage;
    }

    public int getCode() {
        return code;
    }

    public String getErrorMessage() {
        return errorMessage;
    }
}

②. 通用的结果返回类

查看 com/heima/model/common/dtos/PageResponseResult.java 文件:

/**
 * 通用的结果返回类
 * @param <T>
 */
public class ResponseResult<T> implements Serializable {

    private String host;

    private Integer code;

    private String errorMessage;

    private T data;

    public ResponseResult() {
        this.code = 200;
    }

    public ResponseResult(Integer code, T data) {
        this.code = code;
        this.data = data;
    }

    public ResponseResult(Integer code, String msg, T data) {
        this.code = code;
        this.errorMessage = msg;
        this.data = data;
    }

    public ResponseResult(Integer code, String msg) {
        this.code = code;
        this.errorMessage = msg;
    }

    public static ResponseResult errorResult(int code, String msg) {
        ResponseResult result = new ResponseResult();
        return result.error(code, msg);
    }

    public static ResponseResult okResult(int code, String msg) {
        ResponseResult result = new ResponseResult();
        return result.ok(code, null, msg);
    }

    public static ResponseResult okResult(Object data) {
        ResponseResult result = setAppHttpCodeEnum(AppHttpCodeEnum.SUCCESS, AppHttpCodeEnum.SUCCESS.getErrorMessage());
        if(data!=null) {
            result.setData(data);
        }
        return result;
    }

    public static ResponseResult errorResult(AppHttpCodeEnum enums){
        return setAppHttpCodeEnum(enums,enums.getErrorMessage());
    }

    public static ResponseResult errorResult(AppHttpCodeEnum enums, String errorMessage){
        return setAppHttpCodeEnum(enums,errorMessage);
    }

    public static ResponseResult setAppHttpCodeEnum(AppHttpCodeEnum enums){
        return okResult(enums.getCode(),enums.getErrorMessage());
    }

    private static ResponseResult setAppHttpCodeEnum(AppHttpCodeEnum enums, String errorMessage){
        return okResult(enums.getCode(),errorMessage);
    }

    public ResponseResult<?> error(Integer code, String msg) {
        this.code = code;
        this.errorMessage = msg;
        return this;
    }

    public ResponseResult<?> ok(Integer code, T data) {
        this.code = code;
        this.data = data;
        return this;
    }

    public ResponseResult<?> ok(Integer code, T data, String msg) {
        this.code = code;
        this.data = data;
        this.errorMessage = msg;
        return this;
    }

    public ResponseResult<?> ok(T data) {
        this.data = data;
        return this;
    }

    public Integer getCode() {
        return code;
    }

    public void setCode(Integer code) {
        this.code = code;
    }

    public String getErrorMessage() {
        return errorMessage;
    }

    public void setErrorMessage(String errorMessage) {
        this.errorMessage = errorMessage;
    }

    public T getData() {
        return data;
    }

    public void setData(T data) {
        this.data = data;
    }

    public String getHost() {
        return host;
    }

    public void setHost(String host) {
        this.host = host;
    }

    // 测试类
    public static void main(String[] args) {
        //前置
       /* AppHttpCodeEnum success = AppHttpCodeEnum.SUCCESS;
        System.out.println(success.getCode());
        System.out.println(success.getErrorMessage());*/

        //查询一个对象
        /*Map map = new HashMap();
        map.put("name","zhangsan");
        map.put("age",18);
        ResponseResult result = ResponseResult.okResult(map);
        System.out.println(JSON.toJSONString(result));*/


        //新增,修改,删除  在项目中统一返回成功即可
        /*ResponseResult result = ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
        System.out.println(JSON.toJSONString(result));*/


        //根据不用的业务返回不同的提示信息  比如:当前操作需要登录、参数错误
        /*ResponseResult result = ResponseResult.errorResult(AppHttpCodeEnum.NEED_LOGIN,"自定义提示信息");
        System.out.println(JSON.toJSONString(result));*/

        //查询分页信息
        PageResponseResult responseResult = new PageResponseResult(1,5,50);
        List list = new ArrayList();
        list.add("itcast");
        list.add("itheima");
        responseResult.setData(list);
        System.out.println(JSON.toJSONString(responseResult));

    }

}

③. 上面的返回类测试

在这里插入图片描述

④. 分页返回类

查看 com/heima/model/common/dtos/PageResponseResult.java 文件:

public class PageResponseResult extends ResponseResult implements Serializable {
    private Integer currentPage;
    private Integer size;
    private Integer total;

    public PageResponseResult(Integer currentPage, Integer size, Integer total) {
        this.currentPage = currentPage;
        this.size = size;
        this.total = total;
    }

    public PageResponseResult() {

    }


    public int getCurrentPage() {
        return currentPage;
    }

    public void setCurrentPage(int currentPage) {
        this.currentPage = currentPage;
    }

    public int getSize() {
        return size;
    }

    public void setSize(int size) {
        this.size = size;
    }

    public int getTotal() {
        return total;
    }

    public void setTotal(int total) {
        this.total = total;
    }
}

⑵. 实体类

新建 heima-leadnews-model/src/main/java/com/heima/model/user/dtos/LoginDto.java 文件:

@Data
public class LoginDto {

    /**
     * 手机号
     */
    @ApiModelProperty(value = "手机号",required = true)
    private String phone;

    /**
     * 密码
     */
    @ApiModelProperty(value = "密码",required = true)
    private String password;
}

⑶. Controller

新建 heima-leadnews-service/heima-leadnews-user/src/main/java/com/heima/user/controller/v1/ApUserLoginController.java 文件:

@RestController
@RequestMapping("/api/v1/login")
public class ApUserLoginController {

    @PostMapping("/login_auth")
    public ResponseResult login(@RequestBody LoginDto dto) {
        return null;
    }
}

⑷. Mapper

新建 heima-leadnews-service/heima-leadnews-user/src/main/java/com/heima/user/mapper/ApUserMapper.java 文件:

@Mapper
public interface ApUserMapper extends BaseMapper<ApUser> {
}

⑸. service

新建 heima-leadnews-service/heima-leadnews-user/src/main/java/com/heima/user/service/ApUserService.java 文件:

public interface ApUserService extends IService<ApUser>{

    /**
     * app端登录
     * @param dto
     * @return
     */
    public ResponseResult login(LoginDto dto);
    
}

⑹. 实现类Impl

  • 用户输入了用户名和密码进行登录,校验成功后返回jwt(基于当前用户的id生成)
  • 用户游客登录,生成jwt返回(基于默认值0生成)

新建 heima-leadnews-service/heima-leadnews-user/src/main/java/com/heima/user/service/impl/ApUserServiceImpl.java 文件:

@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(map);
        } else {
            //2.游客  同样返回token  id = 0
            Map<String, Object> map = new HashMap<>();
            map.put("token", AppJwtUtil.getToken(0l));
            return ResponseResult.okResult(map);
        }
    }
}

⑺. Controller

编辑 heima-leadnews-service/heima-leadnews-user/src/main/java/com/heima/user/controller/v1/ApUserLoginController.java 文件:

@RestController
@RequestMapping("/api/v1/login")
@Api(value = "app端用户登录",tags = "app端用户登录")
public class ApUserLoginController {

    @Autowired
    private ApUserService apUserService;

    @PostMapping("/login_auth")
    @ApiOperation("用户登录")
    public ResponseResult login(@RequestBody LoginDto dto){
        return apUserService.login(dto);
    }
}




二、接口测试工具

1. Postman

测试 账号错误密码错误游客登录用户登录 返回信息是否正确
在这里插入图片描述

2. Swagger

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

⑴. 配置

①. 引入依赖

heima-leadnews-modelheima-leadnews-common 模块中引入该依赖

  <dependency>
      <groupId>io.springfox</groupId>
      <artifactId>springfox-swagger2</artifactId>
  </dependency>
  <dependency>
      <groupId>io.springfox</groupId>
      <artifactId>springfox-swagger-ui</artifactId>
  </dependency>

②. 配置类

新建 heima-leadnews-common/src/main/java/com/heima/common/swagger/SwaggerConfiguration.java 文件:

@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();
   }
}

③. 自动配置

编辑 heima-leadnews-common/src/main/resources/META-INF/spring.factories 文件:

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
  com.heima.common.exception.ExceptionCatch,\
  com.heima.common.swagger.SwaggerConfiguration

⑵. 注解

①. 常用注解

在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默认值

②. 接口注解

编辑 heima-leadnews-service/heima-leadnews-user/src/main/java/com/heima/user/controller/v1/ApUserLoginController.java 文件:

@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);
    }
}

③. 参数注解

编辑 heima-leadnews-model/src/main/java/com/heima/model/user/dtos/LoginDto.java 文件:

@Data
public class LoginDto {

    /**
     * 手机号
     */
    @ApiModelProperty(value="手机号",required = true)
    private String phone;

    /**
     * 密码
     */
    @ApiModelProperty(value="密码",required = true)
    private String password;
}

④. 在线API文档

启动user微服务,访问地址:http://localhost:51801/swagger-ui.html
在这里插入图片描述

3. Knife4j

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

⑴. 配置

①. 引入依赖

编辑 heima-leadnews-common/pom.xml 文件:

        <!--knife4j接口文档-->
        <dependency>
            <groupId>com.github.xiaoymin</groupId>
            <artifactId>knife4j-spring-boot-starter</artifactId>
        </dependency>

②. 配置类

新建 heima-leadnews-common/src/main/java/com/heima/common/swagger/Swagger2Configuration.java 文件:

@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();
    }
}

以上有两个注解需要特别说明:

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

③. 自动配置

编辑 heima-leadnews-common/src/main/resources/META-INF/spring.factories 文件:

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
  com.heima.common.exception.ExceptionCatch,\
  com.heima.common.swagger.SwaggerConfiguration,\
  com.heima.common.swagger.Swagger2Configuration

⑵. 文档(可下载离线文档)

接口文档: http://localhost:51801/doc.htm
在这里插入图片描述




三、App网关

1. gateway网关微服务

⑴. 服务工程结构

  • heima-leadnews-gateway 网关
    • heima-leadnews-admin-gateway 管理平台
    • heima-leadnews-wemedia-gateway 用户自媒体平台
    • heima-leadnews-app-gateway 用户移动APP

⑵. 配置

①. 导入依赖

新建 heima-leadnews-gateway/pom.xml 文件:

    <dependencies>
        <!--gateway的staeter-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-gateway</artifactId>
        </dependency>
        <!--nacos的注册中心-->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>
        <!--nacos的配置中心-->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
        </dependency>
        <!--jwt解析jar包-->
        <dependency>
            <groupId>io.jsonwebtoken</groupId>
            <artifactId>jjwt</artifactId>
        </dependency>
    </dependencies>

②. 引导类

新建 heima-leadnews-gateway/heima-leadnews-app-gateway/src/main/java/com/heima/app/gateway/AppGatewayApplication.java 文件:

@SpringBootApplication
@EnableDiscoveryClient  //开启注册中心
public class AppGatewayApplication {

    public static void main(String[] args) {
        SpringApplication.run(AppGatewayApplication.class,args);
    }
}

③. 配置文件

编辑 heima-leadnews-gateway/heima-leadnews-app-gateway/src/main/resources/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

④. nacos配置

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

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

⑶. 测试

启动项目网关和用户两个服务,使用postman进行测试

网关后的请求地址: localhost:51601/user/api/v1/login/login_auth
#### ①. 导入依赖



2. 认证过滤器

⑴. 思路分析

在这里插入图片描述

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

⑵. 全局过滤器

新建 heima-leadnews-gateway/heima-leadnews-app-gateway/src/main/java/com/heima/app/gateway/filter/AuthorizeFilter.java 文件:

@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;
    }
}

⑶. 断点调试

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

在这里插入图片描述




四、App前端项目集成

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

1. nginx包

资源链接: https://pan.baidu.com/s/1gPfoG0FnLC3dIUjJhqlKSQ?pwd=abcd

在这里插入图片描述
解压包,运行nginx

2. 前端项目

资源链接: https://pan.baidu.com/s/1wqfxtQCj_aGqSZVxgADVTQ?pwd=abcd
在这里插入图片描述
解压包,记住前端项目存放路径


3. 配置nginx.conf文件1

(nginx包中)新建 D:\code\hm\leadnews\config\nginx-1.18.0\conf\leadnews.conf\heima-leadnews-app.conf 文件:

upstream  heima-app-gateway{
    server localhost:51601; # 根据网关去做的请求
}

server {
	listen 8801;
	location / {
		root D:/code/hm/leadnews/config/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;  #记录代理信息
	}
}

4. 配置nginx.conf文件2

(nginx包中)编辑 D:\code\hm\leadnews\config\nginx-1.18.0\conf\leadnews.conf\nginx.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;
}

5. 重新加载nginx

# 重新加载nginx
nginx -s reload

在这里插入图片描述


6. 运行测试

前端地址: http://localhost:8801/
在这里插入图片描述



本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/124053.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

2020-2021 ICPC, NERC, Southern and Volga Russian Regional Contest K. The Robot

翻译&#xff1a; 有一个机器人在一个没有尽头的方格场上。最初&#xff0c;机器人位于坐标为(0,0)的单元中。他将执行由一串大写拉丁字母“L”、“R”、“D”、“U”所描述的命令。当一个命令被执行时&#xff0c;机器人只是朝着相应的方向移动: “L”:向左一个单元格(当前单…

【聆思CSK6 视觉AI开发套件试用】AI控制直流电机转速接口打通

本篇文章来自极术社区与聆思科技组织的CSK6 视觉AI开发套件活动&#xff0c;更多开发板试用活动请关注极术社区网站。作者&#xff1a;oxlm 背景 在访问极术社区时&#xff0c;偶然发现聆思科技的CSK6开发板的评估活动&#xff0c;看CSK6的硬件配置和技术规格&#xff0c;300M…

JavaScript奇淫技巧:变速齿轮

JavaScript奇淫技巧&#xff1a;变速齿轮 在PC时代&#xff0c;曾有个名为“变速齿轮”的神奇软件&#xff0c;可以加快或减慢系统时间。 当时常用来修改游戏速度&#xff0c;可实现外挂一般的效果&#xff0c;很不可思议。 本文&#xff0c;将用JavaScript复刻这一功能&…

maven在无互联网(内网)环境下打包

Maven在内网环境打包 首先需要准备好项目所需的所有依赖包 我们可以在外网环境下&#xff0c;更改idea中Maven的local repository目录&#xff0c;然后刷新一下项目&#xff0c;将项目所需的依赖下载到更换的目录下 将新建的依赖目录和项目一起拷贝到内网环境下将依赖文件拷贝…

带你学懂数据结构中的八大排序(下)

✨个人主页&#xff1a; Yohifo &#x1f389;所属专栏&#xff1a; 数据结构 | C语言 &#x1f38a;每篇一句&#xff1a; 图片来源 You can avoid reality, but you cannot avoid the consequences of avoiding reality. 你可以逃避现实&#xff0c;但你无法逃避其带来的后果…

《图解TCP/IP》阅读笔记(第八章 8.1~8.4)—— 概要,TELNET、FTP、SMTP、POP、IMAP协议介绍

前言 本篇篇幅较长&#xff0c;请耐心或者选择性阅读。 第八章 应用协议 从本篇开始&#xff0c;将介绍一些应用层协议&#xff0c;一般情况下&#xff0c;人们不太会在意网络应用程序实际上是按照何种机制正常运行的。本章旨在介绍TCP/IP中所使用的几个主要应用协议&#x…

项目管理中,培养高效项目团队的6大优势

大多数项目经理知道合作会促进生产力&#xff0c;并且对不同的团队都很有效。良好的团队合作使你能够顺利地运行不同的项目&#xff0c;克服障碍并实现目标。 它也会使完成项目所需的时间减少&#xff0c;并使资源得到更好的管理。更不用说&#xff0c;高质量的团队合作将有助…

第十四讲:神州交换机链路聚合配置

链路聚合&#xff08;Link Aggregation&#xff09;又称Trunk&#xff0c;是指将多个物理端口捆绑在一起&#xff0c;成 为一个逻辑端口&#xff0c;以实现出/入流量在各成员端口中的负荷分担&#xff0c;交换机根据用户配置的端口负荷分担策略决定报文从哪一个成员端口发送到对…

如何快速理解Python中的for循环?

人生苦短&#xff0c;我用python 这次来给大家带来一点干货&#xff0c; 我们将从一组基本例子和它的语法开始&#xff0c; 还将讨论与 for 循环关联的 else 代码块的用处。 然后我们将介绍迭代对象、迭代器和迭代器协议&#xff0c; 还会学习如何创建自己的迭代对象和迭代器…

微信小程序云开发之用户输入数据后excel表格导出升级版

大家好&#xff0c;我是csdn的小博主lqj_本人&#xff0c;最近在哔哩哔哩开始上传我的制作微信小程序的详细流程&#xff0c;大家可以关注一下哔哩哔哩&#xff1a;小淼前端 本次程序的详细视频教程已上传至哔哩哔哩&#xff1a; 腾讯云开发小程序之用户输入数据excel自动导出系…

HaaS EDU物联网项目实战:微信小程序实现云养花

HaaS EDU K1是一款高颜值、高性能、高集成度的物联网开发板&#xff0c;板载功能强大的4核&#xff08;双核300Mhz M33双核1GHz A7&#xff09;主芯片&#xff0c;2.4G/5G双频Wi-Fi&#xff0c;双模蓝牙&#xff08;经典蓝牙/BLE&#xff09;&#xff0c;并自带丰富的传感器与小…

第一章 vscode安装java环境

要在Visual Studio Code中配置Java环境&#xff0c;需要完成以下步骤&#xff1a; 安装Java Development Kit (JDK)。首先&#xff0c;你需要安装Java Development Kit (JDK)&#xff0c;这是Java的开发环境&#xff0c;包含了Java虚拟机、Java编译器和Java库等。可以前往Oracl…

Python基础知识入门(五)

Python基础知识入门&#xff08;一&#xff09; Python基础知识入门&#xff08;二&#xff09; Python基础知识入门&#xff08;三&#xff09; Python基础知识入门&#xff08;四&#xff09; 一、模块应用 模块是一个包含所有定义的函数和变量的文件&#xff0c;其后缀名…

2022年「博客之星」参赛博主:(天寒雨落)在等您评价 ~

目录 评价方法 参与规则 评选规则 评分规则 活动奖品 评价方法 点击链接&#xff1a;2022年「博客之星」参赛博主&#xff1a;天寒雨落-CSDN社区 在箭头所指位置做出打星评价。 参与规则 1.本次年度评选分为「博客之星|和「博客新星:以及「社区之星|。「博客新星:只针对…

Kafka — 1、基础介绍

1、消息队列简介 &#xff08;1&#xff09;同步&#xff1a;多个服务之间是同步完成一次请求 缺点&#xff1a; a. 性能比较差 b. 稳定性比较差&#xff0c;如果其中一个服务没有执行成功&#xff0c;则整个请求执行失败 &#xff08;2&#xff09;异步&#xff1a;加入【消息…

自动控制原理笔记-线性系统的稳态误差

目录 1.误差与稳态误差 2.计算稳态误差的一般方法 3.静态误差系数法 例题&#xff1a; 稳态误差是系统的稳态性能指标&#xff0c;是系统控制精度的度量。 这里讨论的只是系统的原理性误差&#xff0c;不包括非线性等因素所造成的附加误差。 计算系统的稳态误差以系统稳定…

洛谷千题详解 | P1029 [NOIP2001 普及组] 最大公约数和最小公倍数问题【C++语言】

博主主页&#xff1a;Yu仙笙 专栏地址&#xff1a;洛谷千题详解 目录 题目描述 输入格式 输出格式 输入输出样例 解析&#xff1a; C源码&#xff1a; C源码2&#xff1a; C源码3&#xff1a; ------------------------------------------------------------------------------…

2022博客之星年度总评选开始了

作者简介&#xff1a;陶然同学 专注于Java领域开发 熟练掌握Java、js等语言的“Hello World” CSDN原力计划作者、CSDN内容合伙人、Java领域优质作者、Java领域新星作者、51CTO专家、华为云专家、阿里云专家等 &#x1f3ac; 陶然同学&#x1f3a5; 由 陶然同学 原创&#…

Linux之SQL Server数据库安装

一、SQL Server简介 SQL Server 是一个关系数据库管理系统。它最初是由Microsoft Sybase 和Ashton-Tate三家公司共同开发的&#xff0c;于1988 年推出了第一个OS/2 版本。在Windows NT 推出后&#xff0c;Microsoft与Sybase 在SQL Server 的开发上就分道扬镳了&#xff0c;Micr…

密码学 公开密钥管理

PKU概念 Public Key Infrastructure PKI一般指公钥基础设施。 公钥基础设施是一个包括硬件、软件、人员、策略和规程的集合&#xff0c;用来实现基于公钥密码体制的密钥和证书的产生、管理、存储、分发和撤销等功能。 基于PKI的信任模型 如果一个个体假设CA 能够建立并维持一…