黑马头条-环境搭建、SpringCloud

news2024/12/22 22:41:53

一、项目介绍

1. 项目背景介绍

项目概述

类似于今日头条,是一个新闻资讯类项目。

随着智能手机的普及,人们更加习惯于通过手机来看新闻。由于生活节奏的加快,很多人只能利用碎片时间来获取信息,因此,对于移动资讯客户端的需求也越来越高。黑马头条项目正是在这样背景下开发出来。黑马头条项目采用当下火热的微服务+大数据技术架构实现。本项目主要着手于获取最新最热新闻资讯,通过大数据分析用户喜好精确推送咨询新闻。

业务说明

项目术语

2. 技术栈说明

基础层

服务层

3. 课程概述

收获

项目课程大纲

二、nacos

1. 服务器环境准备

前提条件:安装VWware

①解压课前资料提供的虚拟机镜像,放到你喜欢的位置

②打开VWware,点击“打开虚拟机”,选择CentosOS7-hmtt.vmx文件

③修改虚拟网络配置,子网IP改为192.168.200.0

④修改系统的网络适配器

⑤开启虚拟机,使用MobaXterm连接虚拟机

用户名:root  密码:itcast

2. nacos安装

①docker拉取镜像

docker pull nacos/nacos-server:1.2.0

②创建容器

docker run --env MODE=standalone --name nacos --restart=always -d -p 8848:8848 nacos/nacos-server:1.2.0
  • MODE=standalone:单机版
  • --restart=always:开机启动
  • -p 8848:8848:映射端口
  • -d:创建一个守护式容器在后台运行

③访问地址:http://192.168.200.130:8848/nacos

三、初始工程搭建

1. 环境准备

项目依赖环境:

  • JDK 1.8
  • Intellij Idea
  • maven-3.6.1
  • Git

步骤:

①把课前资料的heima-leadnews.zip拷贝解压到一个不带空格和中文的目录下,使用idea打开

如果识别不出来是SpringBoot工程,打开一个pom.xml文件,右键 > add as maven project

②把pom.xml里报错的信息改成如下

③把Encoding改为UTF-8

④修改maven仓库为课前资料里提供的MAVEN仓库

2. 项目结构

common模块:主要定义了一些全局异常类

feign-api模块:主要定义了远程调用接口

gateway模块:管理网关微服务

model模块:实体类

service模块:微服务工程

test模块:项目中常用的测试

utils模块:项目中常用的工具类

四、登录

1. 需求分析

用户点击开始使用:登录后的用户权限较大,可以查看,也可以操作(点赞、关注、评论)

用户点击不登录,先看看:游客只有查看的权限

2. 表结构分析

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

①启动MySQL服务,连接数据库,执行课前资料里提供的SQL脚本

②user表(放到model包下的user.pojos包)

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;

/**
 * <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;

}

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

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

3. app登录

①在service模块下新建如下

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

在nacos中创建配置文件 leadnews-user(注意修改数据库连接密码)

spring:
  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

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>

②接口定义

③新增LoginDto

package com.heima.model.user.dtos;

import lombok.Data;

@Data
public class LoginDto {
    /**
     * 手机号
     */
    private String phone;

    /**
     * 密码
     */
    private String password;
}

④思路分析

⑤实现

UserApplication

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

ApUserMapper

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> {
}

ApUserService

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

ApUserServiceImpl

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 lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.DigestUtils;

import java.util.HashMap;
import java.util.Map;

@Service
@Transactional
@Slf4j
public class ApUserServiceImpl extends ServiceImpl<ApUserMapper, ApUser> implements ApUserService {
    /**
     * app登录功能
     * @param dto
     * @return
     */
    @Override
    public ResponseResult login(LoginDto dto) {
        // 1. 正常登录 用户名和密码
        if(StringUtils.isNotBlank(dto.getPhone()) && StringUtils.isNotBlank(dto.getPassword())) {
            // 1.1 根据手机号查询用户信息
            ApUser dbUser = getOne(Wrappers.<ApUser>lambdaQuery().eq(ApUser::getPhone, dto.getPhone()));
            if(dbUser == null) {
                return ResponseResult.errorResult(AppHttpCodeEnum.DATA_NOT_EXIST, "用户信息不存在");
            }

            // 1.2 对比密码
            String salt = dbUser.getSalt();
            String password = dto.getPassword();
            String paswd = DigestUtils.md5DigestAsHex((password + salt).getBytes());
            if(!paswd.equals(dbUser.getPassword())) {
                return ResponseResult.errorResult(AppHttpCodeEnum.LOGIN_PASSWORD_ERROR);
            }

            // 1.3 返回数据 jwt
            String token = AppJwtUtil.getToken(dbUser.getId().longValue());
            Map<String, Object> map = new HashMap<>();
            map.put("token", token);
            dbUser.setSalt("");
            dbUser.setPassword("");
            map.put("user", dbUser);

            return ResponseResult.okResult(map);
        } else {
            // 2. 游客登录
            Map<String, Object> map = new HashMap<>();
            map.put("token", AppJwtUtil.getToken(0L));
            return ResponseResult.okResult(map);
        }
    }
}

