🎄概述
经过前面两篇对用户中心项目后端和前端的开发 这篇文章来记录我的首个前后端分离项目的上线过程
关于用户中心项目的前两篇可见下面的链接
- 用户中心 SpringBoot后端
- 用户中心 React前端
🎄用户中心项目·前端部分上线
🍭多环境开发归属
🔮概述
多环境开发指的是在软件开发过程中同时进行多个环境的部署和测试。传统软件开发通常只有一个开发环境和一个生产环境,但随着软件规模和复杂性的增加,需要在不同的环境中进行开发、测试和部署,以确保系统在不同环境中都能正常运行。
多环境开发可以包括以下几个环境:
- 开发环境:开发人员在本地或共享的服务器上进行代码编写和功能测试,可以快速迭代和调试。
- 测试环境:用于测试和验证开发的功能和集成,模拟真实环境,以发现可能存在的问题和漏洞。
- 预生产环境:一个近似于生产环境的环境,用于评估和测试在真实环境下部署的软件的性能和稳定性,以减少出现问题的风险。
- 生产环境:最终部署的软件系统运行的环境,用于提供线上服务和满足用户需求。
多环境开发的好处是能够让开发团队更好地控制和管理软件的生命周期。通过在不同环境中验证和测试,可以更早地发现和解决问题,提高软件的质量和稳定性。同时,多环境开发还能够提供更好的隔离性,防止代码与数据的混乱,并且可以减少对生产环境的影响。
为了实现多环境开发,通常会使用版本控制工具来管理代码的不同版本和分支,以及持续集成和持续部署工具来自动化测试、构建和部署过程。此外,也需要对不同环境进行合理的配置和管理,以确保环境之间的一致性和可重复性。
🔮结合项目分析
在用户中心项目的前端部分 我使用的是Ant Design Pro的开发框架 这个框架是基于umi框架的 在build项目(编译打包)的时候 会自动传入 NODE_ENV = production参数 表示生产环境;当在本地开发启动start的时候 NODE_ENV = development 表示开发环境
不同的NODE_ENV参数对应不同的开发环境 如何来验证上面所说的这一点呢?我们可以在项目启动的时候让其alert出NODE_ENV参数的值 从而进行观察 如下图所示 在项目的初始化入口alert process.env.NODE_ENV
变量观察其值
本地启动 观察
编译后启动
"build": "set NODE_OPTIONS=--openssl-legacy-provider && umi build",
发现无法识别serve命令 这是因为没有安装 所以无法识别这个命令
安装serve
npm install -g serve
重新启动 点击访问
点击登录 发现走的是3000端口
新建plugins文件夹
globalRequest.ts
文件prefix: process.env.NODE_ENV === ‘production’ ? ‘http://服务器IP地址:81’ : undefined
/**
* request 网络请求工具
* 更详细的 api 文档: https://github.com/umijs/umi-request
*/
import {extend} from 'umi-request';
import {message} from "antd";
import {history} from "@@/core/history";
import {stringify} from "querystring";
/**
* 配置request请求时的默认参数
*/
const request = extend({
credentials: 'include', // 默认请求是否带上cookie
// 后面把后端部署到81端口
prefix: process.env.NODE_ENV === 'production' ? 'http://服务器IP地址:81' : undefined
});
/**
* 所以请求拦截器
*/
request.interceptors.request.use((url, options): any => {
console.log(`do request url = ${url}`)
return {
url,
options: {
...options,
headers: {},
},
};
});
/**
* 所有响应拦截器
*/
request.interceptors.response.use(async (response, options): Promise<any> => {
const res = await response.clone().json();
if (res.code === 200) {
return res.data;
}
if (res.code === 40100) {
message.error('请先登录');
history.replace({
pathname: '/user/login',
search: stringify({
redirect: location.pathname,
}),
});
} else {
message.error(res.description)
}
return res.data;
});
export default request;
修改
api.tsx
文件
重新build、serve并访问 登录 可见自己配置的request起作用了 后面就可以把dist目录上传到服务器 使用nginx来进行部署了
🍭部署前端到服务器Nginx
🔮压缩dist目录 上传到服务器 并解压缩
压缩
上传
解压
unzip dist.zip -d /export/server/user_center_frontend_20231002
先创建目标解压目录
指令unzip命令进行解压缩
查看解压后的文件
🔮配置Nginx进行部署
配置nginx.conf
重新启动nginx ->
nginx -s reload
开启服务器防火墙81端口
浏览器测试访问服务器80端口 报404 这是因为nginx配置的时候 没有配置主页面index.html
修改nginx.conf
重启nginx并重新访问
尝试登录访问 可以看到前端的访问前缀端口是81端口 所以等会做一个调整 把前端的访问设置为82端口 81端口供后端使用
🔮调整前端端口为82端口
开启服务器防火墙的82端口
重启访问82端口
非常棒 到此 前端部分成功上线✨
🎄用户中心项目·后端部分上线
🍭本地配置
使用🎯jar的方式打包项目 编辑
pom.xml文件
<groupId>bbm.com</groupId>
<artifactId>bigbigmeng-user-center-backend-20230923</artifactId>
<version>1.0-SNAPSHOT</version>
<!-- 20231002设置项目的打包方式 -->
<packaging>🎯jar</packaging>
增加生产环境的配置文件
# 线上配置文件
spring:
datasource:
driver-class-name: com.mysql.jdbc.Driver
url: 'jdbc:mysql://101.42.24.90:3306/bbm_user_center?&characterEncoding=utf8&useSSL=false'
username: root
password: root
server:
address: 0.0.0.0
port: 8282
servlet:
context-path: /
🍭导入本地SQL文件到服务器
创建数据库
CREATE DATABASE bbm_user_center DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;
导入本地sql文件(提亲上传好)
导入数据:
🙃打包项目上传到服务器(演示错误的打包jar方式❌)
打包
将jar包上传到服务器
后台运行jar文件
nohup java -jar /export/usercenter-backend.jar --spring.profiles.active=prod &
查看启动情况
重新启动 nohup java -jar usercenter-backend.jar >/export/usercenter.log 2>&1&
原因是SpringBoot项目打包之前缺少必要的配置 java找不到执行入口(主启动类)
补充配置(war包部署的时候需要)
修改主启动类j使其继承🎯extends SpringBootServletInitializer
重写configure
方法
package bbm.com;
@SpringBootApplication
public class UserCenterApplication extends SpringBootServletInitializer {
public static void main(String[] args) {
SpringApplication.run(UserCenterApplication.class);
}
🎯@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
return builder.sources(UserCenterApplication.class);
}
}
🙂打包项目上传到服务器(演示正确的打包jar方式✅)
打包
打包配置
执行打包
查看打包好的jar文件
上传jar包并执行
执行jar包
java -jar bigbigmeng-user-center-backend-20230923.jar
❌10:18:25.798 [main] ERROR org.springframework.boot.SpringApplication - Application run failed java.lang.IllegalArgumentException: No auto configuration classes found in META-INF/spring.factories. If you are using a custom packaging, make sure that file is correct.
✅解决方法 在
pom.xml
加上以下插件
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
重新打包上传
重新执行
nohup java -jar /export/bigbigmeng-user-center-backend-20230923-1.0-SNAPSHOT.jar --spring.profiles.active=prod &
查看日志
nohup.out
文件
🍭配置nginx代理
后端jar的启动占用端口是8282 前端请求的url前缀是http://101.42.24.90:81 nginx将这个前缀代理到8282端口
⚡后端执行测试
⚡前端执行测试
分析 当前前后端已经独立部署成功 但是当前的配置会存在跨域的问题
🎄解决跨域问题
⚡出现提示Access-Control-Allow-Origin不能为*
Access-Control-Allow-Origin 是一个HTTP响应头,用于控制跨域资源共享(CORS)。它指定了哪些源(origin)有权限访问该资源。
该头部包含一个值,可以是单个源的 URL(如http://localhost:82),也可以是一个通配符(*),表示任何来源都具有访问权限。
当浏览器发起跨域请求时,服务器会返回 Access-Control-Allow-Origin 头部,告知浏览器是否允许该请求。如果值为 *,表示允许所有来源进行访问;如果值为具体的源,表示只允许该源进行访问。
如果请求的源不在 Access-Control-Allow-Origin 头部所指定的允许范围内,浏览器会阻止响应数据的读取,并抛出一个跨域资源共享失败的错误。
通过设置 Access-Control-Allow-Origin 头部,服务器可以灵活控制允许访问资源的来源,提高系统的安全性和可信度,同时也能更好地满足网站间数据共享的需求。
图中提示的错误是当credentials模式为’include’的时候 返回的response的Access-Control-Allow-Origin ❌不能配置为* 修改为如下’✅http://localhost:8000即可
@Bean
public WebMvcConfigurer corsConfigurer() {
return new WebMvcConfigurer() {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**") // 允许跨域的路径
.allowedOriginPatterns("✅http://localhost:8000")
.allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS")// 允许请求的方法
.allowedHeaders("*") // 允许跨域请求包含的头部信息
.allowCredentials(true) // 是否发送Cookie
.maxAge(3600); // 预检请求的有效期 单位为秒
}
};
}
⚡修改nginx配置文件
在后端代理处添加以下配置
# 20231002 user_center_backend
server {
listen 110; # 110号端口反向代理8282端口
server_name 101.42.24.90;
location ^~ /api/ {
proxy_pass http://101.42.24.90:8282/api;
add_header 'Access-Control-Allow-Origin' $http_origin;
add_header 'Access-Control-Allow-Credentials' 'true';
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
add_header 'Access-Control-Allow-Headers' '*';
if ($request_method = OPTIONS) {
# 20231003 这个配置很关键$http_origin
add_header 'Access-Control-Allow-Origin' $http_origin;
add_header 'Access-Control-Allow-Credentials' 'true';
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range';
add_header 'Access-Control-Max-Age' 1728000;
add_header 'Control-Type' 'text/plain; charset=utf-8';
add_header 'Control-Length' 0;
return 204;
}
}
}
重启nginx
⚡前端测试管理员登录
修改前端访问后端url前缀 端口为9091 重新遍历前端 重新部署
const request = extend({
credentials: 'include', // 默认请求是否带上cookie
prefix: process.env.NODE_ENV === 'production' ? 'http://101.42.24.90:9091' : undefined
// requestType: 'form',
});
访问查看
⚡再次配置跨域
跨域配置无效 把前后端部署到同源 重启nginx测试
⚡修复Nginx500错误
查看报错信息
tail -f /var/log/nginx/error.log
修改
后来发现是nginx代理配置错误
重新执行