前后端分离项目知识汇总(GateWay,Nacos配置中心,Jenkins自动化部署,项目总结)

整合Gateway网关

Spring全家桶–SpringCloud(中级)_小蜗牛耶的博客-CSDN博客_springcloud

详细介绍可看上文

image-20220523215349123

image-20220523215359541

建模块、改pom、yml、启动类

image-20220523215621092

网关相关配置

可以把之前控制类上写的@CrossOrigin注解去掉

所有请求通过gateway网关才会转发给相应微服务,

我们在gateway中解决跨域问题

image-20220523215653182

全局Filter

固定写法

package com.atguigu.gateway.filter;

/**
 * <p>
 * 全局Filter,统一处理会员登录与外部不允许访问的服务
 * </p>
 *
 * @author qy
 * @since 2019-11-21
 */
@Component
public class AuthGlobalFilter implements GlobalFilter, Ordered {
    
    

    private AntPathMatcher antPathMatcher = new AntPathMatcher();

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
    
    
        ServerHttpRequest request = exchange.getRequest();
        String path = request.getURI().getPath();
        //谷粒学院api接口,校验用户必须登录
        if(antPathMatcher.match("/api/**/auth/**", path)) {
    
    
            List<String> tokenList = request.getHeaders().get("token");
            if(null == tokenList) {
    
    
                ServerHttpResponse response = exchange.getResponse();
                return out(response);
            } else {
    
    
//                Boolean isCheck = JwtUtils.checkToken(tokenList.get(0));
//                if(!isCheck) {
    
    
                    ServerHttpResponse response = exchange.getResponse();
                    return out(response);
//                }
            }
        }
        //内部服务接口,不允许外部访问
        if(antPathMatcher.match("/**/inner/**", path)) {
    
    
            ServerHttpResponse response = exchange.getResponse();
            return out(response);
        }
        return chain.filter(exchange);
    }

    @Override
    public int getOrder() {
    
    
        return 0;
    }

    private Mono<Void> out(ServerHttpResponse response) {
    
    
        JsonObject message = new JsonObject();
        message.addProperty("success", false);
        message.addProperty("code", 28004);
        message.addProperty("data", "鉴权失败");
        byte[] bits = message.toString().getBytes(StandardCharsets.UTF_8);
        DataBuffer buffer = response.bufferFactory().wrap(bits);
        //response.setStatusCode(HttpStatus.UNAUTHORIZED);
        //指定编码,否则在浏览器中会中文乱码
        response.getHeaders().add("Content-Type", "application/json;charset=UTF-8");
        return response.writeWith(Mono.just(buffer));
    }
}

自定义异常处理

image-20220523220133477

image-20220523220142482

整合配置中心

jar包和war包区别及理解_猪耳朵的博客-CSDN博客_jar war

Spring全家桶–SpringCloud(高级)_小蜗牛耶的博客-CSDN博客

为什么需要配置中心

在开发阶段不适合使用war包,因为在开发阶段,经常需要添加或删除Web应用程序的内容,更新 Servlet类文件,而每一次改动后,重新建立war包将是一件浪费时间的事情。在产品发布阶段,使用war文件比较合适的,因为在这个时候,几乎不需要再做什么改动了。

在系统开发过程中,开发者通常会将一些需要变更的参数、变量等从代码中分离出来独立管理,以独立的配置文件的形式存在。目的是让静态的系统工件或者交付物(如 WAR,JAR 包等)更好地和实际的物理运行环境进行适配。配置管理一般包含在系统部署的过程中,由系统管理员或者运维人员完成。配置变更是调整系统运行时的行为的有效手段。

如果微服务架构中没有使用统一配置中心时,所存在的问题:

- 配置文件分散在各个项目里,不方便维护

- 配置内容安全与权限

- 更新配置后,项目需要重启

nacos配置中心:系统配置的集中管理(编辑、存储、分发)、动态更新不重启、回滚配置(变更管理、历史版本管理、变更审计)等所有与配置相关的活动。

image-20220524092334617

image-20220524092411906

jar包和war包区别及理解

jar是类的归档文件
JAR(Java Archive,Java 归档文件)是与平台无关的文件格式,它允许将许多文件组合成一个压缩文件,为 J2EE 应用程序创建的jar文件是 EAR 文件(企业 jar文件),jar文件格式以流行的 ZIP 文件格式为基础。与 ZIP 文件不同的是,jar文件不仅用于压缩和发布,而且还用于部署和封装库、组件和插件程序,并可被像编译器和 JVM 这样的工具直接使用。在 jar中包含特殊的文件,如 manifests 和部署描述符,用来指示工具如何处理特定的 jar。
通常是开发时要引用通用类,打成jar包便于存放管理,当你使用某些功能时就需要这些jar包的支持,需要导入jar包。
jar包就是java的类进行编译生成的class文件打包的压缩包,包里面就是一些class文件。当我们自己使用Maven写一些java程序,进行打包生成jar包。同时在可以在其他的工程下使用,但是我们在这个工程依赖的jar包,在其他工程使用该JAR包也要导入。