ApUserLoginController

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

五、接口工具postman、swagger、knife4j

1. 接口工具-postman

Postman是一款功能强大的网页调试与发送网页HTTP请求的Chrome插件。Postman被500万开发者和超过100,000家公司用于每月访问1.3亿个API。

官网:https://www.postman.com/

登录请求的测试:http://localhost:51801/api/v1/login/login_auth

{
    "phone": "13511223456",
    "password": "admin"
}

2. 接口工具-Swagger

前后端分离开发

项目基于前后端分离的架构进行开发,前后端分离架构总体上包括前端和服务端,通常是多人协作开发。

(1)简介

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

  • 使得前后端分离开发更加方便,有利于团队协作
  • 接口的文档在线自动生成,降低后端开发人员编写接口文档的负担
  • 功能测试

(2)SpringBoot集成Swagger

①引入依赖

在heima-leadnews-model和heima-leadnews-common模块的pom.xml中引入该依赖

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

②在heima-leadnews-common中进行配置(其他微服务工程都直接或间接依赖common模块)

新增com.heima.coomon.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();
   }
}

③在heima-leadnews-common模块中的resources目录下的META-INF/spring.factories中新增如下

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

④Swagger常用注解

注解释义
@Api修饰整个类,描述Controller的作用
@ApiOperation描述一个类的一个方法,或者说一个接口
@ApiParam单个参数的描述信息
@ApiModel用对象接收参数
@ApiModelProperty用对象接收参数时,描述对象的一个字段
@ApiResponseHTTP响应其中一个描述
@ApiResponsesHTTP响应整体描述
@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 = "app端用户登录")
public class ApUserLoginController {

    @Autowired
    private ApUserService apUserService;

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

在LoginDto添加注解

package com.heima.model.user.dtos;

import io.swagger.annotations.ApiModelProperty;
import lombok.Data;

@Data
public class LoginDto {
    /**
     * 手机号
     */
    @ApiModelProperty(value = "手机号", required = true)
    private String phone;

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

⑤启动UserApplication

访问接口文档:http://localhost:51801/swagger-ui.html

3. 接口工具-knife4j

(1)简介

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

gitee地址:knife4j: Knife4j是一个集Swagger2 和 OpenAPI3为一体的增强解决方案

官方文档:Knife4j · 集Swagger2及OpenAPI3为一体的增强解决方案. | Knife4j

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

(2)核心功能

  • 文档说明:根据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.xiaoymin</groupId>
     <artifactId>knife4j-spring-boot-starter</artifactId>
</dependency>

②创建swagger配置文件

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

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

③在META-INF/spring.factories中新增配置

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

④启动UserApplication

访问地址:http://localhost:51801/doc.html#/home

六、app端网关

1. app端网关

(1)网关概述

实现步骤:

①在heima-leadnews-gateway导入以下依赖

<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.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
        </dependency>
    <dependency>
        <groupId>io.jsonwebtoken</groupId>
        <artifactId>jjwt</artifactId>
    </dependency>
</dependencies>

②在heima-leadnews-gateway下创建heima-leadnews-app-gateway微服务

新增引导类AppGatewayApplication

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

新增配置类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添加Data ID为leadnews-app-gateway的配置文件

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

④启动AppGatewayApplication和UserApplication

网址:http://localhost:51601/user/api/v1/login/login_auth

2. 认证过滤器

实现步骤:

①拷贝一份jwt解析工具类AppJwtUtil到网关微服务中

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

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);
            // 判断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;
    }
}

③重启AppGatewayApplication和UserApplication

如果访问其他微服务,会提示需要认证才能访问,这个时候就需要在headers中设置token才能正常访问。

七、app前端项目集成

①解压nginx-1.18.0.zip和app-web.zip到一个不带中文的路径下

