Http协议

协议:双方在交互、通讯的时候, 遵守的一种规范、规则。
http协议:针对网络上的客户端 与 服务器端在执行http请求的时候,遵守的一种规范。 其实就是规定了客户端在访问服务器端的时候,要带上哪些东西, 服务器端返回数据的时候,也要带上什么东西。
版本:
    1.0请求数据,服务器返回后, 将会断开连接
    1.1请求数据,服务器返回后, 连接还会保持着。 除非服务器 | 客户端 关掉。 有一定的时间限制,如果都空着这个连接,那么后面会自己断掉。
   
Http请求数据解释

请求的数据里面包含三个部分内容 :请求行 、 请求头 、请求体

*请求行
        POST /examples/servlets/servlet/RequestParamExample HTTP/1.1

POST : 请求方式 ,以post去提交数据
        /examples/servlets/servlet/RequestParamExample
        请求的地址路径 , 就是要访问哪个地方。
        HTTP/1.1 协议版本
* 请求头
        Accept: application/x-ms-application, image/jpeg, application/xaml+xml,
image/gif, image/pjpeg, application/x-ms-xbap, */*
        Referer: http://localhost:8080/examples/servlets/servlet/RequestParamExample
        Accept-Language: zh-CN
        User-Agent: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; WOW64; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E)
        Content-Type: application/x-www-form-urlencoded
        Accept-Encoding: gzip, deflate
        Host: localhost:8080
        Content-Length: 31
        Connection: Keep-Alive
        Cache-Control: no-cache

Accept: 客户端向服务器端表示,我能支持什么类型的数据。
        Referer : 真正请求的地址路径,全路径
        Accept-Language: 支持语言格式
        User-Agent: 用户代理 向服务器表明,当前来访的客户端信息。
        Content-Type: 提交的数据类型。经过urlencoding编码的form表单的数据
        Accept-Encoding: gzip, deflate : 压缩算法 。
        Host : 主机地址
        Content-Length: 数据长度
        Connection : Keep-Alive 保持连接
        Cache-Control : 对缓存的操作

* 请求体
浏览器真正发送给服务器的数据
        发送的数据呈现的是key=value ,如果存在多个数据,那么使用&
        firstname=zhang&lastname=sansan

Http响应数据解析
请求的数据里面包含三个部分内容 : 响应行 、 响应头 、响应体

HTTP/1.1 200 OK
    Server: Apache-Coyote/1.1
    Content-Type: text/html;charset=ISO-8859-1
    Content-Length: 673
    Date: Fri, 17 Feb 2010 02:53:02 GMT

...

* 响应行
    
        HTTP/1.1 200 OK
        协议版本  
        状态码
            200 : 成功,正常处理,得到数据。
            403  : for bidden  拒绝
            404 : Not Found
            500 : 服务器异常
        OK
            对应前面的状态码

* 响应头
        Server:  服务器是哪一种类型。  Tomcat
        Content-Type : 服务器返回给客户端你的内容类型
        Content-Length : 返回的数据长度
        Date : 通讯的日期,响应的时间

Get 和  Post请求区别
* post
1. 数据是以流的方式写过去,不会在地址栏上面显示。  现在一般提交数据到服务器使用的都是POST
2. 以流的方式写数据,所以数据没有大小限制。一定需要一个Content-Lenght的头说明数据的长度有多少
* get
1. 会在地址栏后面拼接数据,所以有安全隐患。 一般从服务器获取数据,并且客户端也不用提交上面数据的时候,可以使用GET
2. 能够带的数据有限, 1kb大小

Web资源
在http协议当中,规定了请求和响应双方, 客户端和服务器端。与web相关的资源。 有两种分类

* 静态资源
    html 、 js、 css
* 动态资源
    servlet/jsp

servlet:
其实就是一个java程序,运行在我们的web服务器上,用于接收和响应 客户端的http请求。
更多的是配合动态资源来做。 当然静态资源也需要使用到servlet,只不过是Tomcat里面已经定义好了一个 DefaultServlet

Hello Servlet

得写一个Web工程 , 要有一个服务器。
测试运行Web工程 1. 新建一个类, 实现Servlet接口
2. 配置Servlet , 用意: 告诉服务器,我们的应用有这么些个servlet。
在webContent/WEB-INF/web.xml里面写上以下内容。 <!-- 向tomcat报告, 我这个应用里面有这个servlet, 名字叫做HelloServlet , 具体的路径是 com.itheima.servlet.HelloServlet -->
<servlet>
<servlet-name>HelloServlet</servlet-name>
<servlet-class>com.itheima.servlet.HelloServlet</servlet-class>
</servlet> <!-- 注册servlet的映射。 servletName : 找到上面注册的具体servlet, url-pattern: 在地址 栏上的path 一定要以/打头 -->
<servlet-mapping>
<servlet-name>HelloServlet</servlet-name>
<url-pattern>/a</url-pattern>
</servlet-mapping> 3. 在地址栏上输入 http://localhost:8080/项目名称/a

Servlet的通用写法

 Servlet (接口)
|
|
GenericServlet
|
|
HttpServlet (用于处理http的请求)
定义一个类,继承HttpServlet 复写doGet 和 doPost
public class HelloHttpServer extends HttpServlet{
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// TODO Auto-generated method stub
super.doGet(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// TODO Auto-generated method stub
super.doPost(req, resp);
} }

Servlet的生命周期:
生命周期:从创建到销毁的一段时间
生命周期方法:
从创建到销毁,所调用的那些方法。
init方法
在创建该servlet的实例时,就执行该方法。
一个servlet只会初始化一次, init方法只会执行一次
默认情况下是 : 初次访问该servlet,才会创建实例。
service方法
只要客户端来了一个请求,那么就执行这个方法了。
 该方法可以被执行很多次。 一次请求,对应一次service方法的调用
destroy方法
  servlet销毁的时候,就会执行该方法
    1. 该项目从tomcat的里面移除。
    2. 正常关闭tomcat就会执行 shutdown.bat

让Servlet创建实例提前:
默认情况下,只有在初次访问servlet的时候,才会执行init方法。 有的时候,我们可能需要在这个方法里面执行一些初始化工作,甚至是做一些比较耗时的逻辑。
在配置的时候, 使用load-on-startup元素来指定, 给定的数字越小,启动的时机就越早。 一般不写负数, 从2开始即可。

<servlet>
<servlet-name>HelloServlet</servlet-name>
<servlet-class>com.fly.servlet.HelloServlet</servlet-class>
<load-on-startup>2</load-on-startup>
</servlet>

ServletConfig:
Servlet的配置,通过这个对象,可以获取servlet在配置的时候一些信息

<servlet>
<servlet-name>ServletConfigName</servlet-name>
<servlet-class>com.fly.servlet.HelloServletConfig</servlet-class>
<init-param>
<param-name>name</param-name>
<param-value>fly</param-value>
</init-param>
</servlet>
public class HelloServletConfig extends HttpServlet{
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletConfig config = getServletConfig(); //得到servlet配置对象 专门用于在配置servlet的信息
String servletName = config.getServletName(); ////获取到的是配置servlet里面servlet-name 的文本内容
System.out.println("servletName:"+servletName); String name = config.getInitParameter("name"); // 可以获取具体的某一个参数
System.out.println("name:"+name); Enumeration<String> names = config.getInitParameterNames(); // 可以获取具体的某一个参数
while (names.hasMoreElements()) { //遍历取出所有的参数名称
String key = (String) names.nextElement();
String value = config.getInitParameter(key);
System.out.println("key:"+key+"value:"+value);
}
/* servletName:ServletConfigName
name:fly
key:namevalue:fly*/ } }

