Servlet
在整个web应用中,Servlet主要负责处理请求、协调调度功能。即web应用中的控制器。
- 继承关系
HttpServlet -> GenericServlet -> Servlet
- 方法
void init(ServletConfig, var)//初始化方法
void service(ServletRequest req, ServletResponse res)//服务方法
void destory()//销毁方法
service
服务方法
service方法会自动响应收到的请求。
HttpServlet会获取请求的方式:get、post、head、delete等等,然后再决定调用的do开头的方法。(doPost等)
HttpServlet中do方法默认都是405实现风格,需要子类实现对应方法,否则报错405。
Servlet生命周期
生命周期 从出生到死亡的过程。
对应init()
,service()
,destroy()
默认情况下:第一次接收请求时,Servlet会进行实例化(调用构造方法)、初始化(调用init())、然后服务(调用service())。从第二次请求开始,每一次都是服务。当容器关闭时,其中的servlet实例会被销毁。
优点:提高系统响应速度
缺点:第一次请求耗时较长
如果需要提高响应速度,可以设置Servlet的初始化时机。通过<load-on-startup>
来设置servlet启动顺序,数字越小,启动越靠前,最小值0。
Tomcat负责维护Servlet的生命周期。
Servlet 特点
Servlet在容器中是:单例的、线程不安全的
- 单例:所有的请求都是同一个实例去响应
- 不安全:一个线程需要根据这个实例中的某个成员变量值做逻辑判断。但是在中间某个时机,另一个线程改变了这个成员变量的值,从而导致第一个线程的执行路径发生了变化
因此,尽量不要在servlet中定义成员变量。
如果定义了成员变量
- 不要修改成员变量值
- 不要根据成员变量值进行判断
Servlet获取TomCat请求
创建一个提交表单的简单功能
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form action = "add" method = "post">
名称:<input type = "text" name = "fruit"/><br/>
价格:<input type = "text" name = "price"/><br/>
库存:<input type = "text" name = "count"/><br/>
备注:<input type = "text" name = "remark"/><br/>
<input type = "submit" value = "添加">
</form>
</body>
</html>
创建Servlet类,获取浏览器请求
public class AddServlet extends HttpServlet {
/**
* 响应post请求
* @param req 请求,客户端像服务器端发送的信息被封装为Request
* @param resp 响应
* @throws ServletException
* @throws IOException
*/
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//post方式下需要设定编码,防止中文乱码
//get方式下不需要设置
req.setCharacterEncoding("UTF-8");
String fruit = req.getParameter("fruit");
String p = req.getParameter("price");
Integer price = Integer.parseInt(p);
String c = req.getParameter("count");
Integer count = Integer.parseInt(c);
String remark = req.getParameter("remark");
System.out.println(fruit + '\n' + price + '\n' + count + '\n' + remark);
}
}
配置xml文件,通过映射建立连接
<servlet>
<servlet-name>AddServlet</servlet-name>
<servlet-class>proj.AddServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>AddServlet</servlet-name>
<url-pattern>/add</url-pattern>
</servlet-mapping>
运行结果
Servlet生命周期演示
public class ServletLife extends HttpServlet {
@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("正在销毁...");
}
}
<servlet>
<servlet-name>ServletLife</servlet-name>
<servlet-class>proj.ServletLife</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>ServletLife</servlet-name>
<url-pattern>/life</url-pattern>
</servlet-mapping>
运行结果
对于第一个用户来说,如果需要提高响应速度,可以通过load-on-startup
设置Servlet初始化时机。数字越小,启动越靠前,最小值0。
<servlet>
<servlet-name>ServletLife</servlet-name>
<servlet-class>proj.ServletLife</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
此时,服务器启动时就进行实例化和初始化。