②启动nginx

nginx: [emerg] bind() to 0.0.0.0:80 failed (10013: An attempt was made to access a socket in a way forbidden by its access permissions)

如果有出现上面的问题,可以查看正在占用80端口的程序,并kill掉

或者在nginx.conf把监听端口改成其他的,如8080

③在niginx安装的conf目录下新建一个文件夹leadnews.conf,在当前文件夹中新建heima-leadnews-app.conf文档,配置如下:(根据自己的情况修改前端工程路径

upstream  heima-app-gateway{
    server localhost:51601;
}

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

④把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;
}

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

可查看进行,检查nginx是否启动。

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

⑥启动UserApplication和AppGatewayApplication

访问:http://localhost:8801/

注意,要先启动nacos

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

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

相关文章

深度学习落地实战:基于UNet实现血管瘤超声图像分割

前言 大家好&#xff0c;我是机长 本专栏将持续收集整理市场上深度学习的相关项目&#xff0c;旨在为准备从事深度学习工作或相关科研活动的伙伴&#xff0c;储备、提升更多的实际开发经验&#xff0c;每个项目实例都可作为实际开发项目写入简历&#xff0c;且都附带完整的代…

无人机技术优势及发展详解

一、技术优势 无人机&#xff08;Unmanned Aerial Vehicle&#xff0c;UAV&#xff09;作为一种新兴的空中智能平台&#xff0c;凭借其独特的技术优势&#xff0c;已经在众多领域中展现出强大的应用潜力和实用价值。以下是无人机的主要技术优势&#xff1a; 1. 自主导航与远程…

《昇思25天学习打卡营第19天|Diffusion扩散模型》

什么是Diffusion Model&#xff1f; 什么是Diffusion Model? 如果将Diffusion与其他生成模型&#xff08;如Normalizing Flows、GAN或VAE&#xff09;进行比较&#xff0c;它并没有那么复杂&#xff0c;它们都将噪声从一些简单分布转换为数据样本&#xff0c;Diffusion也是从…

传统墙面装饰已成过去?创意投影互动墙引领新潮流?

你是否曾遐想过&#xff0c;那些日常中屡见不鲜的平凡墙面&#xff0c;能够摇身一变&#xff0c;成为既炫酷又高度互动的奇迹之地&#xff1f;事实上&#xff0c;这并非遥不可及的梦想&#xff0c;只需巧妙融合前沿的投影技术、灵敏的传感器与智能软件系统&#xff0c;便能瞬间…

01 机器学习概述

目录 1. 基本概念 2. 机器学习三要素 3. 参数估计的四个方法 3.1 经验风险最小化 3.2 结构风险最小化 3.3 最大似然估计 3.4 最大后验估计 4. 偏差-方差分解 5. 机器学习算法的类型 6. 数据的特征表示 7. 评价指标 1. 基本概念 机器学习&#xff08;Machine Le…

AdobeInDesign ID软件三网下载+Id教程

简介&#xff1a; InDesign还可以结合其他产品发布适合平板设备的内容。平面设计师和生产艺术家是主要用户&#xff0c;创作和布局期刊出版物、海报和印刷媒体。它还支持导出到EPUB和SWF格式&#xff0c;以创建电子书和数字出版物&#xff0c;包括数字杂志&#xff0c;以及适合…

【linux高级IO(三)】初识epoll

&#x1f493;博主CSDN主页:杭电码农-NEO&#x1f493;   ⏩专栏分类:Linux从入门到精通⏪   &#x1f69a;代码仓库:NEO的学习日记&#x1f69a;   &#x1f339;关注我&#x1faf5;带你学更多操作系统知识   &#x1f51d;&#x1f51d; Linux高级IO 1. 前言2. 初识e…

【python】PyQt5的窗口界面的各种交互逻辑实现,轻松掌控图形化界面程序

✨✨ 欢迎大家来到景天科技苑✨✨ &#x1f388;&#x1f388; 养成好习惯&#xff0c;先赞后看哦~&#x1f388;&#x1f388; &#x1f3c6; 作者简介&#xff1a;景天科技苑 &#x1f3c6;《头衔》&#xff1a;大厂架构师&#xff0c;华为云开发者社区专家博主&#xff0c;…

H3C Intelligent Management Center无线认证新增设备如何配置