war包是一个Web应用程序
一个web程序进行打包便于部署的压缩包,里面包含我们web程序需要的一些东西,其中包括web.xml的配置文件,前端的页面文件,以及依赖的jar。便于我们部署工程,直接放到tomcat的webapps目录下,直接启动tomcat即可。同时,可以使用WinRAR查看war包,直接将后缀.war改成.rar。

jar包和war包区别

jar是java普通项目打包,通常是开发时要引用通用类,打成jar包便于存放管理。当你使用某些功能时就需要这些jar包的支持,需要导入jar包。war是java web项目打包,web网站完成后,打成war包部署到服务器,目的是为了节省资源,提供效率。

读取配置文件

image-20220524084846596

image-20220524091637274

image-20220524091913957

重启测试

image-20220524092023186

多配置文件加载

在dev环境写两个配置文件,一个端口配置一个其他配置

image-20220524092603975

测试

image-20220524095202572

image-20220524095446382

整合Jenkins

代码上传到码云

省略…

环境配置

代码中需要包含Dockerfile文件

image-20220524095938488

在项目pom文件中指定打包类型,包含build部分内容

image-20220524100009338

安装jenkins环境

在centos环境安装以下环境

  • java
  • maven
  • git
  • docker

其中maven的setttings文件最好改成国内源,不然构建的会很慢!

配置环境变量

image-20220524100308095

部署jenkins

[root@mysql jenkins]# ll
total 92716
-rw-r--r-- 1 root root 94928325 May 20 07:19 jenkins.war

[root@mysql jenkins]# nohup java -jar  /usr/local/jenkins/jenkins.war >/usr/local/jenkins/jenkins.out &
[1] 5570

[root@mysql jenkins]# nohup: ignoring input and redirecting stderr to stdout

登录

image-20220524101545453

下面这一步不太好用,退出之后还是没有updates文件夹,可以在网上下载好插件,然后把插件复制到plugins再打开就有这些功能了

image-20220524101609591

jdk环境配置

image-20220524101903702

git配置

image-20220524102010071

maven配置

image-20220524102023279

保持配置即可…

构建作业

构建思路:

  • 建立任务
  • 选择仓库代码
  • 选择执行作业的方式

1、建立任务

image-20220524102201990

2、选择仓库代码

image-20220524102354875

3、选择执行作业的方式

image-20220524102537271

代码如下:

#!/bin/bash
#maven打包
mvn clean package
echo 'package ok!'
echo 'build start!'
cd ./infrastructure/eureka_server
service_name="eureka-server"
service_prot=8761
#查看镜像id
IID=$(docker images | grep "$service_name" | awk '{print $3}')
echo "IID $IID"
if [ -n "$IID" ]
then
    echo "exist $SERVER_NAME image,IID=$IID"
    #删除镜像
    docker rmi -f $service_name
    echo "delete $SERVER_NAME image"
    #构建
    docker build -t $service_name .
    echo "build $SERVER_NAME image"
else
    echo "no exist $SERVER_NAME image,build docker"
    #构建
    docker build -t $service_name .
    echo "build $SERVER_NAME image"
fi
#查看容器id
CID=$(docker ps | grep "$SERVER_NAME" | awk '{print $1}')
echo "CID $CID"
if [ -n "$CID" ]
then
    echo "exist $SERVER_NAME container,CID=$CID"
    #停止
    docker stop $service_name
    #删除容器
    docker rm $service_name
else
    echo "no exist $SERVER_NAME container"
fi
#启动
docker run -d --name $service_name --net=host -p $service_prot:$service_prot $service_name
#查看启动日志
docker logs  $service_name

第一次可能有些慢,之后就会很快

image-20220521142847507

image-20220524101515900

[root@mysql jenkins]# docker ps -a
CONTAINER ID   IMAGE          COMMAND                  CREATED         STATUS         PORTS     NAMES
96d5a7108ef9   demojenkins2   "java -jar /demojenk…"   2 minutes ago   Up 2 minutes             demojenkins2


部署成功啦!!!

image-20220521143008672

项目总结和复盘

(1)

