uniapp实现tabs切换(可滑动)效果实例

<template>
	<view class="body-view">
		<!-- 使用scroll-view实现tabs滑动切换 -->
		<scroll-view class="top-menu-view" scroll-x="true" :scroll-into-view="tabCurrent">
			<view class="menu-topic-view" v-for="item in tabs" :id="'tabNum'+item.id" :key="(item.id - 1)" @click="swichMenu(item.id - 1)">
				<view :class="currentTab==(item.id - 1) ? 'menu-topic-act' : 'menu-topic'">
					<text class="menu-topic-text">{{item.name}}</text>
					<view class="menu-topic-bottom">
						<view class="menu-topic-bottom-color"></view>
					</view>
				</view>
			</view>
		</scroll-view>
		<!-- 内容 -->
		<swiper class="swiper-box-list" :current="currentTab" @change="swiperChange">
			<swiper-item class="swiper-topic-list" v-for="item in swiperDateList" :key="item.id">
				<view class="swiper-item">
					{{item.content}}
				</view>
			</swiper-item>
		</swiper>
	</view>
</template>
<script>
	export default {
		data() {
			return {
				tabs: [{
						id: 1,
						name: '推荐'
					},
					{
						id: 2,
						name: '交通交通'
					},
					{
						id: 3,
						name: '住房'
					},
					{
						id: 4,
						name: '社会保障'
					},
					{
						id: 5,
						name: '民生热点'
					},
					{
						id: 6,
						name: '即日头条'
					},
					{
						id: 7,
						name: '新闻联播'
					},
				],
				currentTab: 0,
				tabCurrent: 'tabNum1',
				// Tab切换内容
				swiperDateList: [{
						id: 1,
						content: '推荐'
					},
					{
						id: 2,
						content: '交通交通'
					},
					{
						id: 3,
						content: '住房'
					},
					{
						id: 4,
						content: '社会保障'
					},
					{
						id: 5,
						content: '民生热点'
					},
					{
						id: 6,
						content: '即日头条'
					},
					{
						id: 7,
						content: '新闻联播'
					},
				],
			}
		},
		onLoad() {
		},
		methods: {
			swichMenu(id) {
				this.currentTab = id
				console.log(11,id)
				this.tabCurrent = 'tabNum'+ id
			},
			swiperChange(e) {
				console.log(22,e.detail.current)
				let index = e.detail.current
				this.swichMenu(index)
			}
		}
	}
</script>
<style scoped lang="scss">
	.body-view {
		height: 100vh;
		width: 100%;
		display: flex;
		flex: 1;
		flex-direction: column;
		overflow: hidden;
		align-items: flex-start;
		justify-content: center;
	}
	.top-menu-view {
		display: flex;
		position: fixed;
		top: 100rpx;
		left: 0;
		white-space: nowrap;
		width: 100%;
		background-color: #FFFFFF;
		height: 86rpx;
		line-height: 86rpx;
		border-top: 1rpx solid #d8dbe6;
		.menu-topic-view {
			display: inline-block;
			white-space: nowrap;
			height: 86rpx;
			position: relative;
			.menu-topic-text {
				font-size: 30rpx;
				color: #303133;
				padding: 10rpx 40rpx;
			}
			// .menu-topic-act {
			// 	margin-left: 30upx;
			// 	margin-right: 10upx;
			// 	position: relative;
			// 	height: 100%;
			// 	display: flex;
			// 	align-items: center;
			// 	justify-content: center;
			// }
			.menu-topic-bottom {
				position: absolute;
				bottom: 0;
				width: 100%;
				.menu-topic-bottom-color {
					width: 40rpx;
					height: 4rpx;
				}
			}
			.menu-topic-act .menu-topic-bottom {
				display: flex;
				justify-content: center;
			}
			.menu-topic-act .menu-topic-bottom-color {
				background: #3d7eff;
			}
		}
	}
	.swiper-box-list {
		width: 100%;
		padding-top: 200rpx;
		flex:1;
		background-color: #FFFFFF;
		.swiper-topic-list {
		     width: 100%;
		 }
	}
</style>

传递access_token参数的正确方式

在OAuth中, access_token参数的传递如何才能更安全呢? 不知你有没有具体去研究过, 在此总结传递access_token的正确方式,