为什么需要有这个ServletConfig
servlet 里面需要一个数字或者叫做变量值。 但是这个值不能是固定了。 所以要求使用到这个servlet的公司,在注册servlet的时候,必须要在web.xml里面,声明init-params

===========================================================================
HttpServletRequest 和 HttpServletResponse
Servlet配置方式
1.全路径匹配:
以 / 开始 /a /aa/bb
localhost:8080/项目名称/aa/bb
2.路径匹配 , 前半段匹配:
以 / 开始 , 但是以 * 结束 /a/* /*
其实是一个通配符,匹配任意文字
localhost:8080/项目名称/aa/bb
3.以扩展名匹配:
写法: 没有/ 以 * 开始 *.扩展名 *.aa *.bb

ServletContext:
Servlet 上下文每个web工程都只有一个ServletContext对象。

如何得到对象
    ServletContext context = getServletContext();
作用:
1获取全局配置参数
2获取web工程中的资源
3存取数据,servlet间共享数据 域对象

全局配置参数:
  <!-- 用于配置全局的参数 -->
  <context-param>
  <param-name>name</param-name>
  <param-value>fly</param-value>
  </context-param>
获取全局参数:
ServletContext servletContext = getServletContext();
String name = servletContext.getInitParameter("name");
System.out.println("context-name:"+name);

获取Web应用中的资源:
1. 获取资源在tomcat里面的绝对路径

    //获取ServletContent对象
ServletContext context = getServletContext();
//获取给定文件在服务器上的绝对路径(文件放在项目结构的WebContent)
String realPath = context.getRealPath("file/config.properties"); Properties properties = new Properties();
FileInputStream inputStream = new FileInputStream(realPath);
properties.load(inputStream);
String name = properties.getProperty("name");
System.out.println("name:"+name);
inputStream.close();

2. getResourceAsStream 获取资源 流对象

直接给相对的路径,然后获取流对象。
ServletContext context = getServletContext(); Properties properties = new Properties();
//获取web工程下的资源,转化为流对象
InputStream is = context.getResourceAsStream("file/config.properties");
properties.load(is);
String name = properties.getProperty("name");
System.out.println("name:"+name);
is.close();

通过classloader去获取web工程下的资源:

//ClassLoader   \wtpwebapps\xx\WEB-INF\classses
//要回到 \wtpwebapps\xx
InputStream is = this.getClass().getClassLoader().getResourceAsStream("../../file/config.properties");

使用ServletContext存取数据:

//获取表单数据
String username = request.getParameter("username");
String password = request.getParameter("password");
//向客户端输出内容
PrintWriter writer = response.getWriter();
if ("abc".equals(username)&&"123".equals(password)) {
System.out.println("登录成功"); Object object = getServletContext().getAttribute("count");
int count = 0;
if (object!=null) {
count = (int) object;
}
getServletContext().setAttribute("count", count+1); // writer.println("login success");
// writer.write("login success");
response.setStatus(HttpServletResponse.SC_FOUND); //302重定向
response.setHeader("Location", "home.html");
}else {
writer.println("login failed");
} ===================== // 取值
int count = (int) getServletContext().getAttribute("count");
// 输出到界面
response.getWriter().write("当前访问次数:第"+count+"次访问"); 细节;
<form action="login" method="get"> 相对路径

ServletContext 何时创建, 何时销毁?
服务器启动的时候,会为托管的每一个web应用程序,创建一个ServletContext对象
从服务器移除托管,或者是关闭服务器。
ServletContext 的作用范围:同一个项目。

HttpServletRequest:
这个对象封装了客户端提交过来的一切数据。

1. 可以获取客户端请求头信息

        //得到一个枚举集合
Enumeration<String> headerNames = request.getHeaderNames();
while (headerNames.hasMoreElements()) {
String name = (String) headerNames.nextElement();
String value = request.getHeader(name);
System.out.println(name+"="+value); }

2. 获取客户端提交过来的数据

        String name = request.getParameter("name");
String address = request.getParameter("address");
System.out.println("name="+name);
System.out.println("address="+address); //name=zhangsan&name=lisi&name=wangwu 一个key可以对应多个值。 Map<String, String[]> map = request.getParameterMap(); Set<String> keySet = map.keySet();
Iterator<String> iterator = keySet.iterator();
while (iterator.hasNext()) {
String key = (String) iterator.next();
System.out.println("key="+key + "--的值总数有:"+map.get (key).length);
String value = map.get(key)[0];
String value1 = map.get(key)[1];
String value2 = map.get(key)[2]; System.out.println(key+" ======= "+ value + "=" + value1 + "="+ value2);
}

3. 获取中文数据

客户端提交数据给服务器端,如果数据中带有中文的话,有可能会出现乱码情况,那么可以参照以下方法解决。

* 如果是GET方式

    1. 代码转码
String username = request.getParameter("username");
String password = request.getParameter("password"); System.out.println("userName="+username+"==password="+password); //get请求过来的数据,在url地址栏上就已经经过编码了,所以我们取到的就是乱码,
//tomcat收到了这批数据,getParameter 默认使用ISO-8859-1去解码 //先让文字回到ISO-8859-1对应的字节数组 , 然后再按utf-8组拼字符串
username = new String(username.getBytes("ISO-8859-1") , "UTF-8");
System.out.println("userName="+username+"==password="+password);
直接在tomcat里面做配置,以后get请求过来的数据永远都是用UTF-8编码。 2. 可以在tomcat里面做设置处理 conf/server.xml 加上URIEncoding="utf-8" <Connector connectionTimeout="20000" port="8080" protocol="HTTP/1.1" redirectPort="8443" URIEncoding="UTF-8"/> * 如果是POST方式 //设置请求体里面的文字编码。 get方式,用这行,没用
request.setCharacterEncoding("UTF-8"); //这行设置一定要写在getParameter之前。

HttpServletResponse:

负责返回数据给客户端。

输出数据到页面上

    //以字符流的方式写数据
//response.getWriter().write("<h1>hello response...</h1>");
//以字节流的方式写数据
response.getOutputStream().write("hello response".getBytes());

响应的数据编码问题:

String string = Charset.defaultCharset().name(); string类的getByte()方法使用的码表
// 以字符流输出 //response.getWriter()
//1. 指定输出到客户端的时候,这些文字使用UTF-8编码
response.setCharacterEncoding("UTF-8"); //2. 直接规定浏览器看这份数据的时候,使用什么编码来看。
response.setHeader("Content-Type", "text/html; charset=UTF-8"); response.getWriter().write("你好..."); //以字节流输出 //response.getOutputStream() //1. 指定浏览器看这份数据使用的码表
response.setHeader("Content-Type", "text/html;charset=UTF-8"); //2. 指定输出的中文用的码表
response.getOutputStream().write("你好..".getBytes("UTF-8")); //不分情况,一行搞定
response.setContentType("text/html;charset=UTF-8");

下载资源:
1.直接以超链接的方式下载,不写任何代码。 也能够下载东西下来。

让tomcat的默认servlet去提供下载:
    <a href="download/a.rar">cc.rar</a><br>

原因是tomcat里面有一个默认的Servlet -- DefaultServlet 。这个DefaultServlet 专门用于处理放在tomcat服务器上的静态资源。

2.

// <a href="DownLoad?download=cc.rar">c.rar</a>
//获取要现在的文件的名字
String fileName = request.getParameter("download");
//获取文件在tomcat的绝对路径
String path = getServletContext().getRealPath("download/"+fileName);
//以下载的方式提醒用户,而不是直接展示
response.setHeader("Content-Disposition", "attachment;filename="+fileName);
//转化成输出流
InputStream is = new FileInputStream(path);
OutputStream os = response.getOutputStream(); int len = 0;
byte[] b = new byte[1024];
while((len=is.read(b))!=-1) {
os.write(b, 0, len);
}
os.close();
is.close();

 中文文件下载
 
针对浏览器类型,对文件名字做编码处理 Firefox (Base64) , IE、Chrome ... 使用的是URLEncoder

  public static String base64EncodeFileName(String fileName) {
BASE64Encoder base64Encoder = new BASE64Encoder();
try {
return "=?UTF-8?B?"
+ new String(base64Encoder.encode(fileName
.getBytes("UTF-8"))) + "?=";
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
       /*
* 如果文件的名字带有中文,那么需要对这个文件名进行编码处理
* 如果是IE ,或者 Chrome (谷歌浏览器) ,使用URLEncoding 编码
* 如果是Firefox , 使用Base64编码
*/
//获取来访的客户端类型
String clientType = request.getHeader("User-Agent"); if(clientType.contains("Firefox")){ //包含Firefox
fileName = DownLoadUtil.base64EncodeFileName(fileName);
}else{
//IE ,或者 Chrome (谷歌浏览器) ,
//对中文的名字进行编码处理
fileName = URLEncoder.encode(fileName,"UTF-8");
}

