持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第23天,点击查看活动详情
生命周期
Servlet的生命周期对应了三个方法:init()、service()、destroy()
当第一次接收请求时,servlet会进行实例化(调用构造方法)、初始化(调用init())、然后服务(调用service ()),最后当容器关闭时,其中的所有的servlet实例会被销毁,调用销毁方法(destroy()),当初始化过后每一次请求都会调用对应的service()方法
package com.sentiment.servlet;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class Demo01 extends HttpServlet {
public Demo01() {
System.out.println("正在实例化.....");
}
@Override
public void init() throws ServletException {
System.out.println("正在初始化.....");
}
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("正在启动服务.....");
}
@Override
public void destroy() {
System.out.println("正在销毁.....");
}
}
当服务启动后 第一次发出请求时便会执行对应的构造器、init()、service()方法
而当服务关闭时则会执行destory()
初始化时机
默认情况下,实例化和初始化只会执行一次,这样做可以提高系统的启动速度,但如果我们需要提高响应速度则需设置一个参数
<load-on-startup>通过它可以设置servlet的启动顺序,数字越小启动越靠前,最小值为0
设置了该参数后,在启动环境时会默认进行实例化和初始化,避免了第一次请求后的实例化和初始化操作
线程安全问题
Servlet的线程安全问题 | Y4tacker's Blog
为了避免线程安全问题可采取:
①不要去修改成员变量的值
②不要去根据成员变量的值做一些逻辑判断
会话
HTTP无状态
看会话前先了解一下HTTP无状态
HTTP无状态:服务器无法判断这两次请求是同一个客户端发过来的,还是不同的客户端发过来的
会话跟踪技术
HTTP无状态会遇到一个问题︰第一次请求是添加商品到购物车,第二次请求是结账;如果这两次请求服务器无法区分是同一用户请求的
这时就要通过会话跟踪技术也就是seesion来解决
public class Demo02 extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//服务器获取Session,如果没有则创建一个
HttpSession session = req.getSession();
System.out.println(session.getId());
}
}
常用API
- request.getsession () ->获取当前的会话,没有则创建一个新的会话
- request.getsession (true) ->效果和不带参数相同
- request.getsession (false)->获取当前会话,没有则返回null,不会创建新的
- session.getId () ->获取sessionID
- session.isNew ( ) ->判断当前session是否是新的
- session.getMaxInactiveInterval () -> session的非激活间隔时长,默认1800秒session.setMaxInactiveInterval ()
- session.invalidate () ->强制性让会话立即失效
- getSession().setAttribute() -> 设置session
- getSession().getAttribute() -> 获取seesion值
服务器端转发和客户端重定向
服务器内部转发
一次请求响应的过程,对于有客户端而言,内部经过了多少次转发,客户端是不知道的
地址栏没有变化
req.getRequestDispatcher("test6").forward(req,resp);
客户端重定向
两次请求响应的过程。客户端肯定知道请求URL有变化
地址栏有变化
resp.sendRedirect("test6");
Demo05
public class Demo05 extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("demo05......");
//req.getRequestDispatcher("test6").forward(req,resp);
resp.sendRedirect("test6");
}
}
Demo06
public class Demo06 extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("demo06......");
}
}
当启动服务访问test5后,若使用的是服务端转发,则url不变,但是会跳转到demo06输出demo06......
当使用客户端重定向后,url会随之从test5变为test6并输出demo06.........