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

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

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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Spring Boot多级缓存实现方案

1.背景 缓存&#xff0c;就是让数据更接近使用者&#xff0c;让访问速度加快&#xff0c;从而提升系统性能。工作机制大概是先从缓存中加载数据&#xff0c;如果没有&#xff0c;再从慢速设备(eg:数据库)中加载数据并同步到缓存中。 所谓多级缓存&#xff0c;是指在整个系统架…

SpringBoot之logback-spring.xml详细配置

《logback官网》 各种指导文件&#xff0c;有空自己去看&#xff0c;比如&#xff1a;我们需要调整的是布局&#xff0c;直接看Layouts。 pom.xml <!-- 环境配置 --><profiles><profile><id>dev</id><properties><spring.profiles.a…

前端例程20230806:彩色灯珠装饰

演示 这里页面四周的彩色灯珠是会随着页面调整自动调整位置的。 代码 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta http-equiv"X-UA-Compatible" content"IEedge"><meta na…

【数据结构与算法——TypeScript】哈希表

【数据结构与算法——TypeScript】 哈希表(HashTable) 哈希表介绍和特性 哈希表是一种非常重要的数据结构&#xff0c;但是很多学习编程的人一直搞不懂哈希表到底是如何实现的。 在这一章节中&#xff0c;我门就一点点来实现一个自己的哈希表。通过实现来理解哈希表背后的原理…

2022年03月 Python(一级)真题解析#中国电子学会#全国青少年软件编程等级考试

一、单选题&#xff08;共25题&#xff0c;每题2分&#xff0c;共50分&#xff09; 第1题 已知a“161”&#xff0c;b“16”&#xff0c;c“8”,执行语句da>b and a>c&#xff0c;变量d的值为是&#xff1f; A&#xff1a;0 B&#xff1a;1 C&#xff1a;True D&am…

探究使用HTTP爬虫ip后无法访问网站的原因与解决方案

在今天的文章中&#xff0c;我们要一起来解决一个常见问题&#xff1a;使用HTTP爬虫ip后无法访问网站的原因是什么&#xff0c;以及如何解决这个问题。我们将提供一些实际的例子和操作经验&#xff0c;帮助大家解决HTTP爬虫ip无法访问网站的困扰。 1、代理服务器不可用 使用HT…

【SpringBoot笔记】定时任务(cron)

定时任务就是在固定的时间执行某个程序&#xff0c;闹钟的作用。 1.在启动类上添加注解 EnableScheduling 2.创建定时任务类 在这个类里面使用表达式设置什么时候执行 cron 表达式&#xff08;也叫七子表达式&#xff09;&#xff0c;设置执行规则 package com.Lijibai.s…

面试常问:tcp的三次握手和四次挥手你了解吗?

三次握手和四次挥手是各个公司常见的考点&#xff0c;一个简单的问题&#xff0c;却能看出面试者对网络协议的掌握程度&#xff0c;对问题分析与解决能力&#xff0c;以及数据流管理理解和异常情况应对能力。所以回答好一个tcp的三次握手和四次挥手的问题对于我们的面试成功与否…

(vue)获取对象的键遍历,同时循环el-tab页展示key及内容

(vue)获取对象的键遍历&#xff0c;同时循环el-tab页展示key及内容 效果&#xff1a; 数据结构&#xff1a; "statusData": {"订购广度": [ {"id": 11, "ztName": "广", …

C++笔记之两个类的实例之间传递参数的各种方法

C笔记之两个类的实例之间传递参数的各种方法 code review! 文章目录 C笔记之两个类的实例之间传递参数的各种方法1.构造函数参数传递2.成员函数参数传递3.友元函数4.友元类5.传递指针或引用6.静态成员变量7.静态成员函数8.全局变量或命名空间9.回调函数和函数指针10.观察者模…

pg实现月累计