(所谓正确方式是指传递方式更安全, 更隐匿, 更不容易被网络拦截,网络攻击的方式)

在 spring-oauth-server 与 oauth2-shiro 中均支持以下提到的传递access_token的方式.

1. 通过Header传递 access_token; [推荐]

在请求URL的Header中, 添加header -> Authorization: bearer access_token,  示例代码(Java):postHandler.addHeader(“Authorization”, “bearer 0fe12a74-e613-4d1b-9785-f96847bad346”);

一般在代码中使用httpclient或URLConnection来实现,如Android, IOS客户端, 不适用于浏览器传递access_token

2.若请求URL使用POST方式提交, 将access_token放在请求body中而不是拼接在URL上, 示例代码(HTML):<form action=”db_table_description” method=”post”> <input type=”hidden” name=”access_token” value=”0fe12a74-e613-4d1b-9785-f96847bad346″/> <input type=”text” name=”username”/> <button type=”submit”>Submit</button> </form>

3.最后的选择, 通过URL拼接参数access_token, 示例代码:http://monkeyk.com/oauth_test?access_token=0fe12a74-e613-4d1b-9785-f96847bad346

一般使用在GET请求, POST等其他请求方式也支持

以上三种方式, 优先选择第一,第二种, 少用第三种方式.这些方式都是基于HTTP请求下所采用的.
更安全的传递access_token的方式是启用HTTPS连接,保证网络传输安全.

文件批量处理

  1. 批量重命名文件
    在这里最核心的就是os.listdir(),这个函数可以返回文件夹里所有文件的文件名. 有了这个我们才能进行其他操作,包括遍历。
import sys
import os                                 #OS库是文件处理中经常用到的库
import comtypes.client
#单个word转PDF
wdFormatPDF = 17
addr = 'C:\\Users\\wang\\Desktop\\G13-a\\'   #文件夹的绝对路径

names = os.listdir(addr)                        # 读取文件夹下的所有文件名

#进行遍历
for name in names:                         
    old_name = addr + name                 #注意rename函数里要放完整的路径,不能只放新旧名字
    new_name = addr + name[:13]            #这是当时甲方要求去除后缀,故只取旧题目的前13位
    os.rename (old_name, new_name)      

2. 文件分类
在tender的最后提交时,甲方要求按工作编号进行提交,这里需要按照register里的编号进行分类。

首先读取文档,观察数据形式

import pandas as pd
df = pd.read_excel('C:\\Users\\wang\\Desktop\\DCC_file.xlsx')
通过读取register发现我们需要根据“DCC”列进行分类,而对应的文件名在“NATIVE”列

接下来,需要完成的就是:(1) 获取每一类DCC编码下的文件名;(2)复制对应文件名至相应文件夹。

其中文档的复制移动主要依靠shutil模块.

import os
import shutil 

file_dir = r'C:\Users\wang\Desktop\All file'     #这里是存放所有文件的位置,它们需要进行分类

os.chdir(file_dir)    

numb = '10-01902-0002-050'   #这是其中一个DCC 编码
os.mkdir(numb)          #在当前路径下创建对应的文件夹 

filenames = df.loc[(df['DCC']== numb)]['NATIVE']    #利用loc函数筛选出 '10-01902-0002-050' 对应的所有文件名

# 这里操作是因为DC部门在命名文件时,Pdf, Word 和drawing的文件名后三位分别是“P00”,“W00”和“V00”,
# 所以通过这个,为对应的文件名加上对应的后缀,来构成完整的文件名

for name in filenames:      
 
    if name[-3] == 'X':
        fname = name + '.xls'
    if name[-3] == 'V':
        fname = name + '.dgn'
    if name[-3] == 'W':
        fname = name + '.doc'
    
    if os.path.exists(fname) ==1:        #判断文件是否存在
        shutil.copy(fname,numb)         #复制文件至文件夹
    else:
        print(fname)                     #输出不存在的文件名,用来检查

3. 批量Word转PDF

这个很常见的需求,需要将word转为PDF,但传统的Adobe转PDF需要一个一个点,比较慢,而网上大部分批量转PDF的软件基本收费,所以也是临时想起用python写个小程序。

