heima头条项目学习--Day1: 环境搭建、SpringCloud微服务(注册发现、网关)

news2024/11/28 2:49:41

Nacos注册发现、网关

    • a. 项目介绍
    • b. app登录
      • 1) 需求分析
      • 2) 表结构分析
      • 3) 手动加密(md5+随机字符串)
      • 4) 用户端微服务搭建
      • 5) 功能实现
      • 6) app网关
      • 7) 网关校验jwt
      • 8) 前端集成, 配置nginx

a. 项目介绍

业务说明

在这里插入图片描述

技术栈说明

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-k5BDy2q4-1691417838766)(C:\Users\captaindeng\AppData\Roaming\Typora\typora-user-images\image-20230807140029623.png)]

在这里插入图片描述

在这里插入图片描述

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yOvDt0kS-1691417838767)(C:\Users\captaindeng\AppData\Roaming\Typora\typora-user-images\image-20230807141737685.png)]

b. app登录

1) 需求分析

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

在这里插入图片描述

2) 表结构分析

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

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

app_user表对应的实体类如下:

/**
 * @author Kyle
 * @date 2023/8/7 14:35
 *
 * App用户信息表
 */
@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) 用户端微服务搭建

在heima-leadnews-service下创建名为heima-leadnews-user的module

在com.heima.user下创建UserApplication

@SpringBootApplication
@EnableDiscoveryClient
@MapperScan("com.heima.user.mapper")
public class UserApplication {
    public static void main(String[] args) {
        SpringApplication.run(UserApplication.class, args);
    }
}

创建resources/bookstrap.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网站中创建配置文件

在这里插入图片描述

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

创建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>

在这里插入图片描述

5) 功能实现

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

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-P4bv6u47-1691417838767)(C:\Users\captaindeng\AppData\Roaming\Typora\typora-user-images\image-20230807153653965.png)]

接口定义

说明
接口路径/api/v1/login/login_auth
请求方式POST
参数LoginDto
响应结果ResponseResult

实现步骤

0.在model层下创建user.dtos的LoginDto

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

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

1.在controller.v1下创建ApUserLoginController,接口定义

@RestController
@RequestMapping("/api/v1/login")
public class ApUserLoginController {
    
    @Autowired
    private ApUserService apUserService;

    @PostMapping("/login_auth")
    public ResponseResult login(@RequestBody LoginDto loginDto){
        return apUserService.login(loginDto);
    }

}

2.持久层mapper下创建ApUserMapper

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

3.业务层service

public interface ApUserService extends IService<ApUser> {
    /**
     * App端登录功能
     * @param loginDto
     * @return
     */
    public ResponseResult login(LoginDto loginDto);
}

4.实现类

@Service
@Transactional
@Slf4j
public class ApUserServiceImpl extends ServiceImpl<ApUserMapper, ApUser> implements ApUserService {

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

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

            // 1.3 返回数据 jwt user
            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);
        }
    }
}

6) 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>

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

引导类:

@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的配置中心创建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

7) 网关校验jwt

在这里插入图片描述

具体实现:

第一:

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

第二:

在网关微服务中新建全局过滤器:在gateway/fliter下创建

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

8) 前端集成, 配置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;  #记录代理信息
	}
}

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

④ :启动nginx

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

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

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

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

​ 用谷歌浏览器打开,调试移动端模式进行访问

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

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

相关文章

Nginx的优化和防盗链(面试高频!!!)

Nginx的优化和防盗链 全篇高能&#xff01;&#xff01;&#xff01;&#xff01;干货较多&#xff01;&#xff01;&#xff01;&#xff01;本篇含面试高频题&#xff1a; 修改配置文件时&#xff0c;先备份&#xff01;&#xff01;&#xff01;以便回滚&#xff01;&…

API接口:企业信息核验

企业信息核验是现代企业管理中必不可少的一项业务&#xff0c;它可以帮助企业做出正确的决策。在这篇文章里&#xff0c;我们将会介绍如何使用API接口来对企业信息进行核验&#xff0c;并实现快捷、准确的查询。 一、API接口 在这里我们使用的是挖数据提供的企业信息核验API接…

医学影像PACS临床信息系统源码

医学影像临床信息系统&#xff08;Picture Archiving and Communication Systems&#xff09;PACS是指从医疗影像设备中获得数字影像&#xff0c;利用高速网络进行存储、管理、传输的医疗影像信息管理系统。通过该系统&#xff0c;能实现影像数字化、无胶片化管理。 登记系统 …

MyCat水平分表

1.水平拆分案例场景 2.MyCat配置 这个表只是在 schema.xml配置的逻辑表&#xff0c;在具体的数据库里面是没有的 根据id的模确定数据存在哪个节点上&#xff01;&#xff01;

8.7 作业 c高级

1.写一个函数&#xff0c;获取用户的uid和gid并使用变量接收&#xff1a; #!/bin/bash function fun() {uidid -u ubuntugidid -g ubuntu }funecho "UID: $uid" echo "GID: $gid"思维导图&#xff1a;

(树) 剑指 Offer 54. 二叉搜索树的第k大节点 ——【Leetcode每日一题】