完整:

// <a href="DownLoad?download=cc.rar">c.rar</a>
//获取要现在的文件的名字
String fileName = request.getParameter("download");
//防止有中文
fileName = new String(fileName.getBytes("ISO-8859-1"),"UTF-8"); //获取文件在tomcat的绝对路径
String path = getServletContext().getRealPath("download/"+fileName);
/*
* 如果文件的名字带有中文,那么需要对这个文件名进行编码处理
* 如果是IE ,或者 Chrome (谷歌浏览器) ,使用URLEncoding 编码
* 如果是Firefox , 使用Base64编码
*/
//获取来访的客户端类型
String clientType = request.getHeader("User-Agent");//包含Firefox
if (clientType.contains("Firefox")) {
fileName = DownLoadUtil.base64EncodeFileName(fileName);
}else {
//对中文的名字进行编码处理
fileName = URLEncoder.encode(fileName,"UTF-8");
}
//以下载的方式提醒用户,而不是直接展示
response.setHeader("Content-Disposition", "attachment;filename="+fileName);
//转化成输出流
InputStream is = new FileInputStream(path);
OutputStream os = response.getOutputStream(); int len = 0;
byte[] b = new byte[1024];
while((len=is.read(b))!=-1) {
os.write(b, 0, len);
}
os.close();
is.close();