这里呢,如前面提到的DC要求,转换得到的PDF,名字后三位需要时“P00″, 例如C860040001W00.doc 转换后的PDF应该是 C860040001W00.pdf.

所以这里目标有两个:

(1) 遍历,也就是达到批量处理的目的

(2) 重命名后三位为”P00″

这里用到的库是 comtypes.client,用它访问COM组件达到转PDF的目的。

import sys
import os
import comtypes.client

wdFormatPDF = 17

addr = 'C:\\Users\\wang\\Desktop\\doc\\10-01902-0002-711\\' # 目标路径,存放word的位置

doc_names = os.listdir(addr)  #读取文件夹里所有文件的名字
pdf_names = []              #将用来存放转换后PDF的名字

#开始遍历
for name in doc_names:     
    pdf_name = name[:10] +'P00.pdf'    #实现文件名转换:C860040001W00.doc 到 C860040001W00.pdf.
    pdf_names.append(pdf_name)  #存放新的PDF文档文件名
    in_file = os.path.abspath(addr + name)  #构造完整路径的文件名
    out_file = os.path.abspath(addr + pdf_name)
    word = comtypes.client.CreateObject('Word.Application')
    doc = word.Documents.Open(in_file)
    doc.SaveAs(out_file, FileFormat=wdFormatPDF)   #转换为PDF
    doc.Close()
    word.Quit()

有了这些小程序,基本可以处理工作中的文档操作了!感谢Python让我现在有时间喝咖啡写文章,而不用继续click,click,click.

实践美文 (一)

层次看鞋子,卫生看指甲

人品看眼神,自律看身材

格局看买单,家教看坐姿

性格看笑声,脾气看语气

境界看表情,态度看嘴角

pycharm激活

pycharm激活码最新提取方式:www.ajihuo.com

如果不好用了可以到www.ajihuo.com中提取)

提取试卷题目及题号和选项

以下代码的功能是为了实现提取题目中的题号,题目,如是选择题则提取选项,具体代码如下:

// 提取试卷题目及题号
$text = "11. 已知椭圆 $C: \frac{x^{2}}{a^{2}}+\frac{y^{2}}{b^{2}}=1(a>b>0)$ 的左、右焦点分别为 $F_{1}, F_{2}$, 点 $M$ 是椭圆 $C$ 上任意一点, 且 $\overrightarrow{M F_{1}} \cdot \overrightarrow{M F_{2}}$ 的取值范围为 $[2,3]$. 当点 $M$ 不在 $x$ 轴上时, 设 $\triangle M F_{1} F_{2}$ 的内切圆半径为 $m$, 外接圆 半径为 $n$, 则 $m n$ 的最大值为 ( ) A. $\frac{1}{3}$ B. $\frac{1}{2}$ C. $\frac{2}{3}$ D. 1
12. 设函数 $f(x)=\mathrm{e}^{3 \ln -x}-x^{2}-(a-4) x-4$, 若 $f(x) \leqslant 0$, 则 $a$ 的最小值为 $(\quad)$ A. e B. $\frac{1}{\mathrm{e}}$ C. $\frac{1}{\mathrm{e}^{2}}$ D. $\frac{4}{\mathrm{e}^{2}}$
13. $\left(x^{2}-\frac{2}{x}\right)^{6}$ 的展开式中常数项是___.
14. 数列 $\left\{a_{n}\right\}$ 的前 $n$ 项和为 $S_{n}$, 若 $a_{1}=1, a_{n+1}=S_{n}$, 则 $a_{n}=$
15. 在棱长为 2 的正方体 $A B C D-A_{1} B_{1} C_{1} D_{1}$ 中, 若 $E$ 为棱 $B B_{1}$ 的中点, 则平面 $A E C_{1}$ 截正方体 $A B C D-A_{1} B_{1} C_{1} D_{1}$ 的截面面积为___
16. 若函数 $f(x)=\left|x-\sqrt{4-4 x^{2}}-2\right|-2 a-1$ 有两个零点, 则实数 $a$ 的取值范围为___";


$pattern = "/(\d+)\.\s(.*?)(?=\d+\.|\Z)/ms";
preg_match_all($pattern, $text, $matches, PREG_SET_ORDER);


// print_r($matches);

