Javaweb笔记
一、HTTP协议
HTTP(超文本传输协议),它是一种主流B/S架构中应用的通信协议。具有以下的特点:
1.无状态
服务端不会记录客户端每次提交的请求,服务器一旦响应客户端之后,就会结束本次的通信过程。客户端下一次的请求是一个新的连接,和上一次通信没有任何关系。
2.简单灵活
HTTP是基于请求和响应的模型
3.支持客户端与服务端
支持主流的B/S以及C/S架构的通信。
注意:C/S架构可选的协议有多种,例如:TCP/IP,UDP,HTTP
而B/S架构通常只支持HTTP协议
二、服务器
1.概念
服务器通常由硬件和软件部分构成,统一对用户提供多种不同的服务。
1.硬件:包括相应的CPU、内存、磁盘等等
2.软件:包括操作系统、运行环境、服务端软件、数据库等等
2.web服务器
web服务器是提供服务端程序运行的一个环境,它本身也是一个软件。
例如:将我们编写的html文件放入到web服务器中,那么外界就可以通过浏览器来访问我们的html页面常见的web服务器Apache、Tomcat、Jetty、Nginx等等。而Tomcat、Jetty这些web服务器更准确的说是一个Servlet容器。
3.web项目结构
项⽬根⽬ |
录,例 如: myweb、 ch01 | 通常存放静态资源 ⽂件(如: html 等等) |
WEB INF | 这个⽬录是当前项 ⽬私有的⼀个⽂件 夹,只能提供给项 ⽬内部访问,对于 客户端来说是访问 不到了,通常这个 ⽬录下存放的是 Java源代码、编译 后的字节码⽂件以 及Servlet的核⼼ 配置⽂件web.xml |
src | 存放Java源代码的 ⽬录 |
classes | 存放编译后的字节 码⽂件 |
lib | lib⽬录存放当前项 ⽬所需要的jar⽂ 件 |
⽤于存放JSP动态 |
jsp | ⻚⾯ |
web.xml | 项⽬的配置⽂件, ⽤于配置Servlet 的请求映射、过滤 器、监听器等等信 息。每⼀个web项 ⽬都对应⼀个 web.xml配置⽂件 |
META INF | 配置应⽤程序、扩 展程序、类加载服 务等等 |
4.Servlet基础
4.1什么是Servlet
Servlet是JavaEE中的标准组件之⼀,专⻔⽤于处理客户端的HTTP请求。并且它必须依赖于Servlet容(Tomcat就是⼀个标准的Servlet容器)才可以运⾏,⽽不能脱离这个环境⽽单独执⾏。因为Servlet实例的创建和销毁都是由容器负责管理的,我们不能⾃⾏通过new关键去创建和使⽤它。
4.2编写一个简单的Servlet
1.
在任意地⽅创建⼀个
myweb
⽂件夹,这个⽂件夹相当于⼀个项⽬根⽬录2. 在根⽬录下创建 WEB-INF ⼦⽬录
3. 在 WEB-INF ⽬录下创建 src 和 classes ⼦⽬录
4.在src⽬录下编写⼀个类,继承HttpServlet这个⽗类
public class HelloServlet extends
HttpServlet {
}
2.重写⽗类的service⽅法,这个就是专⻔处理客户端请求的⽅法, web容器会为这个⽅法传⼊两个参数HttpServletRequest和HttpServletResponse,并且这个⽅法还需要抛出ServletException和IOException给容器捕获
public class HelloServlet extends
HttpServlet {
public void service(HttpServletRequest
request, HttpServletResponse
response)throws ServletException,
IOException{
//设置响应类型及编码
response.setContentType("text/html;charset
=utf-8");
//获取字符输出流输出html信息
response.getWriter().println("
<h1>Hello Servlet</h1>")
}
}
5.编译Servlet,需要依赖servlet-api.jar⽂件,将它添加到classpath中
javac -cp d:\servlet-api.jar;
HelloServlet.java
6.将编译后的HelloServlet.class⽂件剪切到classes⽬录中
7.在WEB-INF⽬录下创建并编辑web.xml⽂件,为servlet配置请求映射
<?xml version="1.0" encoding="utf-8"?>
<!-- 配置根节点 -->
<web-app>
<!-- 配置servlet类 -->
<servlet>
<!-- 指定servlet的别名 -->
<servlet-name>hello</servlet-name>
<!-- 指定Servlet的完整类名-->
<servlet-class>HelloServlet</servletclass>
</servlet>
<!-- 配置请求映射-->
<servlet-mapping>
<!-- 这⾥的servlet-name和上⾯的
servlet-name要⼀⼀对应 -->
<servlet-name>hello</servlet-name>
<!-- 配置请求映射的url,必须以“/”开头-->
<url-pattern>/hello</url-pattern>
</servlet-mapping>
</web-app>
9.打开浏览器,在地址栏输⼊http://localhost:8080/myweb/hello访问Servlet
4.3 Servlet的请求处理流程浏览器发起http的请求,这个请求⾸先会被servlet容器(Tomcat)截获,然后容器会根据web.xml⽂件中配置servlet的来找到相应的这个别名,然后再根据这个别名找到具体Servlet的类,然后容器会创建这个Servlet类的实例并调⽤service⽅法来处理这个请求。
4.4 Servlet的⽣命周期
所谓的⽣命周期,就是从Servlet的创建⼀直到它销毁的整个过程。并且它的这个⽣命周期都是由Servlet容(Tomcat)负责管理和维护的。(补充:在Tomcat中, Servlet是以单实例多线程的⽅式处理客户端请求)
4.4.1 Servlet对象创建的过程
当第⼀次请求某个Servlet的时候,容器会先查找之前有没有创建过这个Servlet的实例,如果没有则创建⼀个并缓存起来。后续相同的请求都由这个缓存的对象来处理。(注意:这⾥说的是第⼀次请求时创建。另外⼀种情况则是在容器启动的时候就创建Servlet的实例,在web.xml中为Servlet指定配置,这个配置的值是⼀个整型,数值越⼩,则初始化的优先级别越⾼)
4.4.2 ⽣命周期⽅法
⽅法名 | 描述 |
init | 在Servlet对象创建之后⽴即执⾏的初始化 ⽅法,且只执⾏⼀次 |
service | 核⼼的请求处理⽅法,这个⽅法可以执⾏ 多次 |
destroy | 容器准备销毁Servlet实例之前执⾏这个⽅ 法,也是执⾏⼀次 |
4.5 HTTP报⽂组成
4.5.1 请求报⽂
请求⾏:请求报⽂的第⼀⾏就是请求⾏。包括请求⽅法、请求URL地址、 HTTP协议版本。请求头:请求⾏之后的信息就是请求头,它是以“名称:内容”的格式体现。主要包括服务器主机地址及端⼝、连接状态、系统信息、编码、语⾔等等。请求体:请求头结束之后会有⼀个空⾏,空⾏之后就是请求体的内容。通常使⽤POST提交的数据信息会存放在请求体当中,然后传递给服务器。
4.5.2响应报文
状态⾏:主要包括HTTP协议、响应状态码(例如:200表示OK,成功响应)。响应头:主要包括服务器信息响应的类型及编码、内容的⻓度、响应的时间等。响应体:服务端可以将信息数据携带到响应体中,带回客户端。 4.6 HTTP请求⽅法
在HTTP/1.1协议中,请求⽅法主要包括8个,下⾯列举常⽤的请求⽅法进⾏说明。
⽅法 | 说明 |
GET | 向服务器请求指定的资源,并返回响应主 体。⼀般来说GET⽅法应该只⽤于数据的 读取(类似于查询) |
POST | 向指定的服务器提交数据(例如:表单数 据的提交、⽂件上传等) ,并且提交的数据 会放⼊请求体中(类似于新增) |
PUT | 向服务器提交数据,但是和POST有所区 别。如果服务器不存在此资源的时候,则 执⾏新增,如果存在则执⾏修改(类似于 修改) |
DELETE | 根据uri的标识删除服务器上的某个资源 (类似于删除) |
其他 | ... |
备注: GET 与 POST 区别:
1.GET 主要⽤于获取数据, POST ⽤于提交数据。
2.GET 请求所带的参数是放在请求⾏的 url 地址后⾯,⽽
POST 这是放在请求体中。
3. 通常浏览器会对 GET 请求的 url ⻓度有所限制,⽽ POST 提交的数据在请求体中,可以提交更多的内容。
4.浏览器会对GET请求进⾏缓存。
4.7 Servlet的请求处理⽅法
⽅法 | 说明 |
service | 可以处理任何的请求类型 |
doGet | 处理对应的GET请求 |
doPost | 处理对应的POST请求 |
doPut | 处理对应的PUT请求 |
doDelete | 处理对应的DELETE请求 |
其他 | ... |
说明:通过 HttpServlet 的源代码得知,默认的所有请求都会先经过 service ⽅法,然后 service ⽅法根据请求的⽅法类型判断来决定交给 doGet 或者是 doPost ⽅法来处理请求。如果⼦类重写了⽗类的 service ⽅法同时还重写了其他的 doXxx 的⽅法,那么只有 service ⽅法会 处理请求,其他⽅法将失效。
4.8 Request与Response对象
当web容器调⽤某个Servlet的Service⽅法时,会创建⼀个HttpServletRequest和HttpServletRespinse对象
作为参数传⼊到这个⽅法中,那么我们可以通过HttpServletRequest来获取相关的请求内容等,⽽响应客户端可以利⽤HttpServletResponse对象来完成。
4.8.1 HttpServletRequest常⽤API
⽅法 | 说明 |
getParameter(String name) | 获取请求参数,根据请求 参数的name指定 |
getParameterValues(Spring name) | 获取相同name的请求参 数,返回的是字符串数组 |
getParameterNames() | 获取所有的请求参数名称 |
getParameterMap() | 获取所有请求参数,包括 参数名称和值 |
getMethod() | 获取客户端的请求⽅法 |
getHeader(String name) | 根据请求头的名称获取响 应的信息 |
getRemoteAddr() | 获取远程客户端的IP地址 |
getServletPath() | 获取Servlet的请求地址, 也就是url-pattern |
getRequestURL() | 获取请求完整的URL地址 |
getRealPath(String path) | 获取项⽬的绝对路径。 (这个⽅法在request对 象中已废弃,建议通过 ServletContext对象获 取) |
其他 | ... |
4.8.2 HttpServletResponse常⽤API
⽅法 | 说明 |
setContentType(String str) | 设置响应内容的类型及编 码 |
getWriter() | 获取响应字符输出流 |
getOutputStream() | 获取字节输出流 |
setHeader(String name, String value) | 设置响应头信息,如果存 在响应头信息,则执⾏更 新 |
addHeader(String name, String value) | 设置响应头,不管存不存 在都会新加⼊⼀个 |
setStatus(int code) | 设置响应状态码 |
其他 |
...
|
4.8.3 常⻅的响应状态码
状态码 | 说明 |
200 | 请求已成功 |
401 | 请求被禁⽌,未授权 |
404 | 请求的资源不存在 |
405 | 请求⾏的⽅法不被⽀持 |
500 | 服务器内部错误 |
其他 | ... |
4.9 Servlet之间的通信
4.9.1 转发
所谓转发,就是在多个Servlet之间共享请求和响应对象,所有参与转发过程的Servlet都可以共享同⼀个请求对象的信息,在Servlet的API中,转发的操作是由HttpServletRequest对象完成的。
转发的特点
1. URL地址栏不会发⽣改变
2. 转发的过程是在服务端⾃动完成
示例代码:
public class ServletA extends HttpServlet{
public void service(HttpServletRequest
request, HttpServletResponse response)
throws ServletException, IOException{
//获取⻚⾯提交的参数
String name =
request.getParameter("userName");
//转发由HttpServletRequest完成
//第⼀步先获取⼀个请求转发器
RequestDispatcher
//获取请求转发器的同时要告诉转发器转发
到哪⾥,转发给谁
//如果要转发给ServletB,那么就是对应
ServletB的url-pattern
RequestDispatcher rd =
request.getRequestDispatcher("servletB");
//调⽤转发器的forward⽅法执⾏转发,同
时将request和response对象⼀并转发ServletB
rd.forward(request, response);
}
}
public class ServletB extends HttpServlet{
public void service(HttpServletRequest
request, HttpServletResponse response)
throws ServletException, IOException {
//这⾥可以获得同⼀个请求的参数
String name =
request.getParameter("userName");
System.out.println("ServletB获取请求
参数: "+name);
}
}
请求作⽤域:
每⼀个请求对象都有⼀个独⽴的空间,这个空间我们称之为请求作⽤域(RequestScope)。可以为当前这个请求携带额外的⼀些数据信息,这些信息同可以在多个Servlet之间进⾏共享。
示例代码:
public class ServletB extends HttpServlet{
public void service(HttpServletRequest
request, HttpServletResponse response)
//
这⾥可以获得同⼀个请求的参数
String name =
request.getParameter("userName");
System.out.println("ServletB获取请求
参数: "+name);
}
public class ServletA extends HttpServlet {
public void service(HttpServletRequest
request, HttpServletResponse response)
throws ServletException, IOException{
//在ServletA中为request对象设置请求作
⽤域
request.setAttribute("age", 35);
}
}
public class ServletB extends HttpServlet{
public void service(HttpServletRequest
request, HttpServletResponse response)
throws ServletException, IOException{
//在ServletB中获取统⼀个请求对象作⽤
域的值
Integer age =
(Integer)request.getAttribute("age");
}
重定向的机制和转发不同,⾸先重定向是通过HttpServletResponse对象来完成。⼀次重定向的过程中会有两次请求和两次响应,服务器在接收第⼀次请求后会先做⼀次302的响应(302表示重定向状态码),告诉客户端浏览器必须发起⼀个新的请求地址,服务端再次接收这个请求处理,最后再次响应客户端。由于会产⽣不同的请求对象,因此并不同共享同⼀个请求中的参数。
1. URL地址栏会发⽣改变
2. 重定向的操作是在客户端浏览器完成的
示例代码:
⽅式⼀:
⽅式⼆:
public class ServletC extends HttpServlet {
@Override
protected void
service(HttpServletRequest request,
HttpServletResponse response) throws
ServletException, IOException {
//执⾏重定向
//⽅式⼀:设置302响应状态码,并在响应
头中添加location属性指定重定向的地址
response.setStatus(302);
response.addHeader("location",
"http://localhost:8080/ch06/servletD");
}