获取每月累计数据&#xff1a; ​​​ SELECT a.month, SUM(b.total) AS total FROM ( SELECT month, SUM(sum) AS total FROM ( SELECT to_char(date("Joinin"),YYYY-MM) AS month , COUNT(*) AS sum FROM "APP_HR_Staff_Basic_Info" GROUP BY month ) …

做接口测试如何上次文件

在日常工作中&#xff0c;经常有上传文件功能的测试场景&#xff0c;因此&#xff0c;本文介绍两种主流编写上传文件接口测试脚本的方法。 首先&#xff0c;要知道文件上传的一般原理&#xff1a;客户端根据文件路径读取文件内容&#xff0c;将文件内容转换成二进制文件流的格式…

Vue3 第五节 一些组合式API和其他改变

1.provide和inject 2.响应式数据判断 3.Composition API的优势 4.新的组件 5.其他改变 一.provide和inject 作用&#xff1a;实现祖与后代组件间通信 套路&#xff1a;父组件有一个provide选项来提供数据&#xff0c;后代组件有一个inject选项来开始使用这些数据 &…

APP外包开发的学习流程

学习iOS App的开发是一项有趣和富有挑战性的任务&#xff0c;是一个不断学习和不断进步的过程。掌握基础知识后&#xff0c;不断实践和尝试新的项目将使您的技能不断提升。下面和大家分享一些建议&#xff0c;可以帮助您开始学习iOS App的开发。北京木奇移动技术有限公司&#…

hcip的重发布实验(1)

题目 拓扑图 IP地址配置 R1 < Huawei>sy Enter system view, return user view with CtrlZ. [Huawei]sysname r1 [r1]int l0 [r1-LoopBack0]ip add 1.1.1.1 24 [r1-LoopBack0]int g0/0/0 [r1-GigabitEthernet0/0/0]ip add 12.1.1.1 24 Aug 8 2023 21:28:29-08:00 r1 %%0…

升级node版本后vue2的项目node-sass、sass-loader安装报错(14.x升级到16.x)

node升级到16.x版本后&#xff0c;对应的node-sass需要升级到^6.0.0&#xff0c;此时sass-loader的版本需要升级到10.2.0以上 &#xff0c;具体对应版本规则可参考链接: https://github.com/webpack-contrib/sass-loader/releases?page3 vue2通过vue/cli创建的项目&#xff0…

super父类 事物

一个没有事物的方法。 调用他的父类里有事物的方法。 无论this 和 super 都会让父类事物方法没有事物。 如果写了super.class 文件里面&#xff0c;就是super调用。 如果没写&#xff0c;就是this调用&#xff0c;坑爹 测试&#xff0c;把父类注入&#xff0c;事物才生效。

搭建本地开发服务器

搭建本地开发服务器 :::warning 注意 在上一个案例的基础上添加本地开发服务器&#xff0c;请保留上个案例的代码。如需要请查看 Webpack 使用。 ::: 搭建本地开发服务器这一个环节是非常有必要的&#xff0c;我们不可能每次修改源代码就重新打包一次。这样的操作是不是太繁琐…

ArcGIS Pro基础:【划分】工具实现等比例、等面积、等宽度划分图形操作

本次介绍【划分】工具的使用&#xff0c;如下所示&#xff0c;为该工具所处位置。使用该工具可以实现对某个图斑的等比例面积划分、相等面积划分和相等宽度划分。 【等比例面积】&#xff1a;其操作如下所示&#xff0c;其中&#xff1a; 1表示先选中待处理的图斑&#xff0c;2…

无人机光伏巡检系统的全新作用解析,提升效率保障安全

随着光伏发电行业的快速发展&#xff0c;光伏电站的规模越来越大&#xff0c;光伏维护和巡检成为一个巨大的挑战。为解决传统巡检方法的低效率和安全风险问题&#xff0c;无人机光伏巡检系统应运而生&#xff0c;并成为提升光伏巡检效率和保障安全的利器。 首先&#xff0c;无人…