foreach ($matches as $match) {

	$item['number'] = $match[1];
	$item['content'] = $match[2];
    // $number = $match[1];
    // $title = $match[2];


    // echo "题号:$number;题目:$title\n";

    $regex = '/[A-D]\.(.*?)(?=[A-D]\.|\Z)/ms';

    # $regex = '/^[A-D]\.\s(.+)(?=[A-D]+\.|\Z)$/ms';
	if(preg_match_all($regex, $item['content'], $matches2))
	{
		// print_r($matches2);
		$item['options'] = $matches2[1];

		$item['content'] = str_replace($matches2[0],'',$item['content']);
	}


	print_r($item);	

}

运行效果如下:

不合规范的html段落php处理细则

最近业余时间在维护一个rss聚合应用,就发现很多网站feed的条目摘要存在各种问题,用strip_tags一刀切吧,对摘要的段落和样式扭曲了

例如:有一些网站的摘要是截断输出,例如指定的摘要长度截断,这样会导致摘要中出现非闭合的html标签,下面的摘要是一个例子:

$str=<<<EOF
<P>  【手机中国 导购】时间过得真快,转眼就我们就已经度过了2013年的上半年,而我们也悄无声息地老了半岁。不过随着时间的流逝,手机行业也在快速的进步着,其发展速度之快可以用日新月异来形容了。</P>
 <P align=center><IMG style="BORDER-BOTTOM: black 1px solid; BORDER-LEFT: black 1px solid; BORDER-TOP: black 1px solid; BORDER-RIGHT: black 1px solid" alt="2.2GHz骁龙800四核 上半年热门机N宗最 " align=1 src="http://imgm.cnmo.com/cnmo_product/18_500x375/698/ceFYnyzZgUijQ.jpg"><BR>2012年的旗舰机型HTC Butterfly</P>
 <P>  回首2012年,手机市场还处于一个相对比较矛盾的时期,国产手机的初露锋芒以及国际大牌的推陈出新,让消费者有些摸不清头脑。到了2013年之后,虽然这个现象还存在着,唯一不同的就是消费者已经逐渐习惯了这个现状,整个手机行业也是在不断的向前进。</P>
 <P>  毫不夸张的说,今天刚刚上市了一款各个方面都表现突出的机皇级旗舰机,也许明天就被其他品牌旗舰所取代,这是一个不争的事实。但相比来说,每个品牌每款旗舰也都有自己的特长,比如处理器主频高或是屏幕尺寸大等等。</P>
 <P align=center><IMG style="BORDER-BOTTOM: black 1px solid; BORDER-LEFT: black 1px solid; BORDER-TOP: black 1px solid; BORDER-RIGHT: black 1px solid" alt="6.44英寸屏骁龙800 上半年热门机N宗最 " src="http://img.cnmo-img.com.cn/905/904155.jpg"></P>
 <P>  俗话说风水轮流转,曾经榜上有名的强机也许今天就名落孙山,物竞天择,适者生存这句话说的不无道理。今天笔者也给大家统计了2013上半年最新智能手机N宗最,下面就让我们一起看一下吧。<STRONG>
EOF;


上面的摘要有几点不合法:
1.html标签大写
2.最后一个strong由于截断没有正常闭合,strong的父标签p丢失
3.标签的属性中出现了一些样式属性和定义,像:align,style

下面说一说它们的影响
2:如果不加处理的输出会造成页面样式混乱,像非正常闭合的strong浏览器会自动把它后面的输出算成它的子元素.
3:样式定义可能影响你的页面样式,图片溢出你的摘要容器
1:不会造成视觉上的错误,但它会影响你的html合法性

下面来说说处理方法
3:可以用正则把属性给替换掉,像

preg_replace("/<([a-z][a-z0-9]*)(?:[^>]*(\ssrc=['\"][^'\"]*['\"]))?[^>]*?(\/?)>/i",'<$1$2$3>',$str);


2:可以用DOMNode::C14N方法来规范,它可以把丢失的标签给补上,只不过<img />会变成<img></img>

等等:
1.为什么不用strip_tags来处理呢?
是可以,虽然它也可以保留指定的标签,但我会把哪些不安全的标签交给htmlentities

2.好像dom可以删除属性吧!
对,这是下面要讲的,综合处理1,2,3的代码如下