B2C(Business to Customer)。B2C中的B是Business,意思是企业,2则是to的谐音,C是Customer,意思是消费者,所以B2C是企业对消费者的电子商务模式。这种形式的电子商务一般以网络零售业为主,主要借助于Internet开展在线销售活动。

在线教育系统,分为前台网站系统和后台管理系统,B2C模式。

前台用户系统包括课程、讲师、问答、文章几大大部分,使用了微服务技术架构,前后端分离开发。

后端的主要技术架构是:SpringBoot + SpringCloud + MyBatis-Plus + MySQL + Maven+EasyExcel+ nginx

前端的架构是:Node.js + Vue.js +element-ui+NUXT+ECharts

其他涉及到的中间件包括Redis、阿里云OSS、阿里云视频点播

业务中使用了ECharts做图表展示,使用EasyExcel完成分类批量添加、注册分布式单点登录使用了JWT

(2)

项目前后端分离开发,后端采用SpringCloud微服务架构,持久层用的是MyBatis-Plus,微服务分库设计,使用Swagger生成接口文档

接入了阿里云视频点播、阿里云OSS。

系统分为前台用户系统和后台管理系统两部分。

前台用户系统包括:首页、课程、名师、问答、文章。

后台管理系统包括:讲师管理、课程分类管理、课程管理、统计分析、Banner管理、订单管理、权限管理等功能。

前后端联调经常遇到的问题

1、请求方式post、get

2、json、x-wwww-form-urlencoded混乱的错误

3、后台必要的参数,前端省略了

4、数据类型不匹配

5、空指针异常

前后端分离项目中的跨域问题是如何解决的

后端服务器配置:我们的项目中是通过Spring注解解决跨域的 @CrossOrigin

也可以使用nginx反向代理、httpClient、网关

说说你做了哪个部分、遇到了什么问题、怎么解决的

分布式id生成器在前端无法处理,总是在后三位进行四舍五入。

分布式id生成器生成的id是19个字符的长度,前端javascript脚本对整数的处理能力只有2的53次方,也就是最多只能处理16个字符

解决的方案是把id在程序中设置成了字符串的性质

前端渲染和后端渲染有什么区别

前端渲染是返回json给前端,通过javascript将数据绑定到页面上

后端渲染是在服务器端将页面生成直接发送给服务器,有利于SEO的优化

能画一下系统架构图吗

image-20220524104239798

Bug记录

maven错误解决

用我的仓库

删了包,让它重新下

执行了全局异常处理

image-20220412163418570

image-20220412163505493

常见的排错方式

如下错误

image-20220516105619537

排错思路

从头开始想,当我点击这个按钮的时候发生了什么事,从前端想到后端依次检查。如果都没有错误那就检查其他配置,如nginx,nacos,等第三方技术

好,那么我们来实践一下

1、从前到后发森什么事了?

image-20220516111618146

2、详细分析

image-20220516112054147

用开发者工具抓包,看看请求的过程都发生了什么

image-20220516112405497

因为整个项目是微服务架构,这里其实是订单微服务调用了课程信息、用户信息微服务。

用户信息都是显示出来的,那就说明是课程微服务出问题了,我们先用swagger进行测试看看接口的功能有没有问题

image-20220516112908009

问题逐渐清晰了,后端功能没问题,那就是前端的问题了

其实刚才我们就能定位到是前端的问题,因为课程id参数为undefined,参数是通过前端传的。为了更严谨,我们选择都测试。

让目光再次回到前端代码

image-20220516113626404

image-20220516113819243

再次测试

image-20220516113935794

Feign调用异常FeignException$NotFound: [404] during

一般来说,feign报404错误有以下几个原因
1、路径错误
在服务消费者断采用GetMapping方式,如
@GetMapping(“knowledge/metadata/delete/{mdcode}”)

在服务提供者端,用
@RestController
@RequestMapping(“knowledge”)
public class KnowledgeGraphController {

@RequestMapping(“metadata/delete/{mdcode}”)
(实现方法)
}

服务消费者端,一定要加上knowledge呀喂

2、在多个客户端上启动了服务提供者服务,而这两边的服务方法没同步,所以在调用feign时,会采用负载均衡,在多个客户端上一边读取一次。如果这个时候恰好读的是没有指定方法的客户端提供的服务,就会报404错误。
建议改好方法之后提交,两边再跑服务

3、路径上参数为null
例如mdcode 为null,匹配不到路径地址,触发不了路径问题

参考

视频演示

尚硅谷_谷粒学苑-微服务+全栈在线教育实战项目_哔哩哔哩_bilibili

什么是跨域

https://www.jianshu.com/p/8fa2acd103ea

猜你喜欢

转载自blog.csdn.net/qq_45714272/article/details/124980304