目录
一、JavaWeb
二、servlet本质:
三、Servlet对象生命周期
四、Servlet类的方法介绍
五、适配器思想
对于一个web应用来说,涉及到的角色和规范协议:
可以将servlet理解为web服务器和web app之间的一个接口,通过servlet规定的一系列规范,服务器根据接受到的请求可以找到正确的服务。对于web app来说,每一个服务需要有一个Servlet接口的实现类xxxServlet,配置文件中标明了请求路径和实现类xxxServlet的对应关系(专业术语叫做:配置文件完成实现类xxxServlet的注册)。对于web服务器来说,以tomcat为例。服务器接收到浏览器发送的请求,此时tomcat需要找到与请求路径对应的xxxServlet,对应关系存储在配置文件中,因此先解析配置文件,获取到对应的xxxServlet,然后通过反射创建对象,调用service方法。
main函数在tomcat服务器中,程序是写死的,这就表明我们的web app的存放位置、命名等需要遵循一定的规范,只有这样tomcat才能够顺利的访问到webapp。
webapps下为项目文件夹,项目文件夹下创建文件夹WEB-INF
注意:在编译java程序时,由于import了servlet的包,但是JavaSE中并不存在这个包。在tomcat中实现了Servlet,因此需要配置CLASSPATH,值为Servlet jar包的文件位置。
Servlet对象在tomcat服务器启动时并不会默认创建,只有在用户发送请求后才会创建对应的xxxServlet对象。用户发送请求后,首先调用无参构造器生成对象,然后调用init方法和service方法。当用户后续重复发送请求时,只会调用service方法,不会再实例化对象。
tomcat服务器销毁Servlet对象时,会调用destroy方法,调用完成之后便销毁。
xxxServlet作为Servlet接口的实现类,需要重写Servlet接口的方法:
init方法为初始化方法,在Servlet对象创建后只执行1次,方法体中多为连接资源等操作。
init方法入参为ServletConfig类的一个对象,servletconfig去获取xml配置文件中servlet标签中的内容。也就是说,tomcat解析web.xml文件,将
标签中的配置信息自动包装到servletconfig中。
service方法是处理用户请求的核心方法。
destroy作为对象销毁前调用的方法,通常需要负责保存数据、释放资源等操作。
在实际使用中,通常并不直接实现Servlet接口。servlet接口提供了5个方法,其中最常用的其实只有service方法,但所有xxxServlet类要实现接口的所有方法,这就导致代码冗余,不够美观。为了解决这个问题,Servlet中提供了Servlet接口的实现类,在实际使用中,通常会继承这个实现类,来重写service方法,这就是适配器的思想。
GenericServlet实现类源码:
package javax.servlet;
import java.io.IOException;
import java.util.Enumeration;
public abstract class GenericServlet implements Servlet, ServletConfig,
java.io.Serializable {
//版本号
private static final long serialVersionUID = 1L;
private transient ServletConfig config;
/*
此构造方法啥也不做,因为Servlet的所有初始化任务都是由init方法完成的。
*/
public GenericServlet() {
// NOOP
}
@Override
public void destroy() {
// NOOP by default
}
@Override
public String getInitParameter(String name) {
return getServletConfig().getInitParameter(name);
}
@Override
public Enumeration getInitParameterNames() {
return getServletConfig().getInitParameterNames();
}
@Override
public ServletConfig getServletConfig() {
/*通过该方法,可以让子类调用父类私有属性*/
return config;
}
@Override
public ServletContext getServletContext() {
return getServletConfig().getServletContext();
}
@Override
public String getServletInfo() {
return "";
}
@Override
public void init(ServletConfig config) throws ServletException {
/*该方法是形参,tomcat将实参传进来,然后通过this.config=config
把局部变量变为全局变量。*/
this.config = config;
//Tomcat首先调用init()有参方法,然后调用init()无参方法。
this.init();
}
/*目的是让子类重写init()方法的无参构造方法。*/
public void init() throws ServletException {
// NOOP by default
}
public void log(String msg) {
getServletContext().log(getServletName() + ": " + msg);
}
public void log(String message, Throwable t) {
getServletContext().log(getServletName() + ": " + message, t);
}
@Override
public abstract void service(ServletRequest req, ServletResponse res)
throws ServletException, IOException;
@Override
public String getServletName() {
return config.getServletName();
}
}
注意到,类中有一个public ServletContext getServletContext()方法,ServletContext对应的是一个web.xml文件。它获取到的是应用级配置信息,即由所有xxxServlet类共享的信息。ServletContext对象在服务器启动阶段创建,在服务器关闭的时候销毁。
以后我们编写Servlet类的时候,实际上是不会去直接继承GenericServlet类的,因为我们是B/S结构的系统,这种系统是基于HTTP超文本传输协议的,在Servlet规范当中,提供了一个类叫做HttpServlet,它继承了GenericServlet抽象类,是专门为HTTP协议准备的一个Servlet类。我们编写的Servlet类要继承HttpServlet。(HttpServlet是HTTP协议专用的。)使用HttpServlet处理HTTP协议更便捷。
要在继承TttpServlet类的子类中重写后端支持的请求方法。如接口支持post方法,那么需要重写doPost方法,若前端发送请求为get方法,则会走到父类(TttpServlet)中,最终结果会报405错误码(method not allowed)。
1、servlet类继承TttpServlet
2、重写doGet方法或 doPost 方法
3、将servlet类配置在web.xml配置文件中
4、编写前端页面(form表单),form表单中指定请求路径即可