Servlet
概念
Servlet Applet 是--->使用java语言编写的运行在服务器上(web服务器/应用服务器)的程序.
他是作为浏览器客户端和服务器端上的数据库或者程序之间的中间层,起到一个桥梁作用,使用Servlet可以做到获取浏览器客户端中的表单数据和客户端发送的一些请求信息,
关联后端数据库做完业务处理,把处理后的结果值在返回给浏览器客户端展示
Servlet的生命周期
○ 第一个方法:init()初始化Servlet类对象信息,当Servlet对象创建的时候被调用,而且只会调用一次
§ Servlet类对象什么时候会被创建出来?
□ 默认情况下,该Servlet类被第一次访问的时候,Servlet对象被创建出来
□ 手动指定Servlet类对象创建时机.
? 通常在<servlet>标签中的配置<load-on-startup>标签
1.第一次访问的时候被创建出来
<load-on-startup>标签 的值为负数
2.在服务器启动的时候被创建出来
<load-on-startup>的值为0或者正整数
注意
} load-on-startup是用来标记容器是否在启动的时候就加载这个Servlet(实例化并执行init方法)
} load-on-startup他得知必须是一个整数,表示这个Servlet类加载的顺序
} 当值为>=0的时候,表示容器在应用启动的时候加载并初始化这个Servlet类
} 当值为<0的时候,表示容器在该Servlet类被选择时候才会去加载
} 整数的值越小,表明该Servlet类在容器中的优先级越高,应用启动的时候就越先加载
} 当值相同的时候容器会自己选择一个Servlet去加载
备注
} 在Servlet接口中的init()方法,只会执行一次,说明一个Servlet在内存当中只会存在一个对象.
Servlet是单例的
– 狭义:一个类在内存当中有且仅有一个类对象,而且这个类对象自始至终都是同一个对象
做法:把该类的构造器私有化,new的动作只能在类内部使用
– 广义:只要满足在整个系统中或者应用中有且仅有一个实例即可.不保证是同一个
– 在Servlet3.1规范中,当自定义Servlet类没有实现SingleThreadMode接口的时候,Servlet类才是单例的
– 如果实现该接口那么每次请求该Servlet类的时候,容器都会创建一个新的Servlet类对象
– 面试题:Servlet容器如何保证在多线程环境下访问数据的安全性问题
Servlet容器默认情况下采用单例多线程方式处理多个请求
w 当web容器启动的时候(或者客户端发送请求的时候),Servlet就会被加载并实例化
w 容器初始化Servlet主要就是读取配置文件(web.xml).在tomcat容器中也有一个web.xml,在Serve.xml中可以设定线程池中的数目,初始化线程池通过web.xml
w 当客户端请求到达时,Servlet容器可以通过线程调度它管理的下的线程池中的等待执行的线程
w 线程执行Servlet类中的service方法
w 当线程执行完毕,归还线程到线程池中
w 当多个用户同时访问同一个Servlet类的时候,可能存在线程数据安全问题
做法:不要再Servlet中定义成员变量,如果定义了,也不要去修改该成员变量值
○ Servlet类中的service():当客户端发送请求的时候,会执行service方法,而且会执行多次
○ Servlet类中的destroy():当Servlet类对象被销毁的时候,会调用他\
§ 当服务器正常关闭的时候,就会调用destroy方法
§ 当Servlet类被修改时候,也会执行destroy方法
Servlet3.0
提供了注解配置
? 好处:不需要再到web.xml文件去注册Servlet类信息
? 步骤
1.选择Java项目于 Servlet3.0版本以上,创建一个Servlet类
2.在该Servlet类上面添加@WebServlet
3.在该注解中配置一个客户端url请求资源路径
4.@WebServlet("/请求资源路径")
@java.lang.annotation.Target({java.lang.annotation.ElementType.TYPE})
@java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.RUNTIME)
@java.lang.annotation.Documented
public @interface WebServlet {
java.lang.String name() default "";//相当于<servlet-name>
java.lang.String[] value() default {};//代表urlpatterns属性
java.lang.String[] urlPatterns() default {};//相当于<url-pattern>
int loadOnStartup() default -1;//相当于<load-on-startup>
欢迎界面
当我们向浏览器中输入我们的服务器地址,路径url格式":http://localhost:8080/day48/,此时tomcat会自动按照在web.xml文件中配置的<welcom-file-list>从上到下依次查找对应的web资源,如果全部找完没有发现对应的资源,服务器会给浏览器客户端返回一个404状态码(404表示web资源在服务器中没找到),表明web资源路径不匹配.如果找到了,就是我们需要的欢迎界面
注意:
○ 访问的是当前web应用根目录下的文件资源,一般情况下我们访问的都是web文件夹下的资源
○ 有一个文件夹下面的资源直接通过浏览器是访问不到的 WEB-INF(安全目录,保护目录)
○ 只能通过服务器内部来访问.
○ 在<welcome-file-list>标签内部配置的欢迎界面是一种服务器行为,在浏览器客户端尚直接访问WEB-INF里面的资源不可行的.
如:http://localhost/WEB-INF/view/userList.html-->404
Servlet相关配置
我们主要配置<url-pattern>客户端访问web应用资源的路径
○ String[] urlPatterns();一个Servlet可以配置多个访问路径 @WebServlet({"/demo01","/demo02","/demo03",……})
○ 路径定义的规则:
§ /xxx: 路径匹配/完全匹配
§ /xxx/yyy/…: 多层路径匹配/目录匹配--->路径窄化
§ /缺省配置: 当访问web应用中的资源(Servlet)都不匹配,此时会找缺省配置的Servlet信息,让这个缺省配置的Servlet来处理请求资源
当前Servlet它能够处理的资源Servlet和静态资源,jsp资源解决不了
§ /*全部处理 处理静态资源和jsp资源,只能借助于Servlet中访问方式:内部转发和重定向 释放资源
§ *.do *.action: 扩展名匹配 一般要写具体的哪一个服务 userEdit.do,userEdit.action
HTTP
Hyper Text Transport Protocol 超文本传输协议,是互联网中应用最广泛的一种网络协议
传输协议:定义了客户端和服务器端通信时,发送数据的格式.
○ 特点:
§ 基于TCP,IP的协议
§ 默认端口号是80端口
§ 基于请求与响应模型的,一次请求对应一次响应
§ 无状态的:每次请求之间是相互独立的,每次请求之间不能进行数据的交互
§ 历史版本:
□ 1.0 每一次请求与响应都需要建立一次连接,请求与相应结束后连接随着断开,每次建立的连接都是新连接
□ 1.1 持久连接
? 1.1版本最大的变化就是引入持久连接:请求响应结束后默认情况下是不断开 被多个请求所复用,
不在声明:Connection :keep-alive
? 客户端和服务器端发现对方有一段时间没有活动,就会主动关闭连接.如果在客户端发送最后一个请求时,这个请求发送了Connection:close,明确要求服务器关闭TCP连接
? 目前大多数浏览器对于同一个域名最多同时允许建立六个持久连接,提高了带宽的利用率
? 加入了管道机制.在同一个连接里面,允许同时发送多个请求增加了并发性.改善了Http协议的效率
1.1版本作为目前最主流的版本
□ 2.0
? 为了解决利用率不高的问题,继续优化,提供了2.0版本.增加了双工模式.即不仅客户端能够同时发送多个请求,服务器同时处理多个请求,解决了对头堵塞问题
○ 协议的组成与过程
HTTP协议它是由HTTP请求和HTTP响应组成的.当在客户端中输入一个url地址回车,浏览器会将你的请求消息封装为一个HTTP请求的格式
发送给服务器端,服务器端收到这个消息后,解析这个请求消息将他装配到ServletRequest,做完业务逻辑之后组织响应数据封装为一个
HTTP响应的格式返回给浏览器客户端,这个过程就是请求与响应的过程,如果没有请求就没有响应
○ 抓包分析
使用Chrome自带的抓包工具可以看到数据之间相互传输的过程
HTTP请求
get请求---Http默认的请求方式是get请求(直接在客户端的地址栏中输入url和使用<a href = "请求资源路径"></a>),对于from表单可以指定请求的方式为post
//请求行 请求方式,请求路径,HTTP版本号{
scheme
//本机服务器ip地址 域名
http
host
localhost
filename
/checkUser
username
admin
password
123456
地址
127.0.0.1:80
状态
200
版本HTTP/1.1
传输121 字节(大小 0 字节)
Referrer 政策no-referrer-when-downgrade
//连接的方式 长连接
Connection
keep-alive
Content-Length
0
Date
Tue, 12 Jan 2021 07:21:38 GMT
Keep-Alive
//接收的数据格式 告诉服务器端浏览客户端能够接受的数据类型
timeout=20
//mime类型 大范围/小范围
Accept
//接收的压缩格式 浏览器通知服务器我可以接受哪些类型压缩格式的数据
text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Encoding
//浏览器可支持的语言
gzip, deflate
Accept-Language
zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Connection
//Cookie JSESSIONID
keep-alive
Cookie
Idea-e3d8082a=c757308f-8f40-492c-a0a8-28e4771f7ca7; JSESSIONID=14ED1A0E373E8F9FEF81ECF8493BF9AB
Host
//来源地--->浏览器通知服务器当前的请求是来自于哪个地方 Referer:经常用于防盗链
防止盗取我的连接信息 如果你是直接请求资源,没有referer
localhost
Referer
//告诉服务器,自己支持你这种操作,我能读懂服务器发送的信息,建议使用HTTPS而不是用HTTP
http://localhost/
Upgrade-Insecure-Requests
//用户使用的浏览器客户端的内核,还包括操作系统相关的信息
1
User-Agent
Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:84.0) Gecko/20100101 Firefox/84.0
post请求
POST
scheme
http
host
localhost
filename
/checkUser
地址
127.0.0.1:80
状态
200
版本HTTP/1.1
传输764 字节(大小 0 字节)
Referrer 政策no-referrer-when-downgrade
Connection
keep-alive
Content-Length
0
Date
Tue, 12 Jan 2021 07:49:13 GMT
Keep-Alive
timeout=20
Accept
text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Encoding
gzip, deflate
Accept-Language
zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Connection
//内容长度
keep-alive
Content-Length
//如果是post请求在请求体中的数据使用url编码
30
Content-Type
application/x-www-form-urlencoded
Cookie
Idea-e3d8082a=c757308f-8f40-492c-a0a8-28e4771f7ca7; JSESSIONID=14ED1A0E373E8F9FEF81ECF8493BF9AB
Host
localhost
Origin
http://localhost
Referer
http://localhost/
Upgrade-Insecure-Requests
1
User-Agent
Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:84.0) Gecko/20100101 Firefox/84.0
// 请求体内容
username=admin&password=123456
常用的状态码
200 请求成功
302 重定向
304 读取本地缓存文件
404 请求的web资源找不到
405 请求方式不对如:客户端使用的是get请求,服务器端接收采用post方法
500 服务器端程序代码错误
HTTP响应
// 响应行 http协议 状态码
HTTP/1.1 200
// 响应头
// 响应正文的内容长度 当前为0
Content-Length: 0
// 响应的时间
Date: Tue, 12 Jan 2021 07:49:14 GMT
Keep-Alive: timeout=20
Connection: keep-alive
Servlet体系结构
在实际开发中,我们创建一个Servlet类大多数使用的都是service()方法,由于必须遵从Servlet接口规范而不得不重写其他的抽象方法,
这些方法大多时候是闲置不用的,在Servlet体系结构有一个类HTTPServlet,封装了servlet接口中的抽象方法,我们以后可以定义一个类去继承该类即可
GenericServlet他将Servlet接口中的抽象方法基本实现了,有一个service方法没有实现,需要子类来实现,但是由于客户端发送请求时有请求方式的区别,
在service放啊中还要做具体的判断,不方便,在他的子类HttpServlet当中实现了service方法,做了区分不同请求方法的实现,对外提供七个请求的方法
由于目前阶段我们只使用get和post请求方式.所以我们重点关注doGet和doPost方法
? 查看源码发现doGat和doPost方法中的两个参数分贝是HttpServletRequest和HttpServletResponse,就是我们需要请求对象和响应对象
? request和repomse内部原理,参照客户端和服务器端发送数据的原理
原文:https://www.cnblogs.com/shangjinshuai/p/14269625.html