Servlet
概念:运行在服务器端的小程序
快速入门:
- 创建JavaEE项目
- 定义一个类,实现(implements)Servlet接口
- 实现接口中的抽象方法(五个)
- 配置Servlet(web.xml)
Servlet的生命周期方法:
被创建:执行init()方法,只执行一次
- Servlet什么时候创建?
- 默认情况下,第一次访问时,Servlet被创建
- 可以配置创建Servlet的创建时机
- 在
<Servlet>
标签下配置- 第一次被访问时,创建(默认)
<load-on-startup>
的值为负整数(默认值为-1)
- 在服务器启动时,创键
<laod-on-startup>
的值为0或者正整数- 如果有多个Servlet都配置了自动启动,数字越小,启动的优先级越高
- 第一次被访问时,创建(默认)
- 在
- Servlet的init方法,只执行一次,Servlet是单例
- 线程安全问题(有很多人访问)
- Servlet什么时候创建?
提供服务: 执行service()方法,执行多次
- 每次访问Servlet时,service方法都会被调用一次
被销毁:执行destroy()方法,只执行一次
- Servlet被销毁时执行。服务器关闭时,Servlet被销毁
- 只有服务器正常关闭时,才会执行destroy()方法。
- destroy()方法在Servlet被销毁之前执行,一般用于释放资源
Servlet3.0 注解配置
- 好处:
- 支持注解配置,不需要web.xml。
- 使用:
- 在业务类的上面加上一行注解即可,以下是三种使用方法:
@WebServlet(urlPatterns = "/demo")
@WebServlet(value = "/demo")
(value表示最重要的东西,最重要的就是urlPatterns)@WebServlet("/demo")
(只有value一个值的时候可以省略不写,注意不要忘了/
)
- 在业务类的上面加上一行注解即可,以下是三种使用方法:
idea与Tomcat相关配置
- IDEA会为每一个Tomcat部署的项目单独生成一份配置文件
- 可以查看控制台log中的
CATALINA_BASE
来查看路径
- 可以查看控制台log中的
- IDEA项目的发布路径
Servlet的体系结构
Servlet – 接口
↓
GenericServlet – 抽象类
↓
HttpServlet – 抽象类
- Servlet:
实现
(implements)Servlet接口,它的五个方法必需全部实现,不然报错! - GenericServlet:实现了Servlet接口,将Servlet接口中的其他方法做了默认空实现,只将service()方法作为抽象(必需实现的)
继承
(extends)GenericServlet,可以只重写service()方法,其他的可以根据需要重写
- HttpServlet:对Http协议的一种封装,简化操作(常用)
- 一般进行业务操作都要对请求的方法进行判断(GET/POST)
继承
HttpServlet可以直接使用doGet()/doPost()
方法,不用进行判断
Servlet注解路径详解
urlpartten:Servlet访问路径(注解方式)
- 一个Servlet可以定义多个访问路径
@WebServlet({"/d4","/dd4","/ddd4"})
- 路径定义规则:
/xxx
/xxx/xxx
/abc/*
:abc下的所有路径都可以访问/*
:所有路径都可以访问,如果输入目录与其他路径相同,先访问其他目录,即该方式的优先级最低
*.do
- 注意不要带
/
- 注意不要带
URL
- URL(Uniform Resource Locator) 统一资源定位符.
- 它是可以唯一标识一个资源的位置。(就是浏览器里的网址)
- 写法:
协议
+主机
+端口
+URI
- Like this:
https://sky03.xyz:443/blogs/2019/55715.html
- URI(Uniform Resource Identifier) 统一资源标识符.
- 它是在应用中可以唯一定位一个资源的。
HTTP
概念:Hyper Text Transfer Protocol 超文本传输协议
- 传输协议:发送数据的格式
- 特点:
- 基于TCP/IP的高级协议
- 默认端口:80
- 基于请求/响应的模型:一次请求对应一次响应
- 无状态的:每次请求之间相互独立,不能相互的交互数据
- 历史版本:
- 1.0:每一次请求响应都会建立新的连接,然后断开,然后重连,传输,再断开。。。
- 断开和重连都会消耗时间,所以此版本体验极差
- 1.1:复用连接,会等一会,如果还有信息传输,就继续用这个连接,从而节省时间
- 1.0:每一次请求响应都会建立新的连接,然后断开,然后重连,传输,再断开。。。
请求消息数据格式
请求行
请求方式 请求url 请求协议/版本GET /login.html HTTP/1.1
- 请求方式:
- HTTP协议有7中请求方式,常用的有2种
- GET:
- 请求参数在请求行中,在url后。
- 请求的url长度有限制的
- 不太安全(能看到表单密码)
- POST:
- 请求参数在请求体中
- 请求的url长度没有限制的
- 相对安全(看不到表单密码)
- 请求方式:
请求头:客户端浏览器告诉服务器一些信息
请求头名称: 请求头值Host: localhost:8080 Connection: keep-alive Upgrade-Insecure-Requests: 1 User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8 Accept-Encoding: gzip, deflate, br Accept-Language: zh-CN,zh;q=0.9 Cookie: JSESSIONID=CC05E35CD1E8E96DBC1FDCAD55987ED2
- 常见的请求头:
User-Agent
:浏览器告诉服务器,我访问你使用的浏览器版本信息- 可以在服务器端获取该头的信息,解决浏览器的兼容性问题
Referer
:http://localhost/login.html- 告诉服务器,我(当前请求)从哪里来?
- 作用:
- 防盗链
- 统计工作
- 作用:
- 告诉服务器,我(当前请求)从哪里来?
- 常见的请求头:
请求空行
空行(空的一行),就是用于分割POST请求的请求头,和请求体的。
请求体(正文):
username=zhangsan
- 封装POST请求消息的请求参数的
整个请求消息的字符串格式为:
GET /ServletDemo/?name=zhangsan HTTP/1.1 Host: localhost:8080 Connection: keep-alive Upgrade-Insecure-Requests: 1 User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8 Accept-Encoding: gzip, deflate, br Accept-Language: zh-CN,zh;q=0.9 Cookie: JSESSIONID=CC05E35CD1E8E96DBC1FDCAD55987ED2 username=zhangsan
- 响应消息数据格式
Request
1. 功能:
1. 获取请求消息数据
2. 获取请求行数据
- 获取请求方式 :GET
- String getMethod()
- (重点)获取虚拟目录:/servlet
- String getContextPath()
- 获取Servlet路径(urlpartten): /demo1
- String getServletPath()
- 获取get方式请求参数:?name=zhangsan
- String getQueryString()
- (重点)获取请求URI:/day14/demo1
- String getRequestURI(): /day14/demo1
- StringBuffer getRequestURL() : http://localhost/day14/demo1
- URL:统一资源定位符
- URI:统一资源标识符
- 获取协议及版本:HTTP/1.1
- String getProtocol()
- 获取客户机的IP地址:
- String getRemoteAddr()
3. 获取请求头数据
- 方法:
- (重点)String getHeader(String name):通过请求头的名称获取请求头的值
- Enumeration
<String>
getHeaderNames():获取所有的请求头名称
4. 获取请求体数据:
请求体:只有POST请求方式,才有请求体,在请求体中封装了POST请求的请求参数
方法:
获取流对象
- BufferedReader getReader():获取字符输入流,只能操作字符数据
- ServletInputStream getInputStream():获取字节输入流,可以操作所有类型数据
再从流对象中拿数据
5. 其他功能:
获取请求参数通用方式:
不论get还是post
请求方式都可以使用下列方法来获取请求参数所以将来可以只在
doPost/doGet
方法里写一份代码,在另一个方法里这么写:this.doPost(request,response); //或者 this.doGet(request,response);
String getParameter(String name):根据参数名称获取参数值 username=zs&password=123
String[] getParameterValues(String name):根据参数名称获取参数值的数组 hobby=xx&hobby=game
Enumeration <String> getParameterNames():获取所有请求的参数名称的枚举
Map <String,String[]> getParameterMap():获取所有参数的map集合
- 中文乱码问题:
- get方式:tomcat 8 已经将get方式乱码问题解决了
- post方式:会乱码
- 解决:在获取参数前,设置request的编码
request.setCharacterEncoding("utf-8");
2. 请求转发:一种在服务器内部的资源跳转方式
1. 步骤:
通过request对象获取请求转发器对象:RequestDispatcher getRequestDispatcher(String path)
使用RequestDispatcher对象来进行转发:forward(ServletRequest request, ServletResponse response)
一般的写法
RequestDispatcher requestDispatcher = req.getRequestDispatcher(); requestDispatcher.forward(req,resp);
可以使用链式编程
req.getRequestDispatcher("/requestDemo4").forward(req,resp);
2. 特点:
- 浏览器地址栏路径不发生变化
- 只能转发到当前服务器内部资源中。(这个跳转不能直接转到别的服务器网址)
- 转发是一次请求(只有一次请求)
3. 共享数据:
- 域对象:一个有作用范围的对象,可以在范围内共享数据
- request域:代表
一次请求
的范围,一般用于请求转发的多个资源
中共享数据 - 方法:
- void setAttribute(String name,Object obj):存储数据
- Object getAttitude(String name):通过键获取值
- void removeAttribute(String name):通过键移除键值对
4. 获取ServletContext:
- ServletContext getServletContext()