02 http,servlet,servletconfig,HttpServletRequest ,HttpServletResponse的更多相关文章

  1. 找不到javax.servlet.http.HttpServletResponse和javax.servlet.http.HttpServletRequest

    导了个项目进eclipse,发现很多文件都报了错,错误提示是没有引入javax.servlet.http.HttpServletRequest和javax.servlet.http.HttpServl ...

  2. HttpClient_001_初步实现项目01的servlet,与项目02的servlet,之间数据访问

    HttpClient_001_初步实现项目01的servlet,与项目02的servlet,之间数据访问 代码下载地址: http://download.csdn.net/detail/poiuy19 ...

  3. 无法解析类型 javax.servlet.http.HttpServletRequest。从必需的 .class 文件间接引用

    java.lang.Error: 无法解析的编译问题: 无法解析类型 javax.servlet.http.HttpServletRequest.从必需的 .class 文件间接引用了它 无法解析类型 ...

  4. The code of method _jspService(HttpServletRequest, HttpServletResponse) is exceeding the 65535 bytes limit

    如果你是通过搜索来到本文的,相信你应该是遇到了如下的错误 The code of method _jspService(HttpServletRequest, HttpServletResponse) ...

  5. Ajax -02 -JQuery+Servlet -实现页面点击刷出表格数据

    demo功能分析 jquery 的js文件需要导入,json的三个文件需要导入,不然writeValueAsString 会转化成JsonArray(json 数组)失败 $("#mytbo ...

  6. Java-Class-I:javax.servlet.http.HttpServletRequest

    ylbtech-Java-Class-I:javax.servlet.http.HttpServletRequest 1.返回顶部   2.返回顶部 1. package com.ylbtech.ap ...

  7. HttpServletRequest HttpServletResponse接口详解

    HttpServletRequest接口最常用的方法就是获得请求中的参数,这些参数一般是客户端表单中的数据.同时,HttpServletRequest接口可以获取由客户端传送的名称,也可以获取产生请求 ...

  8. JAVAEE_Servlet_12_获取前端页面请求方式 HttpServletRequest HttpServletResponse

    获取前端页面请求方式 * 前端页面发送的请求方式应该是后端服务器需要的请求方式保持一致,若不一致应该提示错误信息. * 获取到前端的请求方式之后通过if语句进行判断, if("GET&quo ...

  9. servlet中的HttpServletResponse对象

    当有多个客户端浏览器去请求Tomcat时,Tomcat会为每一个客户端浏览器创建一对独立的HttpServletRequest与HttpServletResponse对象 HttpServletRes ...

随机推荐

  1. mybatis输出sql语句

    方法一: 这种方法是mybatis官网上介绍的,比较好用: log4j.properties: log4j.rootLogger=ERROR,consolelog4j.appender.console ...

  2. Docker安装websphere(四)

    在Docker容器里安装webshpere <!--前提:已经安装好了docker,能够正常使用.--> (1)docker安装websphere(需要账号和密码登录,不挂载数据卷) 获取 ...

  3. angular4-注入服务

    //配置已创建的服务:import { MemberService } from "./member.service";@NgModule({ // ... providers: ...

  4. 《python》join、守护进程、锁/信号量/事件、进程队列

    一.multiprocess.process模块 1.join方法 阻塞主进程,等待子进程执行完毕再放开阻塞 import time import random from multiprocessin ...

  5. 如何从零安装Mysql

    1.yum/rpm安装 2.采用二进制方式免编译安装MySQL. 3.考虑到MySQL5.4.xx及以后系列产品的特殊性,其编译方式和早期的第一条产品线的有所不同,这里采用cmake或gmake方式的 ...

  6. WebView加载页面

    //使用内置浏览器webView.setWebViewClient(new WebViewClient(){ @Override public boolean shouldOverrideUrlLoa ...

  7. netty源码理解(三) 从channel读取数据

    下面的是ServerBootstrap 的内部类 ServerBootstrapAcceptor extends ChannelInboundHandlerAdapter 的方法 这里其实卡住了我很长 ...

  8. adb shell按键操作(input keyevent)

    前言:input keyeven操作发送手机上常用的一些按键操作 一.keyevent事件对应数字 电话键 KEYCODE_CALL: 拨号键 KEYCODE_ENDCALL: 挂机键 KEYCODE ...

  9. 从Oracle数据库中的本地命名文件tnsnames.ora来看服务别名、服务名和实例名的区别。

    tnsnames.ora的作用这里就不多述了,各位应该都知道. 首先先看两个例子: test1 = (DESCRIPTION = (ADDRESS_LIST = (ADDRESS = (PROTOCO ...

  10. python day 07-数据类型补充,集合,深浅拷贝

    一.基础数据类型补充 1.列表转字符串 a='A'.join(['c','c','s']) print(a) 2.循环删除列表中的每⼀一个元素 lst=['asdf','dftgst','zsdrfs ...