❓剑指 Offer 54. 二叉搜索树的第k大节点 难度&#xff1a;简单 给定一棵二叉搜索树&#xff0c;请找出其中第 k 大的节点的值。 示例 1: 输入: root [3,1,4,null,2], k 13/ \1 4\2 输出: 4示例 2: 输入: root [5,3,6,2,4,null,null,1], k 35/ \3 6/ \2 4/1 输出…

【多音音频测试信号】具有指定采样率和样本数的多音信号,生成多音信号的相位降低波峰因数研究(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

Jmeter响应中的乱码问题

文章目录 问题描述解决办法 问题描述 Jmeter在访问接口的时候&#xff0c;响应内容如果有中文可能会显示乱码 响应页面没有做编码处理&#xff0c;JMeter默认按照ISO-8859-1编码格式进行解析 解决办法 在线程组中添加BeanShell PostProcessor后置处理器 prev.setDataEnco…

爬虫009_字符串高级_替换_去空格_分割_取长度_统计字符_间隔插入---python工作笔记028

然后再来看字符串的高级操作 取长度 查找字符串下标位置 判断是否以某个字符,开头结尾 计算字符出现次数 替换

STM32调试过程中的使用技巧及解决办法

文章目录 技巧 1.定时器使用过程中&#xff0c;分频系数越大&#xff0c;定时误差越大&#xff0c;越不准确。问题 2.编译时出现下述警告&#xff1a;解决办法&#xff1a; keil5 编译提示 single-precision operand implicity converted to double-precesion&#xff0c;意思是…

生成小程序二维码、小程序码

微信自定义生成二维码 使用微信云开发生成自定义二维码、小程序码话不多说&#xff0c;我们先来看最终的展示效果生成码有三种方式操作步骤1. 云环境的初始化2. 在页面上开辟一个容器来展示二维码&#xff08;包括预览和保存到相册的按钮&#xff09;3. 创建云函数4. 生成二维码…

黑客真的那么神奇吗?

对于这个话题我觉得我还是有发言权的&#xff0c;因为本人2008年从事这个行业至今已经是第八个年头。怎么进入这个行业的呢。说起来可笑因为当时家里并没有安装有线电视&#xff0c;而当时我才上初中有碰巧是奥运期间本人是个狂热体育迷所以只能去网吧看直播。兜里又没有几块钱…

按轨迹运行(纯跟踪)

文章目录 import numpy as np import math import matplotlib.pyplot as pltk = 0.1 # 前视距离系数 Lfc = 2.0 # 前视距离 Kp = 1.0 # 速度P控制器系数 dt = 0.1 # 时间间隔,单位:s L = 2.9 # 车辆轴距,单位:mdef plot_arrow(x, y, yaw, length=5, width=1):dx = len…

研发工程师玩转Kubernetes——hostPath

有别于《研发工程师玩转Kubernetes——emptyDir》一文中介绍的emptyDir&#xff0c;hostPath可以在同一个Node的不同Pod间共享卷。 下面的清单文件利用了Pod亲和性&#xff0c;让Pod集中到一个Node上。 apiVersion: apps/v1 kind: Deployment metadata:name: hostpath-deploy…

yolo训练参数scale和multi-scale的区别

yolov5/v7训练时,有两个和多尺度有关的参数,一个是scale, 另一个是multi-scale(yolov8去掉了这个)。 其中scale在超参数配置文件中设置: multi-scale在训练脚本中设置: 那么这两个参数有什么区别呢? 首先我们看看代码中使用它们的地方。 scale scale在datasets.py的ra…

物联网平台使用笔记

阿里云的IOT平台限制了50个设备。排除 移动云的限制较少&#xff0c;这里试用下。 创建完产品&#xff0c;接入设备后。使用MQTT客户端测试 其中client id 为设备id&#xff0c; username 为产品id&#xff0c; password 可以使用设备调试那里生成的。或使用官方token.exe 生成…

时钟周期=1/时钟频率

目录 一、时钟周期 二、时钟频率 三、计算时钟周期 一、时钟周期 时钟周期是指计算机系统中时钟信号的一个完整循环所需要的时间。通常情况下&#xff0c;CPU和其他芯片需要在同一时钟信号下协调其工作。时钟信号的频率越高&#xff0c;系统的处理速度就越快。在计算机系统…

高德地图实现点聚合功能的详细步骤(附源码)

目录 介绍准备工作1.注册并登录高德地图开放平台&#xff0c;申请密钥2.在Vue项目中安装高德地图的相关库/插件。 一、点聚合1.引入高德地图API<font color purple>initializeMap()<font color purple>loadData()<font color purple>createMarkerClustere…

Android Animation Made Easy

原文链接 Android Animation Made Easy 动画在任何一个GUI系统中都是一个非常重要的设计元素&#xff0c;它可以让交互变得优雅&#xff0c;让界面变得炫酷&#xff0c;让操作变得更加的舒畅&#xff0c;让状态过渡变得更加的顺滑&#xff0c;对视觉效果有极大的提升&#xff…

Jmeter添加cookie的两种方式

jmeter中添加cookie可以通过配置HTTP Cookie Manager&#xff0c;也可以通过HTTP Header Manager&#xff0c;因为cookie是放在头文件里发送的。 实例&#xff1a;博客园点击添加新随笔 https://i.cnblogs.com/EditPosts.aspx?opt1 如果未登录&#xff0c;跳转登录页&#xf…