前后端分离后nginx与项目路径配置方法总结
一、前言前后端分离后,在同一台主机上,前端无法直接访问后台接口,会跨域;因此需要使用nginx,才能让前后端通信,便于开发。
一、前言
前后端分离后,如果想将前后端项目都放在同一台电脑上启动与开发,可以使用nginx。
现将配置方法总结如下。
二、后端配置方法
1.如果是springboot项目,要注意application.yml中的:
server:
port: 8080
context-path: /survey
类似这样的配置,说明后端项目启动后,端口是8080,前缀路径为/survey。
2.注意pom.xml中,如果有以下配置:
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<configuration>
<path>/survey</path>
<port>8080</port>
</configuration>
</plugin>
这说明项目打好包启动后,端口是8080,前缀路径为/survey。
3.查看XXXController.java,注意以下部分:
(1)类上的RequestMapping注解
@Controller
@RequestMapping("/survey-api")
public class LoginController{}
这个说明,此controller中具体的路径前有一个前缀,为/survey-api。
(2)方法上的RequestMapping/GetMapping/PostMapping等注解
@GetMapping("/login")
public void login(HttpServletRequest req, HttpServletResponse resp){}
这个说明访问这个后台方法的路径的最后部分为/login。
4.因此,按照上方的例子,访问后台方法login的具体的url为:
http://localhost:8080/survey/survey-api/login
localhost是本地ip的意思,如果后台项目启动在其它主机上,则访问时换成为其它主机的ip。
三、前端配置方法
1.前端可能会有一个总的配置文件,记录一个ip,具体代码中只使用这个ip的引用。
就是声明一个全局变量,例如 IPCONFIG = 10.123.123.123:8081,之后用IPCONFIG拼接后缀形成url。
这个全局变量可能用来拼接前端页面的url,也有可能用来拼接后台接口的url。
因此,打前端包时,应该修改这个参数为存放前端项目或后端项目的电脑的IP+端口。
2.以本人接触的项目为例,vue项目打好包后,生成dist文件夹,其中有一个static文件夹与index.html文件;
static文件夹中,有一个ipConfig.js;
ipConfig.js中,配置了全局变量:
const IPCONFIG="http://10.123.123.123:8081" //本地路径,开发用
//const IPCONFIG="http://www.prodMyCompany.com" //生产路径,生产用
IPCONFIG会被拼接为一些url,进行参数传递与验签用。
10.123.123.123:8081是本地电脑的ip:nginx监听的端口;
前端项目与后台项目都准备放在10.123.123.123上。(后台项目端口为8080,下方nginx会配置)
四、nginx配置方法
1.为了使得配置文件不太混乱,使用新建配置文件并引入的方法。
2.打开D:/nginx-1.18.0/conf/nginx.conf文件(文件路径为参考样例),在末尾增加以下语句:
include D://nginx-1.18.0//conf//upstream.conf;
include D://nginx-1.18.0//conf.d//*.conf;
这两句的意思是,让nginx.conf配置文件包含/conf/upstream.conf文件,以及conf.d文件夹下的所有.conf文件。
3.在conf文件夹中创建upstream.conf文件,用来写upstream信息,例如:
upstream project_survey {
server localhost:8080;
#server 10.123.123.123:8080;
}
配置后,可以供后续使用;
准备把后端项目放到本地计算机上,用8080端口访问,用project_survey表示;
因此这么写。
4.在D:/nginx-1.18.0/文件夹中创建conf.d文件夹,在其中创建一个my.conf文件,用来写具体的nginx映射,例如:
server {
listen 8081;
#listen 10.123.123.123:8081;
server_name 10.123.123.123;
#server_name www.hao1.com;
#server_name www.hao2.com;
#server_name localhost;
location / {
root D:\\project\\web;
try_files $uri $uri/ /index.html;
index index.html;
}
location /survey-wrong/web {
rewrite ^.+ http://localhost:8081/;
#rewrite ^.+ http://localhost:8081/ break;
}
location /project_survey {
expires -1;
proxy_set_header Host $http_host;
proxy_read_timeout 1800;
proxy_connect_timeout 1800;
proxy_send_timeout 1800;
proxy redirect off;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header REMOTE-HOST $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
client_max_body_size 2g;
proxy_pass http://project_survey;
}
location ~ .*\.(gif|jpg|jpeg|png|css|js|ico)$ {
root D:\\project\\web;
proxy_temp_path D:\\project\\web;
}
}
(1)listen 8081,说明nginx监听的是8081的请求。(如果配置了ip,那么server_name就不生效了)
(2)server_name,配置域名。
当收到一个url请求,nginx会先匹配listen中的ip;如果没有配置ip,再匹配server_name;然后匹配listen中的端口。
上方例子配置的server_name是10.123.123.123,listen是8081,因此收到http://10.123.123.123:8081的请求时,会走这个匹配规则,因为server_name与端口匹配成功了;
如果收到http://localhost:8081的请求时,也会走这个匹配规则,因为端口匹配成功了。
/*
如果本地ip不是10.123.123.123,那么不会收到形如http://10.123.123.123:8081的请求,只会收到http://localhost:8081的请求,或者http://本地IP:8081的请求,或者http://本地域名:8081的请求。
因此server_name可以配不配置都可以,只要listen配置了就可以了。
*/
参考:https://blog.csdn.net/qq_40737025/article/details/85053164
(3)location /中配置的D:\\project\\web,是前端项目所在的文件夹,其中web文件夹中有index.html文件以及static文件夹。这样使得请求url形如/的可以访问到本地的前端项目。
如访问http://localhost:8081/,可以访问到D:\\project\\web\\index.html。
root,将url中的头部分替换为指定部分,例如将http://localhost:8081替换为D:\\project\\web。
try_files,先寻找$uri,如果资源不存在,寻找$uri/,如果资源还不存在,寻找/index.html。
index,指定页面初始页,如果访问的url没有指定页面,则访问index.html。
参考:https://www.cnblogs.com/boundless-sky/p/9459775.html
(4)location /survey-wrong/web,表示请求url中包含/survey-wrong/web时,全部重定向为http://localhost:8081/,也就是重定向到首页。
其中,^.+是正则表达式,表示要匹配从第一个(^)开始、任意字符(.)、有1-多个(+)的内容;
匹配后,直接全部替换为指定地址。
因为rewrite进行了重定向,因此会从头开始重新匹配该nginx文件中配置的规则。(接着会走location /,从而访问到index.html)
/*
rewrite后还可以加参数,例如break表示后续不再匹配其余规则等。
参考:https://www.cnblogs.com/brianzhu/p/8624703.html
*/
(5)location /project_survey,表示当请求url包含/project_survey时,会被替换为proxy_pass中的内容,http://project_survey;
而project_survery会被替换为upstream中的localhost:8080,这个是后端项目的地址了。
例如访问
【http://localhost:8081/project_survery/survey/survey-api/login】
实际上访问的是
【http://localhost:8080/survey/survey-api/login】
nginx会将匹配规则以及之前的部分全部替换为proxy_pass中的内容,后半部分保留;
对【location /project_survey】来说,
会将【http://localhost:8081/project_survery】替换为【http://localhost:8080】,然后拼接上剩余的【/survey/survey-api/login】
就得到了【http://localhost:8080/survey/survey-api/login】
这样就访问到后台接口了。
(6)location ~ .*\.(gif|jpg|jpeg|png|css|js|ico)$ ,
[.*]表示任意字符、0-多个,
[\.]表示字符.,
[$]是字符串结尾位置,
也就是url请求中任意以.gif或.jpg或.jpeg或.png或.css或.js或.ico结尾的,走这个匹配规则。
root表示根路径要被替换为指定路径,
例如访问http://localhost:8081/static/ipConfig.js
会将http://localhost:8081替换为
D:\\project\\web
实际访问了D:\\project\\web/static/ipConfig.js
proxy_temp_path为存储承载从代理服务器接收到的数据的临时文件定义目录。
参考:http://www.weixueyuan.net/a/662.html
5.启动nginx,启动后台项目,访问前端网页或后台接口,测试前后台能否成功通信。
例如访问前端index.html,为【http://localhost:8081/】。
五、总结
1.确定后端接口url。(包含ip、端口、controller路径)
例如后端接口为:
http://127.1.2.3:8080/controller/login
2.修改前端全局变量,改为本地的ip+nginx监听的端口。
例如:
const IPCONFIG = "http://127.1.2.3:8081"
3.修改nginx配置文件,使得通过url可以访问到前端页面,并且前端页面可以发送请求给后台接口。
例如:
server {
listen 8081;
server_name localhost;
location / {
root D:\\project\\web;
try_files $uri $uri/ /index.html;
index index.html;
}
location /controller {
proxy_pass http://localhost:8080/controller;
}
location ~ .*\.(gif|jpg|jpeg|png|css|js|ico)$ {
root D:\\project\\web;
proxy_temp_path D:\\project\\web;
}
}
(1)访问http://localhost:8081/或者http://127.1.2.3:8081/,可以跳转到前端页面D:\\project\\web\\index.html
(2)前端页面发送请求给后台,规定url中要包含/controller,这样就会被nginx转换为真实的后台url,例如发送[http://127.1.2.3:8081/controller/login],会把[http://127.1.2.3:8081/controller]替换为[http://localhost:8080/controller],然后拼接剩余的[/login],就访问到了[http://127.1.2.3:8080/controller/login].
(3)因为本地ip是127.1.2.3,所以localhost等价于127.1.2.3.
六、后记
1.本文中的配置信息根据真实项目改编优化;如果有误,欢迎指出,作者会继续修改完善。
2.关于nginx配置中,location中末尾的【/】与proxy_pass中末尾的【/】的说明:
(1)如果这么写:
location /project_survey {
proxy_pass http://127.1.2.3:8080;
}
当访问http://localhost:8080/project_survey/abc/abc时,
由于存在【/project_survey】,匹配成功,nginx会将【/project_survey】及之前的部分全部替换为proxy_pass中的内容,并保留之后的部分,
相当于访问了http://127.1.2.3:8080/abc/abc。
(2)如果这么写:
location /project_survey/ {
proxy_pass http://127.1.2.3:8080/;
}
当访问http://localhost:8080/project_survey/abc/abc时,
由于存在【/project_survey/】,匹配成功,nginx会将【/project_survey/】及之前的部分全部替换为proxy_pass中的内容,并保留之后的部分,
相当于访问了http://127.1.2.3:8080/abc/abc。
(3)如果这么写:
location /project_survey {
proxy_pass http://127.1.2.3:8080/;
}
当访问http://localhost:8080/project_survey/abc/abc时,
由于存在【/project_survey】,匹配成功,nginx会将【/project_survey】及之前的部分全部替换为proxy_pass中的内容,并保留之后的部分,
相当于访问了http://127.1.2.3:8080//abc/abc,会多了一个【/】,倒是影响不太大。
(4)如果这么写,就有问题了:
location /project_survey/ {
proxy_pass http://127.1.2.3:8080;
}
当访问http://localhost:8080/project_survey/abc/abc时,
由于存在【/project_survey/】,匹配成功,nginx会将【/project_survey/】及之前的部分全部替换为proxy_pass中的内容,并保留之后的部分,
相当于访问了http://127.1.2.3:8080abc/abc,少了一个【/】,此时路径就会出错。
(5)所以概括为:要加都加,要不加都不加。
3.nginx中location包含正则表达式的说明
(1)包含正则表达式时,有时候会不按照最长匹配原则,而是按照匹配的先后顺序。如下:
upstream survey{
server 127.1.2.3:8080;
}
location ~ /survey(.*) {
set $name survey;
proxy_pass http://$name/survey1$1$is_args$args;
}
location ~ /survey/dev/search(.*) {
set $name survey;
proxy_pass http://$name/survey2/dev/search$1$is_args$args;
}
当访问http://localhost:8080/survey/dev/search/abc时,
本来希望被转发到:
http://127.1.2.3:8080/survey2/dev/search/abc
实际被转发到:
http://127.1.2.3:8080/survey1/dev/search/abc
原请求同时符合这两个正则表达式,但是nginx走了上方的第一个匹配,而不是走最长匹配原则。
如果想实现需求,需要将上方的匹配规则换一下位置,才会走survey2那个:
upstream survey{
server 127.1.2.3:8080;
}
location ~ /survey/dev/search(.*) {
set $name survey;
proxy_pass http://$name/survey2/dev/search$1$is_args$args;
}
location ~ /survey(.*) {
set $name survey;
proxy_pass http://$name/survey1$1$is_args$args;
}
(2)上方代码参数解释:
~:区分大小写匹配
(.*):匹配0-多个任意字符
$name:声明一个变量,值为upstream中的survey,下方的proxy_pass使用时会被转为ip。
$1:指location中的正则表达式匹配成功后的字符,即(.*)匹配得到的字符。
$is_args:请求中是否包含参数(key-value),如果有,则继续拼接后面的字符;没有则为空。
$args:请求中的参数,没有则为空。
4.nginx配置文件修改后没有生效的一种可能性
windows下,启动nginx.exe或者用cmd启动nginx后,nginx就会在后台运行;
之后关闭启动着nginx的cmd窗口、或者输入命令nginx -s stop,有可能并不会完全关闭nginx;
导致修改配置文件后、再次启动nginx时,配置文件没有生效——是因为请求走到了使用旧配置文件的仍然存活的nginx上。(此时打开任务管理器可以发现多个nginx进程,之前的+新启动的)
解决方法是cmd输入:【taskkill /IM nginx.exe /F】,可以关闭所有启动了的nginx;之后启动一个新的nginx即可。
开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!
更多推荐
所有评论(0)