$doc = new DOMDocument();
$doc->formatOutput=false;

$doc->loadHTML(mb_convert_encoding($str, 'HTML-ENTITIES', 'UTF-8'));
$nodes = $doc->getElementsByTagName('*');
foreach ( $nodes as $node ) {
	$delAtts=array();
	//找到节点的所有属性
	$nodeN=$node->tagName;
	$nodeAtts=$node->attributes;
	foreach($nodeAtts as $attN=>$att){
		//是img保留src属性
		if(strtolower($attN)=='src' && strtolower($nodeN)=='img') continue;
		//不是直接删除所有属性
		array_push($delAtts,$attN);
	}
	foreach($delAtts as $A){
		$node->removeAttribute($A);
	}
}
$doc->saveHTML();
$pstr=$doc->GetElementsByTagName('body')->item(0)->C14N();
//clear empty tag
$pstr=preg_replace('/<(\w+)>(\s| )*<\/\1>/i',"",$pstr);


大体上已经OK了,$pstr的内容是body包裹的$str,最后只需要把body解决掉就可以.
最后要说的有几点:
1.一定不要在遍历属性时把它删除,例如:img有三个属性style,src,alt,它只会删除掉style,style后面的并不会删除
2.一定不要用saveHTML()的返回值作为后续处理的内容,后果是汉字变成如下的东东:

&#12288;&#12288;&#22238;&#39318;2012&#24180;&#65292;&#25163;&#26426;&#24066;&#22330;&#36824

也不要怕,只需要再调一次

mb_convert_encoding($str, 'UTF-8','HTML-ENTITIES')


就ok了,为了偷懒,所以它的返回值不要用

3.$doc->GetElementsByTagName('body')->item(0)->C14N();


也可以换成:

$doc->documentElement->C14N();


只不过返回值不光有body还有html标签,不在乎的话也可以用它,毕竟比GetElementsByTagName更省事

nginx 配置跨域 status code 200,但是报错CORS error,实际还是跨域了

原文链接:https://blog.csdn.net/m0_46496355/article/details/123706879

昨天才完成的ubuntu通过nginx发布vue线上项目
结果今天调试后台接口的时候就出现了跨域问题,由于线上是在同一个域名下,所以在线上项目中调用接口的时候不会出现跨域问题,主要的就是本地调试的时候出现了跨域问题;

解决方法:
在nginx配置中加上这一段配置

add_header Access-Control-Allow-Methods ''; 
add_header Access-Control-Max-Age 3600; 
add_header Access-Control-Allow-Credentials true; 
add_header Access-Control-Allow-Origin '';
add_header Access-Control-Allow-Headers $http_access_control_request_headers always;
 if ($request_method = OPTIONS) {
     return 200;
 }
 // 在server下的location中配置

配置完记得重启一下
这时候已经可以访问了,但是调用接口的时候会发现,在network中status code返回的是200,但是state显示的是CORS error。如下

这是为什么,我不理解~~
这时候其实nginx中已经配置成功了。
经过不断咨询度娘之后,看到了一个比较可信的原因:浏览器的js引擎解析的时候也是遵循同源策略的,由于本地浏览器地址跟访问的地址不在同一个域名下,所以返回了跨域的错误。
知道原因就比较简单了,可以参考我前面的文章前后端本地联调跨域,虽然已经不是本地联调了,但是使用的方法是一样的,利用proxy代理转发来骗过浏览器。
按照前后端本地联调跨域配置完成proxy代理之后,再去访问就可以了。

正式项目是不应该配置Access-Control-Allow-Methods ‘*’的,不安全,因为不管是谁配置个proxy都能访问到你的接口了,并且关于上面的nginx配置我也没有解释,解释了也是误导读者,因为我对其中的概念也比较模糊,目前正在探索学习中,需要深入了解的请自行百度,O(∩_∩)O哈哈哈~

每天分享一个踩坑经历~~~

Nginx配置使用详解

原文链接:https://blog.csdn.net/qq_46312987/article/details/118895520

1、常用命令
需要进入nginx的安装目录中的sbin目录(也可以配置环境变量,在任何目录都可以执行下面的命令),里面有一个nginx脚本文件

