# 浏览器请求
请求方式一共有7中,但是常用的就是只有post和get请求,直接在浏览器中输入地址进入的方式是get请求
# GenericServlet类和HttpServlet
# GenericServlet
GenericServlet已经实现了servlet接口,并且重写了除了service方法,因为其他的方法我们不经常使用,如果我们想要使用其他的方法的话,就自己重写那个方法就行,我们必须要重写service方法
但是这个类,也并不是常用的
# HttpServlet
这是一个抽象类,但是里面的方法都没有抽象方法,这个类继承于GenericSerivlet类,并且重写了
因为请求方式一共有7中,所以,这个类中一个写了7个请求的方法,像doget(),dopost()方法,在service方法中已经按照请求的方式进行if语句的判断,每一个请求方式判断正确就会调用那个do请求方法
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String method = req.getMethod();
long lastModified;
if (method.equals("GET")) {
if (lastModified == -1L) {
this.doGet(req, resp);
} else if (method.equals("HEAD")) {
lastModified = this.getLastModified(req);
this.maybeSetLastModified(resp, lastModified);
this.doHead(req, resp);
} else if (method.equals("POST")) {
this.doPost(req, resp);
} else if (method.equals("PUT")) {
this.doPut(req, resp);
} else if (method.equals("DELETE")) {
this.doDelete(req, resp);
} else if (method.equals("OPTIONS")) {
this.doOptions(req, resp);
} else if (method.equals("TRACE")) {
this.doTrace(req, resp);
} else {
String errMsg = lStrings.getString("http.method_not_implemented");
Object[] errArgs = new Object[]{method};
errMsg = MessageFormat.format(errMsg, errArgs);
resp.sendError(501, errMsg);
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
所以我们如果要测试的话,那么我们就直接重写doget(),dopost()方法就行
如果想要测试get请求的话,很简单,因为直接在浏览器中输入地址进入,就是一个get请求
# urlpartten配置
因为注解中的urlpartten可以定义一个数组,所以我们就可以为其设置多个不同的资源路径
@WebServlet({"/d4","/demon4","/dd4"})
@WebServlet("/user/d/d4")
这种设置资源路径,属于多层结构,我们只有准确写出这个,才能访问
localhost/user/d/d4其他的路径不会访问到
@WebServlet("/user/*")这里的
*
代表所有的,可以在/user/后面加入任何的东西localhost/user/sdfsdlfkj,localhost/user/sdfkhsdkfhskdf都可以访问到
@WebServlet("/*")这种方式,就是输入任何内容,都可以访问到,因为星号代表所有,localhost/sdlfh ,localhost/sdfihsdkfh,
如果文件中存在一个路径localhost/d3,我们也在这里用
(/*)
的方式进行访问,如果输入的地址也是localhost/d3,那么访问的还是真实存在的这个路径资源,因为星号这种方式的级别特别低@WebServlet("*.do")这种方式,输入任何的
.do
都可以访问到资源
# HTTP概述
缩写:Hyper Text Transfer Protocol 超文本传输协议
定义了,客户端和服务器端进行通信时,发送数据的格式
特点:这是一种基于tcp/ip的高级协议
默认端口号80
是一种基于请求/响应模型,也就是一次请求对应一次响应
无状态,每次请求都是相互独立的,请求之间不能进行数据的交互
# HTTP版本
一共有两个版本1.0和1.1
1.0 没请求一次,并且响应成功,就断开,再进行下一次的请求,这种方式浪费资源,
1.1 这个版本会复用上一次请求的连接,不会断开,直到实在是没有请求为止
如果在浏览器中输入baidu.com,一共进行多少次请求?
答案是很多次,并不是一次,应为加载图片。JavaScript,css都需要建立请求,我们可以打开f12,network进行查看
# HTTP请求参数
# 请求行
请求的第一行是“方法 URL 协议/版本”,并以 回车换行作为结尾。请求行以空格分隔。格式如下:
GET /index.html HTTP/1.1
以上代码中“GET”代表请求方法,“//ndex.html”表示URI,“HTTP/1.1代表协议和协议的版本
查看请求行的时候,点击Request Headers便可以查看
# GET
GET 方法用于获取由 Request-URI 所标识的资源的信息,常见的形式是:
GET Request-URI HTTP/1.1 GET方法是默认的HTTP请求方法,例如当我们通过在浏览器的地址栏中直接输入网址的方式去访问网页的时候,浏览器采用的就是 GET 方法向服务器获取资源。
我们可以使用GET方法来提交表单数据,用GET方法提交的表单数据只经过了简单的编码,同时它将作为URL的一部分向服务器发送,因此,如果使用GET方法来提交表单数据就存在着安全隐患上。例如: Http://localhost/login.php?username=aa&password=1234
从上面的URL请求中,很容易就可以辩认出表单提交的内容。(?之后的内容)另外由于GET方法提交的数据是作为URL请求的一部分所以提交的数据量不能太大。这是因为浏览器对url的长度有限制
各种浏览器也会对url的长度有所限制,下面是几种常见浏览器的url长度限制:(单位:字符)
IE : 2803
Firefox:65536
Chrome:8182
Safari:80000
Opera:190000
# POST
POST方法是GET方法的一个替代方法,它主要是向Web服务器提交表单数据,尤其是大批量的数据。 username=aa&password=1234
POST方法克服了GET方法的一些缺点。通过POST方法提交表单数据时,数据不是作为URL请求的一部分而是作为标准数据传送给Web服务器,这就克服了GET方法中的信息无法保密和数据量太小的缺点。因此,出于安全的考虑以及对用户隐私的尊重,通常表单提交时采用POST方法。
# GET与POST方法有以下区别:
1、 在客户端,Get方式在通过URL提交数据,数据在URL中可以看到;POST方式,数据放在HTTP包的body中。
2、 GET方式提交的数据大小有限制(因为浏览器对URL的长度有限制),而POST则没有此限制。
3、安全性问题。正如在(1)中提到,使用 Get 的时候,参数会显示在地址栏上,而 Post 不会。所以,如果这些数据是中文数据而且是非敏感数据,那么使用 get;如果用户输入的数据不是中文字符而且包含敏感数据,那么还是使用 post为好。
4.、服务器取值方式不一样。GET方式取值,如php可以使用$_GET来取得变量的值,而POST方式通过$_POST来获取变量的值。
# HEAD
HEAD 方法与 GET 方法几乎是相同的,它们的区别在于 HEAD 方法只是请求消息报头,而不是完整的内容。对于 HEAD 请求的回应部分来说,它的 HTTP 头部中包含的信息与通过 GET 请求所得到的信息是相同的。利用这个方法,不必传输整个资源内容,就可以得到 Request-URI 所标识的资源的信息。这个方法通常被用于测试超链接的有效性,是否可以访问,以及最近是否更新。
要注意的是,在 HTML 文档中,书写 get 和 post,大小写都可以,但在 HTTP 协议中的 GET 和 POST 只能是大写形式。
# 请求头
服务器端域
# Connection:
作用:表示是否需要持久连接。
如果服务器看到这里的值为“Keep-Alive”,或者看到请求使用的是HTTP 1.1(HTTP 1.1默认进行持久连接),它就可以利用持久连接的优点,当页面包含多个元素时(例如Applet,图片),显著地减少下载所需要的时间。要实现这一点,服务器需要在应答中发送一个Content-Length头,最简单的实现方法是:先把内容写入 ByteArrayOutputStream,然后在正式写出内容之前计算它的大小;
例如: Connection: keep-alive 当一个网页打开完成后,客户端和服务器之间用于传输HTTP数据的TCP连接不会关闭,如果客户端再次访问这个服务器上的 网页,会继续使用这一条已经建立的连接
例如: Connection: close 代表一个Request完成后,客户端和服务器之间用于传输HTTP数据的TCP连接会关闭, 当客户端再次发送Request,需要重新建立TCP连接。
# Host(发送请求时,该报头域是必需的)
Host请求报头域主要用于指定被请求资源的Internet主机和端口号,它通常从HTTP URL中提取出来的。
eg:http://;localhost/index.html 浏览器发送的请求消息中,就会包含Host请求报头域,如下: Host:localhost
此处使用缺省端口号80,若指定了端口号8080,则变成:Host:localhost:8080
# 请求体
请注意:get请求没有请求体,只有post请求才有请求体
# 获取请求信息
# request
Request类的请求继承关系
# org.apache.catalina.connector.RequestFacade ---> HttpServletRequest接口 ---> ServletRequest 接口
org.apache.catalina.connector.RequestFacade是tomcat自己的类,其继承了HttpServletRequest
只要浏览器发送请求并且和服务器建立连接,tomcat服务器就会自动创建一个org.apache.catalina.connector.RequestFacade对象,并且这个类实现了以上请求接口,我们可以直接使用这个请求对象,tomcat已经自动为我们实例化了这个对象
# 获取请求行信息
获取请求方式
getMethond() 返回String类型
获取虚拟目录
getContextPath()
获取servlet文件
getServletParh()
获取参数
getQueryString()
如果没有参数的话,那么就返回null
获取URL资源
获取URI getRequestURI()
获取URL getRequestURL()
什么是URI?
URI是统一资源标识符,没有host体,/chu/rd1 范围比URL大
URL是统一资源定位符 localhost/chu/rd1
获取协议版本
getProtocol()
获取客户端的IP 十六进制
getRemoteAdrr()
# 获取请求头信息
通过请求头名字获取
getHeadetName(String s) 返回这个头的值
获取所有的请求头名字
getHeaderNames() 返回的是一个Enumeration
<String>
类型
Enumeration<String>
类型,可以看做是一个迭代器,里面的方法和迭代器的使用相同
请求头的遍历
Enumeration<String> headerNames = request.getHeaderNames();
while (headerNames.hasMoreElements()) {
String name = headerNames.nextElement();
String value = request.getHeader(name);
System.out.println(name+"--->"+value);
}
2
3
4
5
6
# 获取请求体信息
只有post请求才有请求体
获取字符流
BufferedReader getReader() 只能用于字符
获取字节流
ServletInputStream getInputStream() 可以用于上传文件
request.setCharacterEncoding("utf-8");
//获取请求体信息
ServletInputStream ins = request.getInputStream();
OutputStream ous = new FileOutputStream(new File("D:\\360downloads\\22.jpg"));
int available = ins.available();
byte[] bytes = new byte[available];
ous.write(bytes);
ous.close();
使用这种方式实现文件的上传不太行
2
3
4
5
6
7
8
9
# 获取参数重要方法
下面的这些方法对于get请求还有post请求都能够使用
通过名称获取参数值
getParameter(String name) 返回值
String username = request.getParameter("username");
通过名称获取数组值,通常用于有多个选框,这种情况名称是相同的
getParameterValues(String name) String[] value 返回一个值数组
String[] hobbies = request.getParameterValues("hobby");
for (String hobby : hobbies) {
System.out.println(hobby);
}
2
3
4
获取所有名称的map集合
getParameterMap() 返回map集合
Map<String, String[]> parameterMap = request.getParameterMap();
Set<String> strings = parameterMap.keySet();
for (String name : strings) {
//通过参数名获取值
String[] parameterValues = request.getParameterValues(name);
for (String parameterValue : parameterValues) {
System.out.println(name+"--->"+parameterValue);
}
}
2
3
4
5
6
7
8
9
遍历map集合的方式有几种,可以转化为set集合,使用迭代器,也可以转化为entry集合
获取所有的参数名称,返回的是一个Enumeration对象,相当于迭代器
getParameterNames() 返回一个Enumeration
<String>
对象
Enumeration<String> parameterNames = request.getParameterNames();
while (parameterNames.hasMoreElements()) {
String name = parameterNames.nextElement();//获取名称
String[] parameterValues = request.getParameterValues(name);
for (String parameterValue : parameterValues) {
System.out.println(name+"--->"+parameterValue);
}
}
2
3
4
5
6
7
8
# 中文乱码问题
这种问题是对于post请求,对于get请求,从Tomcat 8版本开始,Tomcat内部就已经解决了乱码情况,但是还是每一次编写都解决这个问题
设置请求的编码方式
request.setCharacterEncoding("utf-8")
如果不设置的话,对于post请求,如果输入的是中文,那么结果就会出现乱码,问号
响应对象应该也需要设置
# 请求转发
通过从一个servlet类中跳转到另一个servlet类中,可以实现资源的跳转
步骤
通过请求对象获取请求转发器对象
RequestDispatcher requestDispatcher = request.getRequestDispatcher(String url);
注意,这里的参数url不能设置为统一资源定位符或者是统一资源标识符,只需要设置为servlet文件就行**/rd6**
使用RequestDispatcher对象来进行转发:
forward(ServletRequest request, ServletResponse response)
推荐连着写
request.getRequestDispatcher("/rd6").forward(request,response);
注意: 请求转发的时候,只能是对应请求方式之间的转发,如果servlet1的请求方式是get,但是你转发的数据是servlet的post请求,那么就不能进行转发
特点
浏览器的地址不会发生变化,尽管在内部访问的是两个servlet文件,但是浏览器中的地址是一个
只能转发内部的资源,对于外部的资源不能进行转发
外部资源像另一个module项目
不仅仅是针对于java程序,我们还可以是web页面
但是不知道为什么会出现这种情况
转发请求只有一个,通过抓包就可以看到
# 域对象
什么是域对象:
就是在一个servlet文件中,可以将一个对象(变量)进行存储,在进行请求转发的时候,就可以在另一个servlet文件中使用这个对象
步骤
存储对象
request.setAttribute(String s,Object o); 存储数据
s参数可以在请求转发到的那个文件中通过这个s获得这个o对象 o对象是需要存储的数据,什么数据都可以
在另一个servlet文件中获取这个对象
Object msg = request.getAttribute(Stirng s);
request.setAttribute("msg","hello world");//存储数据
request.getRequestDispatcher("/rd6").forward(request,response);
//获取对象
Object msg = request.getAttribute("msg");
System.out.println(msg);
2
3
4
5
6
7
注意:
在进行域对象的存储的时候,一定要在请求转发之前就进行存储,如果在请求转发之后进行,那么会另一servlet文件获取这个对象时,会返回null
request.getRequestDispatcher("/rd6").forward(request,response);
request.setAttribute("msg","hello world");//存储数据
2
3





