一、前言

前后端分离后,如果想将前后端项目都放在同一台电脑上启动与开发,可以使用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即可。

 

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