1、启动nginx
./nginx
2、关闭nginx
./nginx -s stop
3、重新加载nginx (nginx.conf)
./nginx -s reload
4、查看版本号
./nginx -v

2、Nginx配置文件(nginx.conf)
2.1概述
默认在Linux上安装的Nginx,配置文件在安装的nginx目录下的conf目录下,名字叫做nginx.conf

nginx.conf主要由三部分组成

全局块,
events块
http块
2.2配置文件结构

2.3真实配置文件概览

# 全局快

user nobody;

worker_processes 1;

error_log logs/error.log;

error_log logs/error.log notice;

error_log logs/error.log info;

pid logs/nginx.pid;


events块

events {
worker_connections 1024;
}

http块

http {
——————————————————————————# http全局块
include mime.types;
default_type application/octet-stream;

#log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
#                  '$status $body_bytes_sent "$http_referer" '
#                  '"$http_user_agent" "$http_x_forwarded_for"';

#access_log  logs/access.log  main;

sendfile        on;
#tcp_nopush     on;

#keepalive_timeout  0;
keepalive_timeout  65;

#gzip on;

server块

server {

server全局块

    listen       80;
    server_name  localhost;

    #charset koi8-r;

    #access_log  logs/host.access.log  main;

location块

    location / {
        root   html;
        index  index.html index.htm;
    }

    #error_page  404              /404.html;

    # redirect server error pages to the static page /50x.html
    #
    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   html;
    }

    # proxy the PHP scripts to Apache listening on 127.0.0.1:80
    #
    #location ~ \.php$ {
    #    proxy_pass   http://127.0.0.1;
    #}

    # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
    #
    #location ~ \.php$ {
    #    root           html;
    #    fastcgi_pass   127.0.0.1:9000;
    #    fastcgi_index  index.php;
    #    fastcgi_param  SCRIPT_FILENAME  /scripts$fastcgi_script_name;
    #    include        fastcgi_params;
    #}

    # deny access to .htaccess files, if Apache's document root
    # concurs with nginx's one
    #
    #location ~ /\.ht {
    #    deny  all;
    #}

}

可以配置多个server块

2.2全局块
就是配置文件从头开始到events块之间的内容,主要设置的是影响nginx服务器整体运行的配置指令比如worker_process, 值越大,可以支持的并发处理量也越多,但是还是和服务器的硬件相关

2.3events块
events 块涉及的指令主要影响 Nginx 服务器与用户的网络连接,常用的设置包括是否开启对多 work process下的网络连接进行序列化,是否允许同时接收多个网络连接,选取哪种事件驱动模型来处理连接请求,每个 word process 可以同时支持的最大连接数等。

上述例子就表示每个 work process 支持的最大连接数为 1024.
这部分的配置对 Nginx 的性能影响较大,在实际中应该灵活配置

2.4http块
包括http全局块,以及多个server块

2.4.1http全局块
http 全局块配置的指令包括文件引入、 MIME-TYPE 定义、日志自定义、连接超时时间、单链接请求数上限等。

2.4.2server块
这块和虚拟主机有密切关系,虚拟主机从用户角度看,和一台独立的硬件主机是完全一样的,该技术的产生是为了节省互联网服务器硬件成本。
每个 http 块可以包括多个 server 块,而每个 server 块就相当于一个虚拟主机
而每个 server 块也分为全局 server 块,以及可以同时包含多个 location 块。
2.4.2.1server全局块
最常见的配置是本虚拟机主机的监听配置和本虚拟主机的名称或 IP 配置。

#这一行表示这个server块监听的端口是80,只要有请求访问了80端口,此server块就处理请求

listen 80;
# 表示这个server块代表的虚拟主机的名字
server_name localhost;
1
2
3
4
2.4.2.2location块
一个 server 块可以配置多个 location 块。
主要作用是根据请求地址路径的匹配,匹配成功进行特定的处理
这块的主要作用是基于 Nginx 服务器接收到的请求字符串(例如 server_name/uri-string),对虚拟主机名称(也可以是 IP 别名)之外的字符串(例如 前面的 /uri-string)进行匹配,对特定的请求进行处理。地址定向、数据缓存和应答控制等功能,还有许多第三方模块的配置也在这里进行。

表示如果请求路径是/就是用这个location块进行处理

