精华内容
下载资源
问答
  • 访问一个URL经历了哪些过程

    万次阅读 多人点赞 2019-04-03 00:18:35
    从大致上来讲经历了 客户端获取URL - >...从用户在浏览器输入域名开始,到web页面加载完毕,这是一个说复杂不复杂,说简单不简单的过程,下文暂且把这个过程称作网页加载过程。下面我将依靠自己的经验,总结一...

    从大致上来讲经历了

    客户端获取URL - > DNS解析 - > TCP连接 - >发送HTTP请求 - >服务器处理请求 - >返回报文 - >浏览器解析渲染页面 - > TCP断开连接

    1、概要

    从用户在浏览器输入域名开始,到web页面加载完毕,这是一个说复杂不复杂,说简单不简单的过程,下文暂且把这个过程称作网页加载过程。下面我将依靠自己的经验,总结一下整个过程。如有错漏,欢迎指正。

    阅读本文需要读者已有一定的计算机知识,了解TCP、DNS等。

    2、分析

    众所周知,打开一个网页的过程中,浏览器会因页面上的css/js/image等静态资源会多次发起连接请求,所以我们暂且把这个网页加载过程分成两部分:

    html(jsp/php/aspx) 页面加载(假设存在简单的Nginx负载均衡)
    css/js/image等 网页静态资源加载(假设使用CDN)

    2.1 页面加载

    先上一张图,直观明了地让大家了解下基本流程,然后我们再逐一分析。
    在这里插入图片描述

    2.1.1 DNS解析

    什么是DNS解析?当用户输入一个网址并按下回车键的时候,浏览器得到了一个域名。而在实际通信过程中,我们需要的是一个IP地址。因此我们需要先把域名转换成相应的IP地址,这个过程称作DNS解析。

    1. 浏览器首先搜索浏览器自身缓存的DNS记录。

    或许很多人不知道,浏览器自身也带有一层DNS缓存。Chrome 缓存1000条DNS解析结果,缓存时间大概在一分钟左右。

    (Chrome浏览器通过输入:chrome://net-internals/#dns 打开DNS缓存页面)

    1. 如果浏览器缓存中没有找到需要的记录或记录已经过期,则搜索hosts文件和操作系统缓存。

    在Windows操作系统中,可以通过 ipconfig /displaydns 命令查看本机当前的缓存。

    通过hosts文件,你可以手动指定一个域名和其对应的IP解析结果,并且该结果一旦被使用,同样会被缓存到操作系统缓存中。

    Windows系统的hosts文件在%systemroot%\system32\drivers\etc下,linux系统的hosts文件在/etc/hosts下。

    3) 如果在hosts文件和操作系统缓存中没有找到需要的记录或记录已经过期,则向域名解析服务器发送解析请求。

    其实第一台被访问的域名解析服务器就是我们平时在设置中填写的DNS服务器一项,当操作系统缓存中也没有命中的时候,系统会向DNS服务器正式发出解析请求。这里是真正意义上开始解析一个未知的域名。

    一般一台域名解析服务器会被地理位置临近的大量用户使用(特别是ISP的DNS),一般常见的网站域名解析都能在这里命中。

    4) 如果域名解析服务器也没有该域名的记录,则开始递归+迭代解析。

    这里我们举个例子,如果我们要解析的是mail.google.com

    首先我们的域名解析服务器会向根域服务器(全球只有13台)发出请求。显然,仅凭13台服务器不可能把全球所有IP都记录下来。所以根域服务器记录的是com域服务器的IP、cn域服务器的IP、org域服务器的IP……。如果我们要查找.com结尾的域名,那么我们可以到com域服务器去进一步解析。所以其实这部分的域名解析过程是一个树形的搜索过程。
    在这里插入图片描述
    根域服务器告诉我们com域服务器的IP。

    接着我们的域名解析服务器会向com域服务器发出请求。根域服务器并没有mail.google.com的IP,但是却有google.com域服务器的IP。

    接着我们的域名解析服务器会向google.com域服务器发出请求。…

    如此重复,直到获得mail.google.com的IP地址。

    为什么是递归:问题由一开始的本机要解析mail.google.com变成域名解析服务器要解析mail.google.com,这是递归。

    为什么是迭代:问题由向根域服务器发出请求变成向com域服务器发出请求再变成向google.com域发出请求,这是迭代。

    5) 获取域名对应的IP后,一步步向上返回,直到返回给浏览器。

    2.1.2 发起TCP请求

    浏览器会选择一个大于1024的本机端口向目标IP地址的80端口发起TCP连接请求。经过标准的TCP握手流程,建立TCP连接。
    在这里插入图片描述
    客户端:

    (应用层开始)获取URL,通过负责域名解析的DNS服务获取网址的IP地址,根据HTTP协议生成HTTP请求报文(应用层结束)

    (传输层开始)根据TCP协议连接从客户端到服务端(通过三次握手)客户端给服务端发送一个带SYN(同步)标志的数据包给客户端,然后客户端接收到信息再给客户端回传一个带有SYN / ACK(确认)标志的数据包以示传达确认信息,客户求最后端的再传送一个带ACK标志的数据包,代表“握手”结束,连接成功.TCP协议在把请求报文按序号分割成多个报文段(传输层结束)

    (网络层开始)根据IP协议(传输数据),ARP协议(获取MAC地址),OSPF协议(选择最优路径),搜索服务器地址,一边中转一边传输数据(网络层结束)

    (数据链路层开始)到达后通过数据链路层,物理层负责0,1比特流与物理设备电压高低,光的闪灭之间的互换。数据链路层负责将0,1序列划分为数据帧从一个节点传输到临近的另一个节点,这些节点是通过MAC来唯一标识的(MAC,物理地址,一个中主机会有一个MAC地址)。 (数据链路层结束)

    服务端

    通过数据链路层 - >通过网络层 - >再通过传输层(根据TCP协议接收请求报文并重组报文段) - >再通过应用层(通过HTTP协议对请求的内容进行处理) - >再通过应用层 - >传输层 - >网络层 - >数据链路层 - >到达客户端

    客户端

    通过数据链路层 - >网络层 - >传输层(根据TCP协议接收响应报文并重组) - >应用层(HTTP协议对响应进行处理) - >浏览器渲染页面 - >断开连接协议四次挥手)

    四次挥手

    主动方发送标志位:(ACK + FIN)+(发送序号= 200 +确认序号= 500)第一次挥手

    被动方接收后发送标志位:ACK +(发送序号=主动方确认序号500 +确认序号=主动方发送序号+1201)第二次挥手

    标志位:(ACK + FIN)+(发送序号=主动方确认序号+1 501)第三次挥手

    主动方接收后发送标志位:(ACK)+(发送序号=被动方的确认序号201 +确认序号=被动方的发生序号+1502)
    在这里插入图片描述

    2.1.3 发起HTTP请求

    其实这部分又可以称为前端工程师眼中的HTTP,它主要发生在客户端。发送HTTP请求的过程就是构建HTTP请求报文并通过TCP协议中发送到服务器指定端口(HTTP协议80/8080, HTTPS协议443)。HTTP请求报文是由三部分组成: 请求行, 请求报头和请求正文。

    请求行

    格式如下:
    Method Request-URL HTTP-Version CRLF

    eg: GET index.html HTTP/1.1
    

    常用的方法有: GET, POST, PUT, DELETE, OPTIONS, HEAD。

    TODO:

    GET和POST有什么区别?

    请求报头

    请求报头允许客户端向服务器传递请求的附加信息和客户端自身的信息。
    PS: 客户端不一定特指浏览器,有时候也可使用Linux下的CURL命令以及HTTP客户端测试工具等。
    常见的请求报头有: Accept, Accept-Charset, Accept-Encoding, Accept-Language, Content-Type, Authorization, Cookie, User-Agent等。

    上图是使用Chrome开发者工具截取的对百度的HTTP请求以及响应报文,从图中可以看出,请求报头中使用了Accept, Accept-Encoding, Accept-Language, Cache-Control, Connection, Cookie等字段。Accept用于指定客户端用于接受哪些类型的信息,Accept-Encoding与Accept类似,它用于指定接受的编码方式。Connection设置为Keep-alive用于告诉客户端本次HTTP请求结束之后并不需要关闭TCP连接,这样可以使下次HTTP请求使用相同的TCP通道,节省TCP连接建立的时间。

    请求正文

    当使用POST, PUT等方法时,通常需要客户端向服务器传递数据。这些数据就储存在请求正文中。在请求包头中有一些与请求正文相关的信息,例如: 现在的Web应用通常采用Rest架构,请求的数据格式一般为json。这时就需要设置Content-Type: application/json。

    服务器处理请求并返回HTTP报文

    自然而然这部分对应的就是后端工程师眼中的HTTP。后端从在固定的端口接收到TCP报文开始,这一部分对应于编程语言中的socket。它会对TCP连接进行处理,对HTTP协议进行解析,并按照报文格式进一步封装成HTTP Request对象,供上层使用。这一部分工作一般是由Web服务器去进行,我使用过的Web服务器有Tomcat, Jetty和Netty等等。

    HTTP响应报文也是由三部分组成: 状态码, 响应报头和响应报文。

    状态码

    状态码是由3位数组成,第一个数字定义了响应的类别,且有五种可能取值:

    • 1xx 【消息】服务器收到请求,需要请求者继续执行操作
    • 2xx 【成功】请求已成功被服务器接收、理解、并接受。
    • 3xx 【重定向】客户端需要采取进一步的操作以完成请求
    • 4xx 【客户端请求错误】客户端错误,请求包含语法错误或无法完成请求
    • 5xx 【服务器错误】服务器在处理请求的过程中发生了错误

    平时遇到比较常见的状态码有:200, 204, 301, 302, 304, 400, 401, 403, 404, 422, 500等:

    • 200 OK //客户端请求成功
    • 304 Not Modified // 未修改。所请求的资源未修改,服务器返回此状态码时,不会返回任何资源
    • 400 Bad Request //客户端请求有语法错误,不能被服务器所理解
    • 401 Unauthorized // 当前请求要求用户的身份认证
    • 403 Forbidden // 服务器理解请求客户端的请求,但是拒绝执行此请求
    • 404 Not Found //请求资源不存在,输入了错误的URL
    • 500 Internal Server Error //服务器发生不可预期的错误
    • 503 Server Unavailable // 由于超载或系统维护,服务器暂时的无法处理客户端的请求。一段时间后可能恢复正常

    更多可见:http://www.webmasterhome.cn/httpstatus/

    TODO:

    301和302有什么区别?

    HTTP缓存

    响应报头

    常见的响应报头字段有: Server, Connection…。

    响应报文

    服务器返回给浏览器的文本信息,通常HTML, CSS, JS, 图片等文件就放在这一部分。

    2.1.4 负载均衡

    什么是负载均衡?当一台服务器无法支持大量的用户访问时,将用户分摊到两个或多个服务器上的方法叫负载均衡。

    什么是Nginx?Nginx是一款面向性能设计的HTTP服务器,相较于Apache、lighttpd具有占有内存少,稳定性高等优势。

    负载均衡的方法很多,Nginx负载均衡、LVS-NAT、LVS-DR等。这里,我们以简单的Nginx负载均衡为例。关于负载均衡的多种方法详情大家可以Google一下。

    Nginx有4种类型的模块:core、handlers、filters、load-balancers。

    我们这里讨论其中的2种,分别是负责负载均衡的模块load-balancers和负责执行一系列过滤操作的filters模块。

    1) 一般,如果我们的平台配备了负载均衡的话,前一步DNS解析获得的IP地址应该是我们Nginx负载均衡服务器的IP地址。所以,我们的浏览器将我们的网页请求发送到了Nginx负载均衡服务器上。

    2) Nginx根据我们设定的分配算法和规则,选择一台后端的真实Web服务器,与之建立TCP连接、并转发我们浏览器发出去的网页请求。

    Nginx默认支持 RR轮转法 和 ip_hash法 这2种分配算法。

    前者会从头到尾一个个轮询所有Web服务器,而后者则对源IP使用hash函数确定应该转发到哪个Web服务器上,也能保证同一个IP的请求能发送到同一个Web服务器上实现会话粘连。

    也有其他扩展分配算法,如:

    fair:这种算法会选择相应时间最短的Web服务器

    url_hash:这种算法会使得相同的url发送到同一个Web服务器

    3) Web服务器收到请求,产生响应,并将网页发送给Nginx负载均衡服务器。

    4) Nginx负载均衡服务器将网页传递给filters链处理,之后发回给我们的浏览器。
    在这里插入图片描述
      而Filter的功能可以理解成先把前一步生成的结果处理一遍,再返回给浏览器。比如可以将前面没有压缩的网页用gzip压缩后再返回给浏览器。

    2.1.5 浏览器渲染

    1) 浏览器根据页面内容,生成DOM Tree。根据CSS内容,生成CSS Rule Tree(规则树)。调用JS执行引擎执行JS代码。

    2) 根据DOM Tree和CSS Rule Tree生成Render Tree(呈现树)

    3) 根据Render Tree渲染网页

    浏览器是一个边解析边渲染的过程。首先浏览器解析HTML文件构建DOM树,然后解析CSS文件构建渲染树,等到渲染树构建完成后,浏览器开始布局渲染树并将其绘制到屏幕上。这个过程比较复杂,涉及到两个概念: reflow(回流)和repain(重绘)。DOM节点中的各个元素都是以盒模型的形式存在,这些都需要浏览器去计算其位置和大小等,这个过程称为relow;当盒模型的位置,大小以及其他属性,如颜色,字体,等确定下来之后,浏览器便开始绘制内容,这个过程称为repain。页面在首次加载时必然会经历reflow和repain。reflow和repain过程是非常消耗性能的,尤其是在移动设备上,它会破坏用户体验,有时会造成页面卡顿。所以我们应该尽可能少的减少reflow和repain。

    JS的解析是由浏览器中的JS解析引擎完成的。JS是单线程运行,也就是说,在同一个时间内只能做一件事,所有的任务都需要排队,前一个任务结束,后一个任务才能开始。但是又存在某些任务比较耗时,如IO读写等,所以需要一种机制可以先执行排在后面的任务,这就是:同步任务(synchronous)和异步任务(asynchronous)。JS的执行机制就可以看做是一个主线程加上一个任务队列(task queue)。同步任务就是放在主线程上执行的任务,异步任务是放在任务队列中的任务。所有的同步任务在主线程上执行,形成一个执行栈;异步任务有了运行结果就会在任务队列中放置一个事件;脚本运行时先依次运行执行栈,然后会从任务队列里提取事件,运行任务队列中的任务,这个过程是不断重复的,所以又叫做事件循环(Event loop)。

    浏览器在解析过程中,如果遇到请求外部资源时,如图像,iconfont,JS等。浏览器将重复1-6过程下载该资源。请求过程是异步的,并不会影响HTML文档进行加载,但是当文档加载过程中遇到JS文件,HTML文档会挂起渲染过程,不仅要等到文档中JS文件加载完毕还要等待解析执行完毕,才会继续HTML的渲染过程。原因是因为JS有可能修改DOM结构,这就意味着JS执行完成前,后续所有资源的下载是没有必要的,这就是JS阻塞后续资源下载的根本原因。CSS文件的加载不影响JS文件的加载,但是却影响JS文件的执行。JS代码执行前浏览器必须保证CSS文件已经下载并加载完毕。

    2.2 网页静态资源加载

    以阿里巴巴的淘宝网首页的logo为例,其url地址为 img.alicdn.com/tps/i2/TB1bNE7LFXXXXaOXFXXwFSA1XXX-292-116.png_145x145.jpg

    我们清楚地看到了url中有cdn字样。

    什么是CDN?如果我在广州访问杭州的淘宝网,跨省的通信必然造成延迟。如果淘宝网能在广东建立一个服务器,静态资源我可以直接从就近的广东服务器获取,必然能提高整个网站的打开速度,这就是CDN。CDN叫内容分发网络,是依靠部署在各地的边缘服务器,使用户就近获取所需内容,降低网络拥塞,提高用户访问响应速度。

    接下来的流程就是浏览器根据url加载该url下的图片内容。本质上是浏览器重新开始第一部分的流程,所以这里不再重复阐述。区别只是负责均衡服务器后端的服务器不再是应用服务器,而是提供静态资源的服务器。

    Web优化

    上面部分主要介绍了一次完整的请求对应的过程,了解该过程的目的无非就是为了Web优化。在谈到Web优化之前,我们回到一个更原始的问题,Web前端的本质是什么。我的理解是: 将信息快速并友好的展示给用户并能够与用户进行交互。快速的意思就是在尽可能短的时间内完成页面的加载,试想一下当你在淘宝购买东西的时候,淘宝页面加载了10几秒才显示出物品,这个时候你还有心情去购买吗?怎么快速的完成页面的加载呢?优雅的学院派雅虎给出了常用的一些手段,也就是我们熟悉的雅虎34条军规。这34军规实际上就是围绕请求过程进行的一些优化方式。

    如何尽快的加载资源?答案就是能不从网络中加载的资源就不从网络中加载,当我们合理使用缓存,将资源放在浏览器端,这是最快的方式。如果资源必须从网络中加载,则要考虑缩短连接时间,即DNS优化部分;减少响应内容大小,即对内容进行压缩。另一方面,如果加载的资源数比较少的话,也可以快速的响应用户。当资源到达浏览器之后,浏览器开始进行解析渲染,浏览器中最耗时的部分就是reflow,所以围绕这一部分就是考虑如何减少reflow的次数。

    展开全文
  • 一个图片url访问后直接下载怎样实现 先看代码 downloadIamge(imgsrc, name) {//下载图片地址和图片名 let image = new Image(); // 解决跨域 Canvas 污染问题 image.setAttribute("cro...

    一个图片url访问后直接下载怎样实现


    先看代码

    downloadIamge(imgsrc, name) {//下载图片地址和图片名  
      let image = new Image();  
      // 解决跨域 Canvas 污染问题  
      image.setAttribute("crossOrigin", "anonymous");  
      image.onload = function() {  
        let canvas = document.createElement("canvas");  
        canvas.width = image.width;  
        canvas.height = image.height;  
        let context = canvas.getContext("2d");  
        context.drawImage(image, 0, 0, image.width, image.height);  
        let url = canvas.toDataURL("image/png"); //得到图片的base64编码数据  
        let a = document.createElement("a"); // 生成一个a元素  
        let event = new MouseEvent("click"); // 创建一个单击事件  
        a.download = name || "photo"; // 设置图片名称  
        a.href = url; // 将生成的URL设置为a.href属性  
        a.dispatchEvent(event); // 触发a的单击事件  
      };  
      image.src = imgsrc;  
    },  
    
    

    JavaScript 下载文件

      fetch('http://somehost/somefile.zip').then(res => res.blob().then(blob => {  
      var a = document.createElement('a');  
      var url = window.URL.createObjectURL(blob);  
      var filename = 'myfile.zip';  
      a.href = url;  
      a.download = filename;  
      a.click();  
      window.URL.revokeObjectURL(url);  
    }))  
    
    

    你可能会问,何必这么麻烦呢?直接写成下面这样不就好了:

    嗯,对于这种写法,我只能说,你做的太正确了!如果你要下载的是已经存在服务器上面的静态文件的话,那么写成这样是最方便的。浏览器会帮你处理整个下载过程,不需要你干涉。如果你用 blob 的方式来下载文件的话,会有下面这些限制的:

    限制一:不同浏览器对 blob 对象有不同的限制

    BrowserConstructs asFilenamesMax Blob SizeDependencies
    Firefox 20+BlobYes800 MiBNone
    Firefox < 20data: URINon/aBlob.js
    ChromeBlobYes500 MiBNone
    Chrome for AndroidBlobYes500 MiBNone
    EdgeBlobYes?None
    IE 10+BlobYes600 MiBNone
    Opera 15+BlobYes500 MiBNone
    Opera < 15data: URINon/aBlob.js
    Safari 6.1+*BlobNo?None
    Safari < 6data: URINon/aBlob.js

    限制二:构建完 blob 对象后才会转换成文件

    这一点限制对小文件(几十kb)可能没什么影响,但对稍微大一点的文件影响就很大了。试想,用户要下载一个 100mb 的文件,如果他点击了下载按钮之后没看到下载提示的话,他肯定会继续按,等他按了几次之后还没看到下载提示时,他就会抱怨我们的网站,然后离开了。

    然而事实上下载的的确确发生了,只是要等到下载完文件之后才能构建 blob 对象,再转化成文件。而且,用户再触发多几次下载就会造成一些资源上的浪费。

    因此,如果是要下载大文件的话,还是推荐直接创建一个 <a> 标签拉~
    写 html 也好,写 JavaScript 动态创建也好,用自己喜欢的方式去创建就好了。

    ## 为什么要用 JavaScript 下载文件

    好拉,说了半天,其实我们一直说的都是:「不要用 JavaScript 下载文件拉,限制多多,又不好用,直接用 html 就好拉,简单方便又快捷」这个论调。
    事实上也确实如此,但有些时候我们确实需要通过 JavaScript 来做一些处理。

    权限校验

    有些时候,我们需要对下载做一些限制,最常见的就是权限校验了,如检查该用户是否有下载的权限,是否有高速下载的权限等等。这时候,我们可以利用 JavaScript 做一些预处理。如:

    fetch('http://somehost/check-permission', options).then(res => {  
      if (res.code === 0) {  
      var a = document.createElement('a');  
      var url = res.data.url;  
      var filename = 'myfile.zip';  
      a.href = url;  
      a.download = filename;  
      a.click();  
      } else {  
      alert('You have no permission to download the file!');  
      }  
    });  
    
    

    在这个例子里面,我们没有用 blob 来构建 URL,而是通过后端服务器来计算出用户的下载链接,然后再利用之前提到的动态创建 <a> 标签的方式来实现下载,很简单吧!

    转载自:https://www.cnblogs.com/liulinjie/p/10245483.html

    转载于:https://my.oschina.net/sansenlian/blog/3072568

    展开全文
  • 判断一个URL是否可以正常访问

    千次阅读 2018-08-16 15:51:16
    判断一个URL是否可以访问,主要用于双域名问题

    判断一个url是否可以访问,主要用于双域名问题

    $.ajax({
            url: 'www.xxx.xx',
            type: 'GET',
            complete: function(response) {
            if(response.status == 200) {
                location.href = 'http://xxx.xxx.xxx';
            } else {
                location.href = 'http://xxx.xxx.xxx';
            }
            }
            });

    complete与success区别

    //可以是单参,如上面
    complete: function (XMLHttpRequest, textStatus) {  
        //textStatus的值:success,notmodified,nocontent,error,timeout,abort,parsererror  
    },  
    error: function (XMLHttpRequest, textStatus, errorThrown) {  
        //textStatus的值:null, timeout, error, abort, parsererror  
        //errorThrown的值:收到http出错文本,如 Not Found 或 Internal Server Error.  
    }  
    
    success : 当请求成功时调用的函数。这个函数会得到一个参数:从服务器返回的数据。当请求成功时调用函数,即status==200。
    
    complete :当请求完成时调用的函数。这个函数会得到两个参数:XMLHttpRequest对象和一个描述请求成功的类型的字符串。当请求完成时调用函数,即status==404403302...。
    
    
    ## 状态码 ##
    100-继续。  
    101-切换协议。  
    2xx-成功  
    这类状态代码表明服务器成功地接受了客户端请求。  
    200-确定。客户端请求已成功。  
    201-已创建。  
    202-已接受。  
    203-非权威性信息。  
    204-无内容。  
    205-重置内容。  
    206-部分内容。  
    3xx-重定向  
    客户端浏览器必须采取更多操作来实现请求。例如,浏览器可能不得不请求服务器上的不同的页面,或通过代理服务器重复该请求。  
    301-对象已永久移走,即永久重定向。  
    302-对象已临时移动。  
    304-未修改。  
    307-临时重定向。  
    4xx-客户端错误  
    发生错误,客户端似乎有问题。例如,客户端请求不存在的页面,客户端未提供有效的身份验证信息。400-错误的请求。  
    401-访问被拒绝。IIS定义了许多不同的401错误,它们指明更为具体的错误原因。这些具体的错误代码在浏览器中显示,但不在IIS日志中显示:  
    401.1-登录失败。  
    401.2-服务器配置导致登录失败。  
    401.3-由于ACL对资源的限制而未获得授权。  
    401.4-筛选器授权失败。  
    401.5-ISAPI/CGI应用程序授权失败。  
    401.7–访问被Web服务器上的URL授权策略拒绝。这个错误代码为IIS6.0所专用。  
    403-禁止访问:IIS定义了许多不同的403错误,它们指明更为具体的错误原因:  
    403.1-执行访问被禁止。  
    403.2-读访问被禁止。  
    403.3-写访问被禁止。  
    403.4-要求SSL。  
    403.5-要求SSL128。  
    403.6-IP地址被拒绝。  
    403.7-要求客户端证书。  
    403.8-站点访问被拒绝。  
    403.9-用户数过多。  
    403.10-配置无效。  
    403.11-密码更改。  
    403.12-拒绝访问映射表。  
    403.13-客户端证书被吊销。  
    403.14-拒绝目录列表。  
    403.15-超出客户端访问许可。  
    403.16-客户端证书不受信任或无效。  
    403.17-客户端证书已过期或尚未生效。  
    403.18-在当前的应用程序池中不能执行所请求的URL。这个错误代码为IIS6.0所专用。  
    403.19-不能为这个应用程序池中的客户端执行CGI。这个错误代码为IIS6.0所专用。  
    403.20-Passport登录失败。这个错误代码为IIS6.0所专用。  
    404-未找到。  
    404.0-(无)–没有找到文件或目录。  
    404.1-无法在所请求的端口上访问Web站点。  
    404.2-Web服务扩展锁定策略阻止本请求。  
    404.3-MIME映射策略阻止本请求。  
    405-用来访问本页面的HTTP谓词不被允许(方法不被允许)  
    406-客户端浏览器不接受所请求页面的MIME类型。  
    407-要求进行代理身份验证。  
    412-前提条件失败。  
    413–请求实体太大。  
    414-请求URI太长。  
    415–不支持的媒体类型。  
    416–所请求的范围无法满足。  
    417–执行失败。  
    423–锁定的错误。  
    5xx-服务器错误  
    服务器由于遇到错误而不能完成该请求。  
    500-内部服务器错误。  
    500.12-应用程序正忙于在Web服务器上重新启动。  
    500.13-Web服务器太忙。  
    500.15-不允许直接请求Global.asa。  
    500.16–UNC授权凭据不正确。这个错误代码为IIS6.0所专用。  
    500.18–URL授权存储不能打开。这个错误代码为IIS6.0所专用。  
    500.100-内部ASP错误。  
    501-页眉值指定了未实现的配置。  
    502-Web服务器用作网关或代理服务器时收到了无效响应。  
    502.1-CGI应用程序超时。  
    502.2-CGI应用程序出错。application.  
    503-服务不可用。这个错误代码为IIS6.0所专用。  
    504-网关超时。  
    505-HTTP版本不受支持。  
    FTP  
    1xx-肯定的初步答复  
    这些状态代码指示一项操作已经成功开始,但客户端希望在继续操作新命令前得到另一个答复。  
    110重新启动标记答复。  
    120服务已就绪,在nnn分钟后开始。  
    125数据连接已打开,正在开始传输。  
    150文件状态正常,准备打开数据连接。  
    2xx-肯定的完成答复  
    一项操作已经成功完成。客户端可以执行新命令。200命令确定。  
    202未执行命令,站点上的命令过多。  
    211系统状态,或系统帮助答复。  
    212目录状态。  
    213文件状态。  
    214帮助消息。  
    215NAME系统类型,其中,NAME是AssignedNumbers文档中所列的正式系统名称。  
    220服务就绪,可以执行新用户的请求。  
    221服务关闭控制连接。如果适当,请注销。  
    225数据连接打开,没有进行中的传输。  
    226关闭数据连接。请求的文件操作已成功(例如,传输文件或放弃文件)。  
    227进入被动模式(h1,h2,h3,h4,p1,p2)。  
    230用户已登录,继续进行。  
    250请求的文件操作正确,已完成。  
    257已创建“PATHNAME”。  
    3xx-肯定的中间答复  
    该命令已成功,但服务器需要更多来自客户端的信息以完成对请求的处理。331用户名正确,需要密码。  
    332需要登录帐户。  
    350请求的文件操作正在等待进一步的信息。  
    4xx-瞬态否定的完成答复  
    该命令不成功,但错误是暂时的。如果客户端重试命令,可能会执行成功。421服务不可用,正在关闭控制连接。如果服务确定它必须关闭,将向任何命令发送这一应答。  
    425无法打开数据连接。  
    426Connectionclosed;transferaborted.  
    450未执行请求的文件操作。文件不可用(例如,文件繁忙)。  
    451请求的操作异常终止:正在处理本地错误。  
    452未执行请求的操作。系统存储空间不够。  
    5xx-永久性否定的完成答复  
    该命令不成功,错误是永久性的。如果客户端重试命令,将再次出现同样的错误。500语法错误,命令无法识别。这可能包括诸如命令行太长之类的错误。  
    501在参数中有语法错误。  
    502未执行命令。  
    503错误的命令序列。  
    504未执行该参数的命令。  
    530未登录。  
    532存储文件需要帐户。  
    550未执行请求的操作。文件不可用(例如,未找到文件,没有访问权限)。  
    551请求的操作异常终止:未知的页面类型。  
    552请求的文件操作异常终止:超出存储分配(对于当前目录或数据集)。  
    553未执行请求的操作。不允许的文件名。  
    常见的FTP状态代码及其原因  
    150-FTP使用两个端口:21用于发送命令,20用于发送数据。状态代码150表示服务器准备在端口20上打开新连接,发送一些数据。  
    226-命令在端口20上打开数据连接以执行操作,如传输文件。该操作成功完成,数据连接已关闭。  
    230-客户端发送正确的密码后,显示该状态代码。它表示用户已成功登录。  
    331-客户端发送用户名后,显示该状态代码。无论所提供的用户名是否为系统中的有效帐户,都将显示该状态代码。  
    426-命令打开数据连接以执行操作,但该操作已被取消,数据连接已关闭。  
    530-该状态代码表示用户无法登录,因为用户名和密码组合无效。如果使用某个用户帐户登录,可能键入错误的用户名或密码,也可能选择只允许匿名访问。如果使用匿名帐户登录,IIS的配置可能拒绝匿名访问。  
    550-命令未被执行,因为指定的文件不可用。例如,要GET的文件并不存在,或试图将文件PUT到您没有写入权限的目录。 
    展开全文
  • 如何将一个URL转换为一个URL

    万次阅读 多人点赞 2018-04-21 14:40:41
    前几天整理面试题的时候,有一道试题是《如何将一个很长的URL转换为一个短的URL,并实现他们之间的相互转换?》,现在想起来这是一个绝对不简单的问题,需要考虑很多方面,今天和大家一起学习研究一下! 短网址:...

    一、前言

    前几天整理面试题的时候,有一道试题是《如何将一个很长的URL转换为一个短的URL,并实现他们之间的相互转换?》,现在想起来这是一个绝对不简单的问题,需要考虑很多方面,今天和大家一起学习研究一下!

    短网址:顾名思义,就是将长网址缩短到一个很短的网址,用户访问这个短网址可以重定向到原本的长网址(也就是还原的过程)。这样可以达到易于记忆、转换的目的,常用于有字数限制的微博、二维码等等场景。

    关于短URL的使用场景,举个简单的例子来说明一下,看一下业务中使用短URL的重要性!

    二、短地址使用场景

    1、新浪微博

    我们在新浪微博上发布网址的时候,微博会自动判别网址,并将其转换,例如:https://t.cn/RuPKzRW。为什么要这样做的?

    这是因为微博限制字数为140字一条,那么如果我们需要发一些链接上去,但是这个链接非常的长,以至于将近要占用我们内容的一半篇幅,这肯定是不能被允许的或者说用户体验很差的,所以短网址应运而生了,短网址这种服务可以说是在微博出现之后才流行开来的!往下看:

    (1)首先,我先发一条微博带有一个URL地址:
    这里写图片描述
    (2)然后,看他转换之后显示的效果是什么样子的哪?
    这里写图片描述
    (3)查看对应页面元素的HTML源码如下:
    这里写图片描述
    (4)可以看出:https://blog.csdn.net/xlgen157387/article/details/79863301 被转换为:http://t.cn/RuPKzRW,此时你访问http://t.cn/RuPKzRW是可以定位到https://blog.csdn.net/xlgen157387/article/details/79863301,也就是实现了转换。

    2、短网址二维码

    网址在转换成短网址时,也可以生成相应的短网址二维码,短网址二维码的应用,二维码核心解决的是跨平台、跨现实的数据传输问题;而且二维码跟应用场景结合之后,所能解决的问题会越来越多。

    (1)短网址二维码相比短链接更方便,能少输入,尽量少输入,哪怕只是少点一下键盘,都是有意义的。

    (2)二维码只是扫描一个简单的链接,打开的却是一个世界。想象一下,用手机购买售货机里商品,二维码扫描是略快于从用手机找到该售货机并找到该商品的,而且这种操作相对于搜索/查找而言不是更优雅吗?

    (3)所有商超里面的商品,都是使用条码来确定商品的唯一性的,去买单的时候都是扫描条码。试想,如果里面加入了更多产品的生产日期、厂家、流转途径、原材料等等信息,是不是厉害了呢?特别是针对食品信息的可追溯上,二维码应用场景更广泛。

    三、短地址的好处

    除了上述场景中,我们将长地址转换为短地址的使用场景的优点(压缩URL长度)之外,短地址还具有很多实际场景中的优点,例如:

    (1)节省网址长度,便于社交化传播,一个是让URL更短小,传播更方便,尤其是URL中有中文和特殊字符,短网址解决很长的URL难以记忆不利于传播的问题;

    (2)短网址在我们项目里可以很好的对开放以及对URL进行管理。有一部分网址可以会涵盖性、暴力、广告等信息,这样我们可以通过用户的举报,完全管理这个连接将不出现在我们的应用中,对同样的URL通过加密算法之后,得到的地址是一样的;

    (3)方便后台跟踪点击量、地域分布等用户统计。我们可以对一系列的网址进行流量,点击等统计,挖掘出大多数用户的关注点,这样有利于我们对项目的后续工作更好的作出决策;

    (4)规避关键词、域名屏蔽手段、隐藏真实地址,适合做付费推广链接;

    (5)当你看到一个淘宝的宝贝连接后面是200个“e7x8bv7c8bisdj”这样的字符的时候,你还会觉得舒服吗。更何况微博字数只有140字,微博或短信里,字数不够,你用条短网址就能帮你腾出很多空间来;

    四、短网址服务提供平台

    目前,国内网又很多提供短地址服务的平台,例如:

    等等还有很多,这个可以搜索一下就会有很多!但是一个注意的是,如果使用某一个平台的短地址服务,一定要保证长期可靠的服务,不然一段时间失效了,我们以前已经转换的URL就完了!

    这里以百度例,将我们上述博客的地址转换为短地址如下所示:

    这里写图片描述

    当然,对于我们的业务来说,如果自己可以提供自己的短URL服务那才是更好的,不需要受制于人!(中国芯片需要崛起!!!)

    五、关于如何生成短地址URL的讨论

    关于短地址URL如何生成方式的,网上有很多方式,有基于映射的,有基于Hash的,有基于签名的,但是总的来说并不能满足绝大部分场景的使用,或者说是一种错误的设计方式。这里不再重复造轮子!以下是知乎用户iammutex关于该问题的探讨,截图过来和大家一起学习一下:

    这里写图片描述

    作者:iammutex
    链接:https://www.zhihu.com/question/29270034/answer/46446911
    来源:知乎
    著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
    

    六、生成短地址URL需要注意的

    看到上述知乎用户iammutex关于如何正确生成短地址URL的探讨,我们知道了,可以通过发号器的方式正确的生成短地址,生成算法设计要点如下:

    (1)利用放号器,初始值为0,对于每一个短链接生成请求,都递增放号器的值,再将此值转换为62进制(a-zA-Z0-9),比如第一次请求时放号器的值为0,对应62进制为a,第二次请求时放号器的值为1,对应62进制为b,第10001次请求时放号器的值为10000,对应62进制为sBc。

    (2)将短链接服务器域名与放号器的62进制值进行字符串连接,即为短链接的URL,比如:t.cn/sBc。

    (3)重定向过程:生成短链接之后,需要存储短链接到长链接的映射关系,即sBc -> URL,浏览器访问短链接服务器时,根据URL Path取到原始的链接,然后进行302重定向。映射关系可使用K-V存储,比如Redis或Memcache。

    七、生成短地址之后如何跳转哪?

    对于该部分的讨论,我们可以认为他是整个交互的流程,具体的流程细节如下:

    (1)用户访问短链接:http://t.cn/RuPKzRW;

    (2)短链接服务器t.cn收到请求,根据URL路径RuPKzRW获取到原始的长链接(KV缓存数据库中去查找):https://blog.csdn.net/xlgen157387/article/details/79863301;

    (3)服务器返回302状态码,将响应头中的Location设置为:https://blog.csdn.net/xlgen157387/article/details/79863301;

    (4)浏览器重新向https://blog.csdn.net/xlgen157387/article/details/79863301发送请求;

    (5)返回响应;

    八、短地址发号器优化方案

    1、算法优化

    采用以上算法,如果不加判断,那么即使对于同一个原始URL,每次生成的短链接也是不同的,这样就会浪费存储空间(因为需要存储多个短链接到同一个URL的映射),如果能将相同的URL映射成同一个短链接,这样就可以节省存储空间了。主要的思路有如下两个:

    方案1:查表

    每次生成短链接时,先在映射表中查找是否已有原始URL的映射关系,如果有,则直接返回结果。很明显,这种方式效率很低。

    方案2:使用LRU本地缓存,空间换时间

    使用固定大小的LRU缓存,存储最近N次的映射结果,这样,如果某一个链接生成的非常频繁,则可以在LRU缓存中找到结果直接返回,这是存储空间和性能方面的折中。

    2、可伸缩和高可用

    如果将短链接生成服务单机部署,缺点一是性能不足,不足以承受海量的并发访问,二是成为系统单点,如果这台机器宕机则整套服务不可 用,为了解决这个问题,可以将系统集群化,进行“分片”。

    在以上描述的系统架构中,如果发号器用Redis实现,则Redis是系统的瓶颈与单点,因此,利用数据库分片的设计思想,可部署多个发号器实例,每个实例负责特定号段的发号,比如部署10台Redis,每台分别负责号段尾号为0-9的发号,注意此时发号器的步长则应该设置为10(实例个数)。

    另外,也可将长链接与短链接映射关系的存储进行分片,由于没有一个中心化的存储位置,因此需要开发额外的服务,用于查找短链接对应的原始链接的存储节点,这样才能去正确的节点上找到映射关系。

    九、如何用代码实现短地址

    1、使用随机序列生成短地址

    说到这里终于说到重点了,很多小伙伴已经按捺不住了,不好意思让大家失望了,这只是一片简单的文章,并不能把这么繁杂的一个系统演示清楚!秉着不要重复造轮子的原则,这里给出一个为数不多还算可以的实现短地址的开源项目:urlshorter

    注意:urlshorter本身还是基于随机的方式生成短地址的,并不算是一个短地址发号器,因此会有性能问题和冲突的出现,和知乎用户iammutex 描述的实现方式还是有区别的!而关于短地址发号器的方式目前还没有找到更好的开源项目可供参考!

    项目地址:https://gitee.com/tinyframework/urlshorter

    这里写图片描述

    2、使用SnowFlake发号器生成短地址

    实现参考:
    https://github.com/beyondfengyu/SnowFlake
    http://www.wolfbe.com/detail/201611/381.html

    Twitter的雪花算法SnowFlake,使用Java语言实现。

    SnowFlake算法用来生成64位的ID,刚好可以用long整型存储,能够用于分布式系统中生产唯一的ID, 并且生成的ID有大致的顺序。 在这次实现中,生成的64位ID可以分成5个部分:

    0 - 41位时间戳 - 5位数据中心标识 - 5位机器标识 - 12位序列号
    

    5位数据中心标识、5位机器标识这样的分配仅仅是当前实现中分配的,如果业务有其实的需要,可以按其它的分配比例分配,如10位机器标识,不需要数据中心标识。

    Java代码实现如下:

    /**
     * 进制转换工具,最大支持十进制和62进制的转换
     * 1、将十进制的数字转换为指定进制的字符串;
     * 2、将其它进制的数字(字符串形式)转换为十进制的数字
     * @author xuliugen
     * @date 2018/04/23
     */
    public class NumericConvertUtils {
    
        /**
         * 在进制表示中的字符集合,0-Z分别用于表示最大为62进制的符号表示
         */
        private static final char[] digits = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
                'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
                'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
                'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
                'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'};
    
        /**
         * 将十进制的数字转换为指定进制的字符串
         * @param number 十进制的数字
         * @param seed   指定的进制
         * @return 指定进制的字符串
         */
        public static String toOtherNumberSystem(long number, int seed) {
            if (number < 0) {
                number = ((long) 2 * 0x7fffffff) + number + 2;
            }
            char[] buf = new char[32];
            int charPos = 32;
            while ((number / seed) > 0) {
                buf[--charPos] = digits[(int) (number % seed)];
                number /= seed;
            }
            buf[--charPos] = digits[(int) (number % seed)];
            return new String(buf, charPos, (32 - charPos));
        }
    
        /**
         * 将其它进制的数字(字符串形式)转换为十进制的数字
         * @param number 其它进制的数字(字符串形式)
         * @param seed   指定的进制,也就是参数str的原始进制
         * @return 十进制的数字
         */
        public static long toDecimalNumber(String number, int seed) {
            char[] charBuf = number.toCharArray();
            if (seed == 10) {
                return Long.parseLong(number);
            }
    
            long result = 0, base = 1;
    
            for (int i = charBuf.length - 1; i >= 0; i--) {
                int index = 0;
                for (int j = 0, length = digits.length; j < length; j++) {
    	            //找到对应字符的下标,对应的下标才是具体的数值
                    if (digits[j] == charBuf[i]) {
                        index = j;
                    }
                }
                result += index * base;
                base *= seed;
            }
            return result;
        }
    }  
    
    /**
     * Twitter的SnowFlake算法,使用SnowFlake算法生成一个整数,然后转化为62进制变成一个短地址URL
     * @author beyond
     * @author xuliugen
     * @date 2018/04/23
     */
    public class SnowFlakeShortUrl {
    
        /**
         * 起始的时间戳
         */
        private final static long START_TIMESTAMP = 1480166465631L;
    
        /**
         * 每一部分占用的位数
         */
        private final static long SEQUENCE_BIT = 12;   //序列号占用的位数
        private final static long MACHINE_BIT = 5;     //机器标识占用的位数
        private final static long DATA_CENTER_BIT = 5; //数据中心占用的位数
    
        /**
         * 每一部分的最大值
         */
        private final static long MAX_SEQUENCE = -1L ^ (-1L << SEQUENCE_BIT);
        private final static long MAX_MACHINE_NUM = -1L ^ (-1L << MACHINE_BIT);
        private final static long MAX_DATA_CENTER_NUM = -1L ^ (-1L << DATA_CENTER_BIT);
    
        /**
         * 每一部分向左的位移
         */
        private final static long MACHINE_LEFT = SEQUENCE_BIT;
        private final static long DATA_CENTER_LEFT = SEQUENCE_BIT + MACHINE_BIT;
        private final static long TIMESTAMP_LEFT = DATA_CENTER_LEFT + DATA_CENTER_BIT;
    
        private long dataCenterId;  //数据中心
        private long machineId;     //机器标识
        private long sequence = 0L; //序列号
        private long lastTimeStamp = -1L;  //上一次时间戳
    
        /**
         * 根据指定的数据中心ID和机器标志ID生成指定的序列号
         * @param dataCenterId 数据中心ID
         * @param machineId    机器标志ID
         */
        public SnowFlake(long dataCenterId, long machineId) {
            if (dataCenterId > MAX_DATA_CENTER_NUM || dataCenterId < 0) {
                throw new IllegalArgumentException("DtaCenterId can't be greater than MAX_DATA_CENTER_NUM or less than 0!");
            }
            if (machineId > MAX_MACHINE_NUM || machineId < 0) {
                throw new IllegalArgumentException("MachineId can't be greater than MAX_MACHINE_NUM or less than 0!");
            }
            this.dataCenterId = dataCenterId;
            this.machineId = machineId;
        }
    
        /**
         * 产生下一个ID
         * @return
         */
        public synchronized long nextId() {
            long currTimeStamp = getNewTimeStamp();
            if (currTimeStamp < lastTimeStamp) {
                throw new RuntimeException("Clock moved backwards.  Refusing to generate id");
            }
    
            if (currTimeStamp == lastTimeStamp) {
                //相同毫秒内,序列号自增
                sequence = (sequence + 1) & MAX_SEQUENCE;
                //同一毫秒的序列数已经达到最大
                if (sequence == 0L) {
                    currTimeStamp = getNextMill();
                }
            } else {
                //不同毫秒内,序列号置为0
                sequence = 0L;
            }
    
            lastTimeStamp = currTimeStamp;
    
            return (currTimeStamp - START_TIMESTAMP) << TIMESTAMP_LEFT //时间戳部分
                    | dataCenterId << DATA_CENTER_LEFT       //数据中心部分
                    | machineId << MACHINE_LEFT             //机器标识部分
                    | sequence;                             //序列号部分
        }
    
        private long getNextMill() {
            long mill = getNewTimeStamp();
            while (mill <= lastTimeStamp) {
                mill = getNewTimeStamp();
            }
            return mill;
        }
    
        private long getNewTimeStamp() {
            return System.currentTimeMillis();
        }
    
        public static void main(String[] args) {
            SnowFlake snowFlake = new SnowFlake(2, 3);
    
            for (int i = 0; i < (1 << 4); i++) {
                //10进制
                Long id = snowFlake.nextId();
                //62进制
                String convertedNumStr = NumericConvertUtils.toOtherNumberSystem(id, 62);
    
                //10进制转化为62进制
                System.out.println("10进制:" + id + "  62进制:" + convertedNumStr);
    
                //TODO 执行具体的存储操作,可以存放在Redis等中
    
                //62进制转化为10进制
                System.out.println("62进制:" + convertedNumStr + "  10进制:" + NumericConvertUtils.toDecimalNumber(convertedNumStr, 62));
                System.out.println();
            }
        }
    }
    //生成结果:
    10进制:185784275776581632  62进制:dITqmhW2He
    62进制:dITqmhW2He  10进制:185784275776581632
    
    10进制:185784284689477632  62进制:dITqw17E6k
    62进制:dITqw17E6k  10进制:185784284689477632
    
    10进制:185784284689477633  62进制:dITqw17E6l
    62进制:dITqw17E6l  10进制:185784284689477633
    
    10进制:185784284689477634  62进制:dITqw17E6m
    62进制:dITqw17E6m  10进制:185784284689477634
    
    10进制:185784284689477635  62进制:dITqw17E6n
    62进制:dITqw17E6n  10进制:185784284689477635
    
    10进制:185784284689477636  62进制:dITqw17E6o
    62进制:dITqw17E6o  10进制:185784284689477636
    
    10进制:185784284689477637  62进制:dITqw17E6p
    62进制:dITqw17E6p  10进制:185784284689477637
    
    10进制:185784284693671936  62进制:dITqw1pfeo
    62进制:dITqw1pfeo  10进制:185784284693671936
    
    10进制:185784284693671937  62进制:dITqw1pfep
    62进制:dITqw1pfep  10进制:185784284693671937
    
    10进制:185784284693671938  62进制:dITqw1pfeq
    62进制:dITqw1pfeq  10进制:185784284693671938
    
    10进制:185784284693671939  62进制:dITqw1pfer
    62进制:dITqw1pfer  10进制:185784284693671939
    
    10进制:185784284693671940  62进制:dITqw1pfes
    62进制:dITqw1pfes  10进制:185784284693671940
    
    10进制:185784284693671941  62进制:dITqw1pfet
    62进制:dITqw1pfet  10进制:185784284693671941
    
    10进制:185784284693671942  62进制:dITqw1pfeu
    62进制:dITqw1pfeu  10进制:185784284693671942
    
    10进制:185784284693671943  62进制:dITqw1pfev
    62进制:dITqw1pfev  10进制:185784284693671943
    
    10进制:185784284693671944  62进制:dITqw1pfew
    62进制:dITqw1pfew  10进制:185784284693671944
    

    最后的代码地址:https://gitee.com/xuliugen/codes/9upvmzyk6c2i78eb3lgnj63

    3、推荐一个通用ID发号器

    码云地址:https://gitee.com/robertleepeak/vesta-id-generator

    这里直接给大家地址,不在介绍,有想了解的可以移步查看文档。

    十、总结

    到此为止,我们一起学习了什么是短地址,短地址的优点,如何选择一种正确的方式来实现我们的短地址,以及在码云上找到的一个还算可以的短地址生成项目,相信此时的你能够有一个更好的了解!


    参考文章:

    1、https://www.2cto.com/kf/201601/486883.html
    2、https://blog.csdn.net/lz0426001/article/details/52370177
    3、http://blog.sina.com.cn/s/blog_16aace20e0102x4tt.html
    4、https://www.zhihu.com/question/29270034/answer/46446911
    5、https://github.com/beyondfengyu/SnowFlake

    在这里插入图片描述

    【视频福利】2T免费学习视频,搜索或扫描上述二维码关注微信公众号:Java后端技术(ID: JavaITWork)回复:1024,即可免费获取!内含SSM、Spring全家桶、微服务、MySQL、MyCat、集群、分布式、中间件、Linux、网络、多线程,Jenkins、Nexus、Docker、ELK等等免费学习视频,持续更新!

    展开全文
  • 通过URL访问WEB

    千次阅读 2018-12-17 14:48:12
    当我们写完一个web程序之后(例如一个Servlet程序类,或者一个JSP页面),如果要访问这个web程序可以通过浏览器进行访问,还可以通过java客户端进行访问. 所谓的java客户端指的是.java.net.URL处理类,通过这个URL类可以...
  • 通过URL访问django静态资源

    千次阅读 2018-11-17 04:00:34
    问题真的困扰了好几天…这跟django的版本号应该有关系,网上的方法大多都只适用于旧的django版本 截止发帖为止,我当前用的是django 2.1.2版本 ... 首先需要url.py里引入django自带的views...
  • 2021年前端面试题及答案

    万次阅读 多人点赞 2020-02-11 19:29:34
    大纲 1、前言 2、前端工程化 3、前端设计模式 4、前端安全性问题 5、前端跨域问题 6、前端数据加密 7、前端http相关问题 8、*前端基础知识点面试题 9、前端技术栈问题 前言 ...
  • 支付宝接口使用文档说明 支付宝异步通知(notify_url)与return_url.现支付宝的通知有两类。
  • java爬虫

    千次阅读 多人点赞 2019-04-12 11:59:12
    爬虫的基本概念: ​ 什么是爬虫 ​ 爬虫的价值 ​ 爬虫的分类 ​ 通用的爬虫 ​ 垂直的爬虫 ​ 爬虫的基本原理 爬虫的三大模块: ​ 获取数据 ...​ 网络爬虫是一个程序, 采用一种特定的解析结构来获取互...
  • 一、确保为web项目,创建WebConfig 继承 WebMvcConfigurationSupport 或 ...Spring Boot中只能有一个implements WebMvcConfigurationSupport配置类是真正起作用的,对于这个问题,其实可以通过implements WebMvcConfi
  • 访问页面URL的常用方法

    千次阅读 2018-07-23 19:37:44
    window对象还包含-一个location 属性,该属性可用于访问该窗口或Frame所装载文档的地址。location 对象还包含如下几个常用属性。  hostname 文档所在地址的主机名。 href 文档所在地址的URL地址。 host ...
  • 程序中大多的实体或对象能够被序列化为包含键值对的JSON对象,键(key)是字段(field)或属性(property)的名字,值(value)可以是字符串、数字、布尔类型、另一个对象、值数组或者其他特殊类型,比如表示日期的字符串...
  • 访问URL地址实现下载文件

    千次阅读 2017-07-09 15:45:29
    package Url; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.net.H
  • js获取url地址中的每一个参数,方便操作url的hash 值得收藏 &amp;lt;html&amp;gt; &amp;lt;body&amp;gt; &amp;lt;script&amp;gt; //location.search; //可获取浏览器当前访问url中&...
  • Python爬虫根据关键词爬取知网论文摘要并保存到数据库中 由于实验室需要一些语料做研究,语料要求是知网上的论文摘要,但是目前最新版的知网爬起来有些麻烦,所以我利用的是知网的另外一个搜索接口
  • JAVA上百实例源码以及开源项目

    千次下载 热门讨论 2016-01-03 17:37:40
    得到名字上下文,查询jndi名,通过强制转型得到Home接口,getInitialContext()函数返回一个经过初始化的上下文,用client的getHome()函数调用Home接口函数得到远程接口的引用,用远程接口的引用访问EJB。 EJB中JNDI...
  • 最近看到一个题目,**当在浏览器中输入一个url后回车,后台发生了什么?**比如输入url后,你看到了百度的首页,那么这一切是如何发生的呢? 网上各种的说法,不外乎都是这样的: 第一步:客户机提出域名解析请求,并...
  • js通过Location实现访问Url,重定向,刷新页面
  • 访问一个网站需要那几个协议?

    万次阅读 2015-07-14 11:04:21
    作为一个软件开发者,你一定会对网络应用如何工作有一个完整的层次化的认知,同样这里也包括这些应用所用到的技术:像浏览器,HTTP,HTML,网络服务器,需求处理等等。 本文将更深入的研究当你输入一个网址的时候,...
  • 解决阿里云OSS使用URL无法访问图片

    千次阅读 2020-04-08 18:41:45
    1、使用URL访问OSS存储的图片时显示XML代码 2、使用URL访问OSS存储的图片时自动下载 二、解决方式: 如果大家对HTTP头部内容不清晰的可以去百度了解一下再看 解决问题: 问题出现的原因:因为在OSS的Bucket权限...
  • django 通过URL访问上传的文件

    千次阅读 2018-08-17 19:04:58
    Django是一个成熟的web框架,基于python实现,有很多的优点,很容易快速上手(详见官网:https://www.djangoproject.com/)的文档,Django2.0的文档有1872页,不得不说是非常全的,文档是可谓包罗万象。 Django给我...
  • 编写你的第一个 Django 程序 第3部分本教程上接 教程 第2部分 。我们将继续 开发 Web-poll 应用并且专注在创建公共界面 – “视图 (views )”。哲理在 Django 应用程序中,视图是一“类”具有特定功能和模板的网页...
  • Python 搭建一个简易QQ机器人

    万次阅读 多人点赞 2019-10-01 15:43:19
    可以参考官方文档:nonebot指南 安装nonebot: pip install nonebot tips:python版本要>=3.6.1 下载酷Q: 官方地址 然后可以跟着酷Q的新手教程走遍 安装 CoolQ HTTP API 插件 官方地址 继续跟着教程走 在...
  • vue中axios跨域请求

    万次阅读 多人点赞 2019-06-22 13:22:31
    //对于post请求可以统一设置一个请求头,后面所有post请求就可以不用单独设置请求头了 axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded'; // 具体语法 let params = new ...
  • 1. 在 Spring Boot 中,默认情况下,一共有5位置可以放静态资源,Spring Boot 默认将 /** 所有访问映射到以下目录,五路径分别是如下5: classpath:/META-INF/resources/ classpath:/resources/ classpath:/...
  • location / { root /home/wwwroot/; index index.html; **add_header Content-Type text/plain;** }
  • java后台访问url连接——HttpClients

    万次阅读 2015-07-13 11:25:12
    java后台访问url,并获取或者传递数据 1、无参数传递,以微信开发为例,后台访问url连接获得全部的人员列表 /** * 获取全部人员列表 * @return */ public JSONObject getAllEmployee(){ //获取微信号 ...
  • 一个完整的URL 解析过程

    万次阅读 2018-12-29 10:35:17
    域名解析服务器是基于UDP实协议实现的一个应用程序,通常通过监听53端口来获取客户端的域名解析请求。DNS查找过过程如下: 浏览器缓存-浏览器会缓存DNS记录一段时间。有趣的是操作系统没有告诉浏览器存储DNS记录的...
  • http://blog.csdn.net/jserkang/archive/2005/03/13/318623.aspx<br />  接入9588短信网关(http协议),9588的iis上的短信服务url需要身份验证, 在程序中使用的URL:... System
  • 问题描述 用户在访问ECS服务器上的网站时,提示如下错误: 解决方案 如果您对实例或数据有修改、变更等风险操作,务必注意实例的容灾、容错能力,确保数据安全。...这是由于云盾的应用防火墙对URL访问判定...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 382,943
精华内容 153,177
关键字:

url访问一个文档需要