nginx访问静态资源的相关配置
nginx访问静态资源的相关配置
引言
需要通过nginx服务读取静态文件,需要配置nginx.conf的相关配置,如虚拟主机配置server、location配置。
其实nginx.conf的配置文件是由指令集组成的,指令集分为:简单指令、模块指令。
简单的指令由名字和参数组成,中间用空格隔开,末尾用分号(;)结尾。
模块指令和简单指令有着相同的结构,但是末尾的分号(;)改为了花括号({})
如果模块指令中含有其它的模块指令,那么该模块指令就叫做上下文(context),比如http模块指令、server模块指令。
1、server模块指令
server模块指令是nginx用来配置虚拟主机的
什么是虚拟主机?
server模块指令中有三个重要的指令:listen 监听端口号,server_name 服务名,location映射解析文件地址
2、location模块指令
向server模块指令添加location模块指令如下:
location / {
root 文件地址
}
如下:
解释这段指令:
location中指定的“/html”会和请求的uri做比较,如果符合,那么uri会加载到root指令集中指定的路径“E:\javaWork\XXXX\0521”后面。
举个例子说明:如果在浏览器的地址栏写上/html/23/24/xx.html的话,那么因为uri里含有html,那么就能够匹配到这个location指定的“/html"。
所以完整的映射文件解析地址是:E:\javaWork\XXXX\0521\html\23\24\xx.html
前半部分加下划线的就是root指令集指定的路径,后半部分是匹配得到的uri。
(1)一个目录可以对应多个location指令集
这样的话,一个文件的目录可以写成多个location指令进行匹配,因为最后访问的话是根据root指令集所指的地址 加上 location指定的uri拼接的
就拿上面E:\javaWork\XXXX\0521\html\23\24这个目录通过root指令对应的的地址和location指定的uri拼接能够得到的方式有:(举几种,不举全)
(1)root E:\javaWork\XXXX\0521; location \html\23\24;
(2)root E:\javaWork\XXXX\0521\html; location \23\24;
(3)root E:\javaWork\XXXX\0521\html\23; location \24;
如果server指令集写的端口是8084,server_name是localhost。
那么上面的三种root指令集对应的地址和location对应的uri拼接情况,可以通过以下三种方式取到 \24 目录下对应的静态文件。
(1)localhost:8084/html/23/24/xx.html (匹配第一个对应的location指令集)
(2)localhost:8084/23/24/xx.html (匹配第二个对应的location指令集)
(3)localhost:8084/24/xx.html (匹配第三个对应的location指令集)
(2)优先更全的uri匹配原则(精确匹配原则)
如果两个不同的目录有以下两个location指令对应
(1)
location /0521 {
root E:/java/jvm;
}
(2)
location /0521/doc {
root D:/java/gc;
}
这时,如果在浏览器地址栏访问localhost:8084/0521/doc/hello.html
(1)假设E:/java/jvm/0521目录下有doc文件夹,并且里面有hello.html静态文件。
(2)假设D:/java/gc/0521/doc目录下,有hello.html静态文件。
这一步是不是给弄懵逼了?请求的uri符合这两个location指令的匹配,那么具体匹配哪一个呢?
那就是按照精确匹配原则,哪个location对应的uri更加和请求的uri精确,那么就匹配哪个location指令集。也就是说,在上面那个问题中,会匹配第二个location指令集。
证明上面结论:
(1)创建测试文件
D盘符文件,及hello.html内容:
E盘符文件,及hello.html内容:
(2)给nginx.conf增加两个location指令集
(3)重新加载nginx.conf配置文件
使用 nginx -s reload 命令重新加载nginx.conf配置文件
(4)浏览器地址栏访问:localhost:8084/0521/doc/hello.html
对吧?匹配的就是指向D盘的那个location。 如果所匹配的location并不是你所期望的那样或者诸如此类的其它问题,那么你可以去查看logs目录下的error.log和access.log这两个日志文件。
(3)一个请求始终只匹配最精确的location
到这里,再抛出一个问题,接着上面的操作,精确匹配确实是匹配到了指向D盘的location,那么,如果我要匹配的文件在doc目录下,并没有呢?nginx会对浏览器发出的请求如何处理,是直接抛出404吗?
我们可以尝试着将第二个location对应的目录下的hello.html进行删除,再去访问localhost:8084/0521/doc/hello.html;看看是否会访问E盘下的hello.html
结果显然,并不会去匹配第一个映射E盘的location,也就是说,如果uri已经匹配到当前这个精确location的话,那么如果没有需要访问的文件,那么直接抛出404,而不会去继续匹配其它的不精确的location。
(4)额外注意
这段话是个人总结的,网上没见着相关结论。
location的映射文件地址是root对应地址加上location的uri。(E:\javaWork\XXXX\0521\html\23\24)
如果要访问这个地址 (E:\javaWork\XXXX\0521\html\23\24) 的前一层或前几层目录下的文件,那么只能通过匹配另外的location。并不能通过相对路径(..)的形式访问到。
我们让一个文件地址匹配两个location指令,如下图:
(1)匹配的第一个location,这个location的文件映射地址是:E:\javaWork\XXX\0521\html
(2)匹配的第二个location,这个location的文件映射地址是:E:\javaWork\XXX\0521\html\static\html\self_test
我们可以看见页面报错了,是由于页面用到的jquery没有正确引入。
这是为什么?因为磁盘上没有吗?可是第一个location映射文件地址是可以的,所以显然 并不是 这个原因。
这是因为nginx通过这个location,只读取了E:\javaWork\XXX\0521\html\static\html\self_test目录下的文件进来。而jquery文件,并不在这个目录下。
也就是说,nginx只会读取location映射的文件地址下的所有文件,除此目录外的文件一律获取不到。