location / {
root html;
index index.html index.htm;
}
1
2
3
4
5
3、反向代理
3.1正向代理与反向代理概述
3.1.1正向代理
正向代理代理的是客户端,需要在客户端配置,我们访问的还是真实的服务器地址

3.1.2反向代理
反向代理代理的是服务器端,客户端不需要任何配置,客户端只需要将请求发送给反向代理服务器即可,代理服务器将请求分发给真实的服务器,获取数据后将数据转发给你。隐藏了真实服务器,有点像网关。

3.1.3区别与总结
正向代理与反向代理的区别

最根本的区别是代理的对象不同

正向代理代理的是客户端,需要为每一个客户端都做一个代理服务器,客户端访问的路径是目标服务器
反向代理代理的是真实服务器,客户端不需要做任何的配置,访问的路径是代理服务器,由代理服务器将请求转发到真实服务器
3.2配置
3.2.1应用一
实现效果访问http://192.168.80.102:80(Nginx首页),最终代理到http://192.168.80.102:8080(Tomcat首页)

首先启动一台Tomcat服务器(已经安装了Tomcat)

进入Tomcat的安装目录下的bin目录下,使用./startup.sh命令,启动Tomcat

在Nginx的配置文件中进行配置

1、新建一个server块,在server全局块中配置监听80端口

2、在location块中配置 / 路径请求代理到tomcat的地址

下面三个配置的含义就是 ,当访问Linux的http://192.168.80.102:80这个地址时,由于配置Nginx监听的是80端口,所以会进入这个server块进行处理,然后看你的访问路径,根据location块配置的不同路径进入对应的处理,由于配置了/请求,所以进入/的location处理,然后配置了proxy_pass,所以进行代理到指定的路径。

server {

监听端口80 即当访问服务器的端口是80时,进入这个server块处理

    listen       80;

server_name当配置了listen时不起作用

    server_name  localhost;

location后面代表访问路径 当是/ 请求时 代理到tomcat的地址

    location / {

使用 proxy_pass(固定写法)后面跟要代理服务器地址

        proxy_pass http://192.168.80.102:8080;
    }

}

经过测试,当输入http://192.168.80.102:80时,Nginx给我们代理到了Tomcat,所以显示了Tomcat的页面,即配置成功

3.2.2应用二
应用一访问的是/路径,给我们代理到指定的服务器

应用二实现:

让Nginx监听9001端口
我们实现当访问http://192.168.80.102:9001/edu(Nginx地址)时,nginx给我们代理到http://192.168.80.102:8081,
当访问http://192.168.80.102:9001/vod时,nginx给我们代理到http://192.168.80.102:8082
启动两个Tomcat服务器

端口分别是8081和8082,
在8001的服务器的webapps下创建一个edu目录,编写一个test.html
在8002的服务器的webapps下创建一个vod目录,编写一个test.html
由于虚拟机的ip是192.168.80.102,所以保证访问http://192.168.80.102:8081/edu/test.html和http://192.168.80.102:8082/vod/test.html 都可以成功访问

编写Nginx配置文件

server {

监听9001端口

    listen       9001;

进行路径匹配,匹配到edu代理到8081

    location ~/edu/ {
        proxy_pass http://192.168.80.102:8081;
    }

进行路径匹配,匹配到vod代理到8082

    location ~/vod/ {
        proxy_pass http://192.168.80.102:8082;
    }

}

经过测试,访问成功!!!

3.3location详解

3.4server_name作用及访问流程
客户端通过域名访问服务器时会将域名与被解析的ip一同放在请求中。当请求到了nginx中时。nginx会先去匹配ip,如果listen中没有找到对应的ip,就会通过域名进行匹配,匹配成功以后,再匹配端口。当这三步完成,就会找到对应的server的location对应的资源。

CSDN

4、负载均衡
4.1概述
简单来说就是使用分布式的场景,将原先的一台服务器做成一个集群,然后将请求分发到各个服务器上,但是,如何将请求每次转发到不同的服务器呢,Nginx就可以做到。原来我们都是直接访问服务器,现在我们可以使用Nginx进行反向代理,然后我们访问Nginx,由Nginx将我们的请求分发到不同的服务器上,以实现负载均衡

4.2配置
实现:

