最近一直在重新回顾J2EE方面的知识,今天学习了一下HTTP协议。有利于更好地了解客户端和服务器是如何协同工作的,是如何完成
“有求必应”的这么一个效果的。
1.什么是HTTP协议呢?
http协议即是超文本传输协议(HyperText Transfer Protocal),是互联网上应用最广的一种网络协议。是工作在tcp/ip协议的基础之上的,所有的www文件都必须遵守这个标准。设计http最初的目的就是提供一种发布和接受HTML页面的方法。
http分为两个版本1.0(短连接)和1.1(长连接)版本。短连接和长连接指的是服务器和客户端连接的时间长短,现在通用的是http1.1
版本的。
2.http请求包括哪些内容呢?
一个请求行、若干消息头、以及实体内容
①请求行 包括请求资源地址 、请求方式、http版本
请求方式大致了解两种即可,一种是post请求,一种是get请求。
他们的区别有三点:
①请求数据的位置不同。get请求方式的请求参数会附在url之后,以?分割url和请求数据,多个请求数据之间用&隔开例如:http:\\baidu.com?username=a&password=a,而post方式把请求数据放在http包的包体中
②传输数据的大小不同。get方式的请求数据是附在url之后的所以浏览器是限制url的长度的一般在2k左右,而post不是通过url传输数据的所以理论上是不受限制的。
③安全性不同。get的请求参数都暴露在url也就是地址栏中很不安全,而post是将请求数据放在http包的包体中安全性较高。
②请求消息头
消息头的格式是[消息头名称:消息值]不是每次一请求的消息头都是一样的。
Http请求消息头的详解
Host[告诉服务器我请求的主机是哪一个]
User-Agent[用户代理指的是我发出请求客户端浏览器的内核是那种]
Accept[我接受的响应数据格式]
Accept-Language[我接受响应的语言有哪些]
Accept-Encoding[告诉服务器我接受(gzip,deflate)哪些算法压缩后的数据]
If-Modified-Since[记录请求资源在我缓冲中存储的时间,用于如果请求资源没有改动那么我就用缓冲中的资源即可]
Referer[告诉服务器我这个请求是从哪里发出来的,如果不是通过正规站点或者是地址栏直接输入的地址,referer的值都是null]
Connection[告诉服务器我与服务器连接的方式,是否保持连接]
③请求数据的内容
3.那么我们的服务器如何获得客户端请求服务器的http的请求消息头呢?
①其实很简单之前就说过当客户端发送请求,web服务器找到相应的servlet处理类创建该实例时同样会创建HttpServletRequest对象将http的请求信息装载到里面去,并且把HttpServletRequest对象作为参数交给Servlet请求处理类。所以理所当然我们可以通过HttpServletRequest对象来访问http中的任何信息。在j2ee中我们只需要通过getHeader(“消息头名”)即可获得相应的消息头值。
②这里我着重研究了一下消息头Referer,网站上说Referer可以防止盗链。因为我们可以通过Referer的值来判断请求来自于哪,从而给予客户端访问的权限或者限制其不合法的操作。(关于防盗链的代码实现在下面资源下载的那边一起展示)
4.那么服务器做出响应,http响应包括哪些内容呢?
①一个状态行,状态行中包括http协议版本 状态码 原因叙述
状态码的详细如下:
常见的状态码有
200:表示请求和响应都没有错误,这个最常见
302:表示当浏览器请求服务器时,服务器返回一个302,让浏览器转向到另一个资源
404:找不到资源
500:服务器端发生错误
②若干响应消息头
Location[告诉浏览器重新定位到那个url]
Server[告诉浏览器是什么服务器给它做出的响应]
Content-Encoding[告诉浏览器我给你返回的资源你需要用这样的编码解压一下]
Content-Length[告诉浏览器我给你响应的文件的大小]
Content-Language[告诉浏览器我给你响应的内容语言类型]
Content-Type[告诉浏览器我给你响应的内容类型]
Last-Modified[告诉浏览器我给你响应的资源在服务器中最近一次的修改时间]
Refresh[告诉浏览器过多久刷新到指定的url]
Content-Disposition[用于告诉浏览器要下载资源的文件名,用于下载中的内容配置使用的]web容器下载文件的过程如下:浏览器发出请求下载的资源,服务器接受请求用httpresponse对象将请求的资源写到缓存中去然后发送给客户端。
实现案例如下:
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//首先从请求对象中获得要下载的文件的文件名
String filename=request.getParameter("filename");
ServletContext servletContext=this.getServletContext();
//获得资源的虚拟路径 在服务器的那个位置
String path=servletContext.getRealPath("/download/"+filename);
//获得请求信息头的Referer值
String host=request.getHeader("Host");
String referer=request.getHeader("Referer");
//防止盗链的路径
String acceptUrl="http://"+host+servletContext.getContextPath();
//如果是不合法的链接那么就直接跳转到提示页面
if (referer==null||!referer.startsWith(acceptUrl)) {
response.sendRedirect("/J2EE_Http/Error.jsp");
return;
}else{
//如果是本网站的页面发出的请求那么就开始去读取文件
//1.告诉浏览器我响应请求下载的文件
response.setHeader("Content-Disposition","attachment;filename="+filename);
InputStream is=new FileInputStream(path);
byte bs[]=new byte[2048];
int len=0;
while((len=is.read(bs))!=-1){
//那么就将文件下载到客户端
response.getOutputStream().write(bs, 0, len);
}
//关闭流
response.getOutputStream().close();
is.close();
}
}
Transfer-Encoding[传输的编码]
Set-Cookie[响应头设置cookie值,见另一个博客]
Expires[告诉浏览器如何缓存,支持http1.0和http1.1]
Cache-Control[告诉浏览器如何缓存用于http1.1]
Pragma[也是用于告诉浏览器如何缓存用于http1.1]
如果以后我们开发一个网站如果实时性要求比较高的,比如股票等网页时一定要禁止浏览器缓存我们的页面来达到实时性。设置如下:
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/html;charset=utf-8");
//告诉浏览器不需要缓存 为了兼容各种版本
//如需缓存一段时间//response.setDateHeader("Expires", 毫秒数即可);
response.setDateHeader("Expires", -1);
response.setHeader("Cache-Control", "no-cache");
response.setHeader("Pragma", "no-cache");
response.getWriter().println("我是个好人");
}
③响应内容