目录 前提条件 一、IPsec VPN配置 二、IMC平台的配置 1.组网 ​编辑 2.核心设备配置 3.AAA服务器侧配置 4.创建认证的用户 5.登录测试 三、AC无线控制器图形界面配置 1.认证配置 1.1 新增ISP域 ​编辑​编辑 1.2新增 RADIUS 1.3 Portal认证配置​编辑​编辑​编…

Rust编程-crates.io

发布配置和开发配置&#xff1a; [profile.dev]: > cargo build opt-level0 [profile.release]: > cargo build --release opt-level3 发布到crates.io 文档注释&#xff1a; 三斜线&#xff08;///&#xff09;&#xff0c;使用markdown语法来格式化内容 可以为函数…

fatal: read error: Connection reset by peer

参考文章&#xff1a;https://www.cnblogs.com/sisimi/p/7910272.html 问题&#xff1a; 首先确认是否可以访问外网&#xff1a; ping www.baidu.com如果可以访问外网&#xff0c;把 git: 修改为 http: 即可&#xff1a;

高职院校人工智能人才培养成果导向系统构建、实施要点与评量方法

一、引言 近年来&#xff0c;人工智能技术在全球范围内迅速发展&#xff0c;对各行各业产生了深远的影响。高职院校作为培养高技能人才的重要基地&#xff0c;肩负着培养人工智能领域专业人才的重任。为了适应社会对人工智能人才的需求&#xff0c;高职院校需要构建一套科学、…

Java学习 - spring Bean 详解

Bean 的别名配置 接着上一篇文章中的 <bean> 配置&#xff0c;其中配置了 id 属性&#xff0c;通过 id 属性我们就可以获取到对象。其实 <bean> 配置也提供了 name 属性&#xff0c;它是用于定义 Bean 的别名&#xff0c;一个 Bean 的别名是可以有多个的&#xff…

[C++]——同步异步日志系统(7)

同步异步日志系统 一、日志器管理模块&#xff08;单例模式&#xff09;1.1 对日志器管理器进行设计1.2 实现日志器管理类的各个功能1.3. 设计一个全局的日志器建造者1.4 测试日志器管理器的接口和全局建造者类 二、宏函数和全局接口设计2.1 新建一个.h,文件,文件里面放我们写的…

视图库对接系列(GA-T 1400)十九、视图库对接系列(级联)注册

背景 在上一章视图库对接系列(GA-T 1400)十八、视图库对接系列(级联)代码生成中我们已经把代码生成了,那怎么实现级联? 我们可以抓包看设备是怎么注册到我们平台的, 那我们就怎么实现就可以了。 实现 先看设备注册到我们服务端的包 步骤 注册我们可以参考视图库对接系列(…

Data类中的常用方法

Calender类 java.util.Calendar是一个抽象的基类&#xff0c;创建对象需要使用静态方法Calendar.getInstance()完成。通过Calendar对象可以获得详细的日历信息&#xff0c;例如年、月、日、小时、分和秒&#xff0c;Calendar的子类可以实现特定的日历系统。 当前时间 Calenda…

CV每日论文--2024.7.16

1、Radiance Fields from Photons 中文标题&#xff1a;光子的辐射场 简介&#xff1a;神经辐射场(NeRFs)已成为从多个视角捕获的图像进行高质量视图合成的事实标准方法。然而,在野外环境下捕获图像时,仍存在许多挑战,例如低光、高动态范围或快速运动导致的模糊重建和明显的伪…

【MySQL进阶篇】索引

1、索引概述 索引&#xff08;Index&#xff09;是帮助MySQL高效获取数据的数据结构&#xff08;有序&#xff09;。在数据之外&#xff0c;数据库系统还维护着满足特定查找算法的数据结构&#xff0c;这些数据结构以某种方式引用&#xff08;指向&#xff09;数据&#xff0c…

高职院校专业群的生成机制研究

摘要&#xff1a;本研究针对我国产业转型升级背景下高职院校专业群的生成机制进行了深入探讨。运用案例分析法&#xff0c;从生成决策、生成目标、生成规则三个维度出发&#xff0c;对专业群的生成机制进行了系统分析。研究发现&#xff0c;高职院校专业群的生成是一个与产业环…

容器之Harbor

Harbor 是一个开源的企业级 Docker 镜像仓库&#xff0c;用于存储、签名和扫描 Docker 镜像。它由 VMware 开发&#xff0c;旨在增强用户在容器化环境中的安全性和效率。以下是对 Harbor 的详细介绍&#xff1a; 主要功能 1. 镜像管理 镜像存储&#xff1a;提供高效的存储管理…