文章目录
提示:以下是本篇文章正文内容,下面案例可供参考
一、B/S结构的系统通信原理
关于域名:
- https://www.baidu.com/ (网址)
- www.baidu.com 是一个域名
- 在浏览器地址栏上输入域名,回车之后,域名解析器会将域名解析出来一个具体的IP地址和端口号等。
- 解析结果也许是:http://110.242.68.3:80/index.html
IP地址是啥?
- 计算机在网络当中的一个身份证号。在同一个网络当中,IP地址是唯一的。
- A计算机要想和B计算机通信,首先你需要知道B计算机的IP地址,有了IP地址才能建立连接。
端口号是啥?
- 一个端口代表一个软件(一个端口代表一个应用,一个端口仅代表一个服务)。
- 一个计算机当中有很多软件,每一个软件启动之后都有一个端口号。
- 在同一个计算机上,端口号具有唯一性。
什么是URL?
- 统一资源定位符(http://www.baidu.com)
什么是请求,什么是响应?
- 从Browser端发送数据到Server端,我们称为请求----request
- 从Server端向浏览器Browser端发送数据,我们称为响应–response
二、下载并使用TOMCAT
- Tomcat下载
- tomcat官网地址:https://tomcat.apache.org
- tomcat开源免费的轻量级WEB服务器。
- tomcat的logo是一只公猫(寓意表示Tomcat服务器是轻巧的,小巧的,果然,体积小,运行速度快,只实现了Servlet+JSP规范)
- tomcat是java语言写的。
- Tomcat服务器要想运行,需要先有jre,所以要先安装JDK,配置java运行环境。
- 配置Tomcat服务器需要哪些环境变量?
- JAVA_HOME=JDK的根
- TOMCAT_HOME=Tomcat服务器的根
- PATH=%JAVA_HOME%\bin;%TOMCAT_HOME%\bin
- 测试Tomcat服务器有没有启动成功呢?
- 在浏览器的地址栏上输入URL即可:
- http://ip地址(localhost):端口号(8080)
三.Servlet对象的生命周期
Servlet对象是由谁来维护的?
- Servlet对象的创建,对象上方法的调用,对象最终的销毁,Javaweb程序员是无权干预的。
- Servlet对象的生命周期是由Tomcat服务器(WEB Server)全权负责的。
- Tomcat服务器通常我们又称为:WEB容器。
- WEB容器来管理Servlet对象的死活。
思考:我们自己new的Servlet对象受WEB容器的管理吗?
- 我们自己new的Servlet对象是不受WEB容器管理的。
- WEB容器创建的Servlet对象,这些Servlet对象都会被放到一个集合当中(HashMap),只有放到这个HashMap集合中的Servlet才能够被WEB容器管理,自己new的Servlet对象不会被WEB容器管理。(自己new的Servlet对象不在容器当中)
web容器底层应该有一个HashMap这样的集合,在这个集合当中存储了Servlet对象和请求路径之间的关系
服务器在启动的Servlet对象有没有被创建出来(默认情况下)?
- 经过测试得出结论:默认情况下,服务器在启动的时候Servlet对象并不会被实例化。
- 这个设计是合理的。用户没有发送请求之前,如果提前创建出来所有的Servlet对象,必然是耗费内存的,并且创建出来的Servlet如果一直没有用户访问,显然这个Servlet对象是一个废物,没必要先创建。
怎么让服务器启动的时候创建Servlet对象呢?
在servlet标签中添加子标签,在该子标签中填写整数,越小的整数优先级越高。
<servlet> <servlet-name>aservlet</servlet-name> <servlet-class>com.bjpowernode.javaweb.servlet.AServlet</servlet-class> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>aservlet</servlet-name> <url-pattern>/a</url-pattern> </servlet-mapping>
Servlet对象生命周期
- 第一:Servlet对象是单例的(单实例的。但是要注意:Servlet对象是单实例的,但是Servlet类并不符合单例模式。我们称之为假单例。之所以单例是因为Servlet对象的创建我们javaweb程序员管不着,这个对象的创建只能是Tomcat来说了算,Tomcat只创建了一个,所以导致了单例,但是属于假单例。真单例模式,构造方法是私有化的。)
- 第二:无参数构造方法、init方法只在第一次用户发送请求的时候执行。也就是说无参数构造方法只执行一次。init方法也只被Tomcat服务器调用一次。
- 第三:只要用户发送一次请求:service方法必然会被Tomcat服务器调用一次。发送100次请求,service方法会被调用100次。
- 第四:在服务器关闭的时候。因为服务器关闭的时候要销毁AServlet对象的内存。 服务器在销毁AServlet对象内存之前,Tomcat服务器会自动调用AServlet对象的destroy方法。
关于Servlet类中方法的调用次数?
- 构造方法只执行一次。
- init方法只执行一次。
- service方法:用户发送一次请求则执行一次,发送N次请求则执行N次。
- destroy方法只执行一次。
init、service、destroy方法中使用最多的是哪个方法?
- 使用最多就是service方法,service方法是一定要实现的,因为service方法是处理用户请求的核心方法。
- 什么时候使用init方法呢?
- init方法很少用。
- 通常在init方法当中做初始化操作,并且这个初始化操作只需要执行一次。例如:初始化数据库连接池,初始化线程池…
- 什么时候使用destroy方法呢?
- destroy方法也很少用。
- 通常在destroy方法当中,进行资源的关闭。马上对象要被销毁了,还有什么没有关闭的,抓紧时间关闭资源。还有什么资源没保存的,抓紧时间保存一下。
四.GenericServlet — 适配器设计模式Adapter
我们编写一个Servlet类直接实现Servlet接口有什么缺点?
- 我们只需要service方法,其他方法大部分情况下是不需要使用的。代码很丑陋。
编写一个GenericServlet类,这个类是一个抽象类,其中有一个抽象方法service。
- GenericServlet实现Servlet接口。
- GenericServlet是一个适配器。
- 以后编写的所有Servlet类继承GenericServlet,重写service方法即可。
思考第一个问题:我提供了一个GenericServlet之后,init方法还会执行吗?
- 还会执行。会执行GenericServlet类中的init方法。
思考第二个问题:init方法是谁调用的?
- Tomcat服务器调用的。
思考第三个问题:init方法中的ServletConfig对象是谁创建的?是谁传过来的?
- 都是Tomcat干的。
- Tomcat服务器先创建了ServletConfig对象,然后调用init方法,将ServletConfig对象传给了init方法。
五. ServletConfig
什么是ServletConfig?
- Servlet对象的配置信息对象。
- ServletConfig对象中封装了标签中的配置信息。(web.xml文件中servlet的配置信息)
一个Servlet对应一个ServletConfig对象。
Servlet对象是Tomcat服务器创建,并且ServletConfig对象也是Tomcat服务器创建。并且默认情况下,他们都是在用户发送第一次请求的时候创建。
Tomcat服务器调用Servlet对象的init方法的时候需要传一个ServletConfig对象的参数给init方法。
ServletConfig接口有哪些常用的方法?
public String getInitParameter(String name); // 通过初始化参数的name获取value public Enumeration<String> getInitParameterNames(); // 获取所有的初始化参数的name public ServletContext getServletContext(); // 获取ServletContext对象 public String getServletName(); // 获取Servlet的name
六.ServletContext
一个Servlet对象对应一个ServletConfig。100个Servlet对象则对应100个ServletConfig对象。
只要在同一个webapp当中,只要在同一个应用当中,所有的Servlet对象都是共享同一个ServletContext对象的。
ServletContext对象在服务器启动阶段创建,在服务器关闭的时候销毁。这就是ServletContext对象的生命周期。ServletContext对象是应用级对象。
Tomcat服务器中有一个webapps,这个webapps下可以存放webapp,可以存放多个webapp,假设有100个webapp,那么就有100个ServletContext对象。但是,总之,一个应用
一个ServletContext对象通常对应的是一个web.xml文件。
ServletContext接口中有哪些常用的方法?
public String getInitParameter(String name); // 通过初始化参数的name获取value public Enumeration<String> getInitParameterNames(); // 获取所有的初始化参数的name
<!--以上两个方法是ServletContext对象的方法,这个方法获取的是什么信息?是以下的配置信息--> <context-param> <param-name>pageSize</param-name> <param-value>10</param-value> </context-param> <context-param> <param-name>startIndex</param-name> <param-value>0</param-value> </context-param> <!--注意:以上的配置信息属于应用级的配置信息,一般一个项目中共享的配置信息会放到以上的标签当中。--> <!--如果你的配置信息只是想给某一个servlet作为参考,那么你配置到servlet标签当中即可,使用ServletConfig对象来获取。-->
// 获取应用的根路径(非常重要),因为在java源代码当中有一些地方可能会需要应用的根路径,这个方法可以动态获取应用的根路径 // 在java源码当中,不要将应用的根路径写死,因为你永远都不知道这个应用在最终部署的时候,起一个什么名字。 public String getContextPath(); //String contextPath = application.getContextPath();
向ServletContext中存 删 取 数据
// 存(怎么向ServletContext应用域中存数据)
public void setAttribute(String name, Object value); // map.put(k, v)
// 取(怎么从ServletContext应用域中取数据)
public Object getAttribute(String name); // Object v = map.get(k)
// 删(怎么删除ServletContext应用域中的数据)
public void removeAttribute(String name); // map.remove(k)
注意:以后我们编写Servlet类的时候,实际上是不会去直接继承GenericServlet类的,因为我们是B/S结构的系统,这种系统是基于HTTP超文本传输协议的,在Servlet规范当中,提供了一个类叫做HttpServlet,它是专门为HTTP协议准备的一个Servlet类。我们编写的Servlet类要继承HttpServlet。(HttpServlet是HTTP协议专用的。)使用HttpServlet处理HTTP协议更便捷。
jakarta.servlet.Servlet(接口)【爷爷】
jakarta.servlet.GenericServlet implements Servlet(抽象类)【儿子】
jakarta.servlet.http.HttpServlet extends GenericServlet(抽象类)【孙子】
我们以后编写的Servlet要继承HttpServlet类。
七.HTTP协议
HTTP的请求协议(B --> S)
HTTP的请求协议包括:4部分
- 请求行
- 请求头
- 空白行
- 请求体
- 请求行
- 包括三部分:
- 第一部分:请求方式(7种)
- get(常用的)
- post(常用的)
- delete
- put
- head
- options
- trace
- 第二部分:URI
- 什么是URI? 统一资源标识符。代表网络中某个资源的名字。但是通过URI是无法定位资源的。
- 什么是URL?统一资源定位符。代表网络中某个资源,同时,通过URL是可以定位到该资源的。
- URI和URL什么关系,有什么区别?
- URL包括URI
- http://localhost:8080/servlet05/index.html 这是URL。
- /servlet05/index.html 这是URI。
- 第三部分:HTTP协议版本号
- 请求头
- 请求的主机
- 主机的端口
- 浏览器信息
- 平台信息
- cookie等信息
- ....
- 空白行
- 空白行是用来区分“请求头”和“请求体”
- 请求体
- 向服务器发送的具体数据。
HTTP的响应协议(S --> B)
HTTP的响应协议包括:4部分
- 状态行
- 响应头
- 空白行
- 响应体
- 状态行
- 三部分组成
- 第一部分:协议版本号(HTTP/1.1)
- 第二部分:状态码(HTTP协议中规定的响应状态号。不同的响应结果对应不同的号码。)
- 200 表示请求响应成功,正常结束。
- 404表示访问的资源不存在,通常是因为要么是你路径写错了,要么是路径写对了,但是服务器中对应的资源并没有启动成功。总之404错误是前端错误。
- 405表示前端发送的请求方式与后端请求的处理方式不一致时发生:
- 比如:前端是POST请求,后端的处理方式按照get方式进行处理时,发生405
- 比如:前端是GET请求,后端的处理方式按照post方式进行处理时,发生405
- 500表示服务器端的程序出现了异常。一般会认为是服务器端的错误导致的。
- 以4开始的,一般是浏览器端的错误导致的。
- 以5开始的,一般是服务器端的错误导致的。
- 第三部分:状态的描述信息
- ok 表示正常成功结束。
- not found 表示资源找不到。
- 响应头:
- 响应的内容类型
- 响应的内容长度
- 响应的时间
- ....
- 空白行:
- 用来分隔“响应头”和“响应体”的。
- 响应体:
- 响应体就是响应的正文,这些内容是一个长的字符串,这个字符串被浏览器渲染,解释并执行,最终展示出效果。
怎么向服务器发送GET请求,怎么向服务器发送POST请求?
- 到目前为止,只有一种情况可以发送POST请求:使用form表单,并且form标签中的method属性值为:method=“post”。
- 其他所有情况一律都是get请求:
- 在浏览器地址栏上直接输入URL,敲回车,属于get请求。
- 在浏览器上直接点击超链接,属于get请求。
- 使用form表单提交数据时,form标签中没有写method属性,默认就是get
- 或者使用form的时候,form标签中method属性值为:method=“get”
- …
GET请求和POST请求有什么区别?
- get请求发送数据的时候,数据会挂在URI的后面,并且在URI后面添加一个“?”,"?"后面是数据。这样会导致发送的数据回显在浏览器的地址栏上。(get请求在“请求行”上发送数据)
- http://localhost:8080/servlet05/getServlet?username=zhangsan&userpwd=1111
- post请求发送数据的时候,在请求体当中发送。不会回显到浏览器的地址栏上。也就是说post发送的数据,在浏览器地址栏上看不到。(post在“请求体”当中发送数据)
- get请求无法发送大数据量。
- post请求可以发送任何类型的数据,包括普通字符串,流媒体等信息:视频、声音、图片。
- get请求在W3C中是这样说的:get请求比较适合从服务器端获取数据。
- post请求在W3C中是这样说的:post请求比较适合向服务器端传送数据。
- get请求发送数据的时候,数据会挂在URI的后面,并且在URI后面添加一个“?”,"?"后面是数据。这样会导致发送的数据回显在浏览器的地址栏上。(get请求在“请求行”上发送数据)
八.关于WEB-INF目录
- 在WEB-INF目录下新建了一个文件:welcome.html
- 打开浏览器访问:http://localhost:8080/servlet07/WEB-INF/welcome.html 出现了404错误。
- 注意:放在WEB-INF目录下的资源是受保护的。在浏览器上不能够通过路径直接访问。所以像HTML、CSS、JS、image等静态资源一定要放到WEB-INF目录之外。
九.HttpServletRequest接口详解
HttpServletRequest是一个接口,全限定名称:jakarta.servlet.http.HttpServletRequest
HttpServletRequest接口是Servlet规范中的一员。
HttpServletRequest接口的父接口:ServletRequest
代码如下(示例):HttpServletRequest对象中都有什么信息?都包装了什么信息?
- HttpServletRequest对象是Tomcat服务器负责创建的。封装了HTTP的请求协议。
- 实际上是用户发送请求的时候,遵循了HTTP协议,发送的是HTTP的请求协议,Tomcat服务器将HTTP协议中的信息以及数据全部解析出来,然后Tomcat服务器把这些信息封装到HttpServletRequest对象当中,传给了我们javaweb程序员。
- javaweb程序员面向HttpServletRequest接口编程,调用方法就可以获取到请求的信息了。
HttpServletRequest接口中有哪些常用的方法?
Map<String,String[]> getParameterMap() 这个是获取Map Enumeration<String> getParameterNames() 这个是获取Map集合中所有的key String[] getParameterValues(String name) 根据key获取Map集合的value String getParameter(String name) 获取value这个一维数组当中的第一个元素。这个方法最常用。 // 以上的4个方法,和获取用户提交的数据有关系。
应用域对象–ServletContext (Servlet上下文对象。)
void setAttribute(String name, Object obj); // 向域当中绑定数据。
Object getAttribute(String name); // 从域当中根据name获取数据。
void removeAttribute(String name); // 将域当中绑定的数据移除
- “请求域”对象–request
void setAttribute(String name, Object obj); // 向域当中绑定数据。
Object getAttribute(String name); // 从域当中根据name获取数据。
void removeAttribute(String name); // 将域当中绑定的数据移除
尽量使用小的域对象,因为小的域对象占用的资源较少。
- 跳转
- 转发(一次请求)
// 第一步:获取请求转发器对象
RequestDispatcher dispatcher = request.getRequestDispatcher("/b");
// 第二步:调用转发器的forward方法完成跳转/转发
dispatcher.forward(request,response);
关于request对象中两个非常容易混淆的方法:
- ```java // uri?username=zhangsan&userpwd=123&sex=1 String username = request.getParameter("username"); // 之前一定是执行过:request.setAttribute("name", new Object()) Object obj = request.getAttribute("name"); // 以上两个方法的区别是什么? // 第一个方法:获取的是用户在浏览器上提交的数据。 // 第二个方法:获取的是请求域当中绑定的数据。 ```
十.web应用中应该如何完成资源的跳转
在一个web应用中通过两种方式,可以完成资源的跳转:
- 第一种方式:转发
- 第二种方式:重定向
转发和重定向有什么区别?
代码上有什么区别?
转发
// 获取请求转发器对象 RequestDispatcher dispatcher = request.getRequestDispatcher("/dept/list"); // 调用请求转发器对象的forward方法完成转发 dispatcher.forward(request, response); // 合并一行代码 request.getRequestDispatcher("/dept/list").forward(request, response); // 转发的时候是一次请求,不管你转发了多少次。都是一次请求。 // AServlet转发到BServlet,再转发到CServlet,再转发到DServlet,不管转发了多少次,都在同一个request当中。 // 这是因为调用forward方法的时候,会将当前的request和response对象传递给下一个Servlet。
重定向
// 注意:路径上要加一个项目名。为什么? // 浏览器发送请求,请求路径上是需要添加项目名的。 // 以下这一行代码会将请求路径“/oa/dept/list”发送给浏览器 // 浏览器会自发的向服务器发送一次全新的请求:/oa/dept/list response.sendRedirect("/oa/dept/list");
形式上有什么区别?
- 转发(一次请求)
- 在浏览器地址栏上发送的请求是:http://localhost:8080/servlet10/a ,最终请求结束之后,浏览器地址栏上的地址还是这个。没变。
- 重定向(两次请求)
- 在浏览器地址栏上发送的请求是:http://localhost:8080/servlet10/a ,最终在浏览器地址栏上显示的地址是:http://localhost:8080/servlet10/b
- 转发(一次请求)
转发和重定向的本质区别?
- 转发:是由WEB服务器来控制的。A资源跳转到B资源,这个跳转动作是Tomcat服务器内部完成的。
- 重定向:是浏览器完成的。具体跳转到哪个资源,是浏览器说了算。