1.servlet是什么
servlet是一种javaEE规范,遵循servlet规范的web应用可以放到不同的web服务器中运行。servlet规范包括:
- 规范了接口
- 规范了类
- 规范了一个web应用中应该有哪些配置文件
- 规范了一个web应用中配置文件的名字
- 规范了一个web应用中配置文件存放的路径
- 规范了一个web应用中配置文件的内容
- 规范了一个合法有效的web应用它的目录结构应该是怎样的。
2.servlet对象的生命周期
servlet对象的生命周期是由tomcat服务器(WEB 容器)负责的,自己new的是不交给WEB容器管理的,Web容器底层应该有一个HashMap的集合,用来存储servlet对象和请求路径的对应关系;
默认情况下,启动tomcat容器,servlet对象是不会创建出来的,可以加上子标签来让tomcat容器启动时创建servlet对象。填写的整数越小,优先级越高
接受请求—>servlet对象创建—>servlet对象初始化(init()方法执行)—>service()方法处理请求—>destroy()方法执行—>servlet对象销毁
**servlet对象销毁并不是在destroy()方法中执行的,web容器提供destroy()让我们在销毁servlet之前可以做一些事情
3.servlet继承关系
jakarta.servlet.Servlet(接口)【爷爷】
jakarta.servlet.GenericServlet implements Servlet(抽象类)【儿子】
jakarta.servlet.http.HttpServlet extends GenericServlet(抽象类)【孙子】
我们以后编写的Servlet要继承HttpServlet类。HttpServlet 是Servlet规范专为Http协议准备的一个Servlet类,可以更加便捷的处理HTTP请求。
HttpServlet 部分源码:
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException{
// 报405错误
String msg = lStrings.getString("http.method_get_not_supported");
sendMethodNotAllowed(req, resp, msg);
}
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
// 报405错误
String msg = lStrings.getString("http.method_post_not_supported");
sendMethodNotAllowed(req, resp, msg);
}
例如这个405错误就是提供给我们的提示,表示请求方式错误。为了避免可以重写doGet和doPost两个方法,但是这样不建议,这样的话不如直接重写service方法
4.servlet开发步骤
- 编写一个Servlet类,直接继承HttpServlet
- 第二步:重写doGet方法或者重写doPost方法,到底重写谁,javaweb程序员说了算。
- 第三步:将Servlet类配置到web.xml文件当中。
- 第四步:准备前端的页面(form表单),form表单中指定请求路径即可。
5.HTTP协议结构
URI和URL区别:
URI:统一资源标识符,代表网络中某个资源的名字,无法通过URI定位到某个资源;
URL:统一资源定位符,代表网络中某个资源,可以通过URL定位到该资源,URL包括URI;
http://localhost:8080/servlet/index.html是一个URL,/servlet/index.html是URI
5.1HTTP请求结构
- 请求行:请求方式、URI、协议版本号
- 请求头:请求的主机、端口、浏览器、平台、cookie等信息
- 空白行:区分请求头和请求体
- 请求体:数据
GET请求:
GET /servletDemo/getServlet?username=lyaa&userpwd=123456 HTTP/1.1 请求行
Host: localhost:8080 请求头(含下面的)
Connection: keep-alive
sec-ch-ua: "Google Chrome";v="95", "Chromium";v="95", ";Not A Brand";v="99"
sec-ch-ua-mobile: ?0
sec-ch-ua-platform: "Windows"
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.54 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Sec-Fetch-Site: same-origin
Sec-Fetch-Mode: navigate
Sec-Fetch-User: ?1
Sec-Fetch-Dest: document
Referer: http://localhost:8080/servlet05/index.html
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9
空白行
请求体
Post请求:
POST /servletDemo/postServlet HTTP/1.1 请求行
Host: localhost:8080 请求头(含下面的)
Connection: keep-alive
Content-Length: 25
Cache-Control: max-age=0
sec-ch-ua: "Google Chrome";v="95", "Chromium";v="95", ";Not A Brand";v="99"
sec-ch-ua-mobile: ?0
sec-ch-ua-platform: "Windows"
Upgrade-Insecure-Requests: 1
Origin: http://localhost:8080
Content-Type: application/x-www-form-urlencoded
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.54 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Sec-Fetch-Site: same-origin
Sec-Fetch-Mode: navigate
Sec-Fetch-User: ?1
Sec-Fetch-Dest: document
Referer: http://localhost:8080/servlet05/index.html
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9
空白行
username=lyaaa&userpwd=123456 请求体
5.2HTTP响应结构
- 状态行:协议版本号、状态码、状态描述
- 响应头:相应的内容类型、长度、时间等信息
- 空白行:区分响应头和响应体
- 响应体:响应的数据
HTTP/1.1 200 ok 状态行
Content-Type: text/html;charset=UTF-8 响应头
Content-Length: 160
Date: Mon, 08 Nov 2021 13:19:32 GMT
Keep-Alive: timeout=20
Connection: keep-alive
空白行
<!doctype html> 响应体
<html>
<head>
<title>from get servlet</title>
</head>
<body>
<h1>from get servlet</h1>
</body>
</html>
5.3Get请求和Post请求的区别
Get请求发送的数据会显示到地址栏URI后面;
Get请求只能发送普通字符串,Post可以发送字符串、流媒体等信息;
Get一般用来获取数据,Post一般用来提交数据;
Get请求会被缓存(可以URI后面加时间戳等方法不走缓存),Post请求不会;
6.servlet共享数据
将数据放到ServletContext应用域中;
数据放到request请求域中,然后用请求转发的方式跳转servlet;
7.请求转发和重定向
请求转发是一次请求:
request.getRequestDispatcher("/servletB").forward(request,response);
重定向是两次请求,路径需要加上项目名:
response.sendRedirect("/servletDemo/servletB");
需要携带request域中的数据到下个servlet则使用请求转发,其他使用重定向
8.Session和Cookie
session是一种机制,用来保存会话状态(HTTP是无状态协议),session是保存状态在服务器上,cookie是保存在浏览器客户端上
HttpSession session = request.getSession();
session.setAttribute("userName",rs.getString("user_name"));
Cookie cookie = new Cookie("userName",rs.getString("user_name"));
Cookie cookie2 = new Cookie("passWord",rs.getString("pass_word"));
cookie.setPath("");
cookie2.setPath("");
/*设置路径,访问哪个路径时携带cookie,默认是此次请求的上级路径的子路径,例如:此次访问的是
http://localhost:8080/servletDemo/cookie,不设置路径的话则之后访问http://localhost:8080/servletDemo
下的所有路径都会携带上面的cookie
*/
cookie.setMaxAge(60 * 60);
cookie2.setMaxAge(60 * 60);
//设置cookie有效时间,如果时间>0,则这个cookie会保存到硬盘文件中,如果<0则和不设置一样,保存到浏览器内存中,如果=0则是删除cookie
response.addCookie(cookie);
response.addCookie(cookie2);
获取cookie:
Cookie[] cookies = request.getCookies(); // 可能返回null
if(cookies != null){
for(Cookie cookie : cookies){
// 获取cookie的name
String name = cookie.getName();
// 获取cookie的value
String value = cookie.getValue();
}
}
9.JSP
9.1jsp的本质
jsp(JavaServer Pages)本质上就是一个servlet,servlet用来获取、处理、返回数据,jsp用来展示数据;
index.jsp会被翻译成index_jsp.java文件,然后被编译为index_jsp.class文件,jsp是继承 HttpJspBase类的,HttpJspBase是继承HttpServlet的,所有jsp就是一个servlet
jsp对应的servlet代码位置:
<%!%>符号中的内容会被翻译到该jsp(servlet)中service方法之外的java语句
<%!
private int i = 0;
%>
<%%>符号中的内容会被翻译到该jsp(servlet)中service方法之内的java语句
<%
System.out.println("test");
%>
直接在jsp中写的字符会被翻译到该jsp(servlet)中service方法里面的out.write()方法内 字节流输出
test
<%=%>符号中的内容会被翻译到该jsp(servlet)中service方法里面的out.print()方法内 字符流输出
<%=request.getContextPath()%>
9.2jsp的九大内置对象
-
PageContext pageContext 页面作用域
-
HttpServletRequest request 请求作用域
-
HttpSession session 会话作用域
-
ServletContext application 应用作用域
- pageContext < request < session < application
- 以上四个作用域都有:setAttribute、getAttribute、removeAttribute方法。
- 以上作用域的使用原则:尽可能使用小的域。
-
java.lang.Throwable exception
-
jakarta.servlet.ServletConfig config
-
java.lang.Object page (其实是this,当前的servlet对象)
-
jakarta.servlet.jsp.JspWriter out (负责输出)
-
jakarta.servlet.http.HttpServletResponse response (负责响应)
10.Filter过滤器
过滤器创建方法:
1.创建过滤器类,实现Filter接口
public class TestFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("filter初始化");
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println("filter执行=======================");
//放行
filterChain.doFilter(servletRequest,servletResponse);
System.out.println("dada");
}
@Override
public void destroy() {
System.out.println("filter销毁");
}
}
2.Web.xml配置该过滤器(还可以使用@WebFilter注解来配置过滤器)
<filter>
<filter-name>TestFilter</filter-name>
<filter-class>com.filter.TestFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>TestFilter</filter-name>
<url-pattern>*</url-pattern>
</filter-mapping>
过滤器对象是在容器启动时就创建的,这一点与servlet不同
11.监听器
监听器创建方法:
1.编写一个监听器类实现监听器接口(以HttpSessionAttributeListener监听器为例)
public class Listener implements HttpSessionAttributeListener {
@Override
public void attributeAdded(HttpSessionBindingEvent event) {
//向session域中存数据时
}
@Override
public void attributeRemoved(HttpSessionBindingEvent event) {
//session域中删除数据时
}
@Override
public void attributeReplaced(HttpSessionBindingEvent event) {
//session域中数据替换时
}
}
2.配置文件配置监听器(也可以使用@WebListener注解)
<listener>
<listener-class>com.listener.Listener</listener-class>
</listener>