访问http://192.168.80.102:80/edu/test.html,Nginx将请求分配到8081和8082两台tomcat服务器上。

1、开启两台tomcat

分别在webapps下的edu下编写一个test.html,文件内容可以不一致,为了明显看到负载均衡的效果

2、配置文件

在http块中的全局块中配置

upstream固定写法 后面的myserver可以自定义

upstream myserver{
server 192.168.80.102:8081;
server 192.168.80.102:8082;
}

server配置

server {
  # 监听80端口
    listen 80;   
    #location块
    location / {

反向代理到上面的两台服务器 写上自定义的名称

    proxy_pass http://myserver;
    }
}


访问http://192.168.80.102:80/edu/test.html时,可以分发到8081和8082两台服务器,测试成功

4.3负载均衡规则
4.3.1轮询(默认)
每个请求按时间顺序逐一分配到不同的后端服务器,如果后端服务器 down 掉,能自动剔除

4.3.2weight权重
weight 代表权重默认为 1,权重越高被分配的客户端越多

upstream myserver {
server 192.168.80.102:8081 weight=1 ;
server 192.168.80.102:8082 weight=2 ;
}
server {
listen 80;
location / {
proxy_pass http://myserver;
}

4.3.3ip_hash
每个请求按访问 ip 的 hash 结果分配,这样每个访客固定访问一个后端服务器,可以解决session问题

配置负载均衡的服务器和端口

upstream myserver {
server 192.168.80.102:8081;
server 192.168.80.102:8082;
ip_hash;
}
server {
listen 80;
location / {
proxy_pass http://myserver;
}
}

4.3.4fair
按后端服务器的响应时间来分配请求,响应时间短的优先分配。

配置负载均衡的服务器和端口

upstream myserver {
server 192.168.80.102:8081;
server 192.168.80.102:8082;
fair;
}
server {
listen 80;
location / {
proxy_pass http://myserver;
}
}

5、动静分离
5.1概述
将静态资源 css html js等和动态资源(jsp servlet)进行分开部署,我们可以将静态资源直接部署在专门的服务器上,也可以直接放在反向代理服务器上(Nginx)所在在的服务器上 然后动态资源还是部署在服务器上,如tomcat。
然后请求来的时候,静态资源从专门的静态资源服务器获取,动态资源还是转发到后端服务器上。

5.2配置
准备工作:在Linux的根目录下/的staticResource目录下创建两个文件夹,分别是www和image,在www目录下创建一个okc.html,在image目录下放一张ttt.jpg

实现效果,访问http://192.168.80.102:80/www/okc.html和http://192.168.80.102:80/image/ttt.img时可以成功访问资源

配置

server {
listen 80;
# 当访问路径带了www时,进入这个location处理,去/staticResource目录下对应的www目录 去找okc.html
# 即最终实现访问到这个路径
# http://192.168.80.102:80/staticResource/www/okc.html
location /www/{
root /staticResource/;
index index.html index.htm;
}
# 跟上面一样
location /image/{
root /staticResource/;
}
}
经过测试,成功访问

5.3root与alias区别与访问路径
alias 实际访问文件路径不会拼接URL中的路径
root 实际访问文件路径会拼接URL中的路径
示例如下:

alias

location ^~ /sta/ {
alias /usr/local/nginx/html/static/;
}

请求:http://test.com/sta/sta1.html
实际访问:/usr/local/nginx/html/static/sta1.html 文件
root

location ^~ /tea/ {
root /usr/local/nginx/html/;
}

请求:http://test.com/tea/tea1.html
实际访问:/usr/local/nginx/html/tea/tea1.html 文件
6、高可用集群
6.1概述
主备架构

作为备用服务器,当主服务器宕掉后,配置的备用服务器自动切换,
keepalived提供虚拟ip,对外我们访问的是虚拟ip,绑定了主备的ip

6.2配置
6.2.1环境搭建
开启两台虚拟机,都安装上nginx和keepalived

两台虚拟机的ip分别是 192.168.80.102 192.168.80.103

安装keepalived,直接使用yum安装

yum install -y keepalived

默认安装在/etc下,生成一个keepalived目录,里面有一个keepalived.conf文件,后面配置的主要就是这个配置文件

6.2.2配置