1.什么是servlet
servlet
是运行在web服务器上的程序,它能接收和处理用户的请求,向用户返回数据。
2.Servlet接口
Servlet
是一个接口,它定义了如下几种方法。
public interface Servlet{
//servlet的初始化方法,在servlet整个生命周期中只执行一次,如果顺利执行,则将serlvet实例放入servlet容器中;
//否则抛出异常,servlet实例创建失败。
//同时传入一个servletConfig配置对象, 能够获取当前servlet的配置信息。
public void init(ServletConfig config);
//获取当前servlet所对应的servletConfig对象,这个config对象是由Tomcat创建的。
public ServletCongig getServletConfig();
//处理用户请求的核心方法。
public void service(ServletRequest req, ServletResponse res);
//获取当前servlet的基本信息
public String getServletInfo();
//销毁方法,在项目在服务器上关闭时执行。
public void destroy();
}
3.Servlet的生命周期所执行的方法
1. 初始化方法,默认为空实现。
2. init()方法,
3. service()方法
4. destory()方法
方法1,2顺利执行后,servlet
对象才能被顺利创建。方法3在servlet
对象被创建后才能调用。方法4在工程关闭时被调用,销毁servlet
对象。
4.Servlet接口的继承关系
总体来说,GenericServlet
抽象类实现了Servlet
接口,HttpServlet
抽象类继承了GenericServlet
。
4.1 GenericServlet
GenericServlet
类不仅实现了Servlet
接口,还实现了ServletConfig
接口,在属性中声明了ServletConfig
对象:
private transient ServletConfig config;//每个servlet对象对对应一个config
主要方法如下:
① init方法
public void init(ServletConfig config) throws ServletException {
this.config = config;//接受服务器传给的config对象,给config属性赋值。
this.init();//init()无参初始化函数,它是一个空实现。
}
② service抽象方法
public abstract void service(ServletRequest req, ServletResponse res)
throws ServletException, IOException;//抽象方法等待继承它的子类去实现
③ getServletContext方法
public ServletContext getServletContext() {
ServletConfig sc = getServletConfig();
return sc.getServletContext();
}
该方法通过服务器传入的ServletConfig
对象调用getServletContext()
方法获取ServletContext
上下文对象。
④ getServletName方法
public String getServletName() {
ServletConfig sc = getServletConfig();
return sc.getServletName();//默认返回当前servlet的类名
}
4.2 HttpServlet
HttpServlet
是GenericServlet
的子类。
主要方法如下:
① service()方法
protected void service(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException
{
String method = req.getMethod();
if (method.equals(METHOD_GET)) {
long lastModified = getLastModified(req);
if (lastModified == -1) {
// servlet doesn't support if-modified-since, no reason
// to go through further expensive logic
doGet(req, resp);
} else {
long ifModifiedSince = req.getDateHeader(HEADER_IFMODSINCE);
if (ifModifiedSince < lastModified) {
// If the servlet mod time is later, call doGet()
// Round down to the nearest second for a proper compare
// A ifModifiedSince of -1 will always be less
maybeSetLastModified(resp, lastModified);
doGet(req, resp);
} else {
resp.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
}
}
} else if (method.equals(METHOD_HEAD)) {
long lastModified = getLastModified(req);
maybeSetLastModified(resp, lastModified);
doHead(req, resp);
} else if (method.equals(METHOD_POST)) {
doPost(req, resp);
} else if (method.equals(METHOD_PUT)) {
doPut(req, resp);
} else if (method.equals(METHOD_DELETE)) {
doDelete(req, resp);
} else if (method.equals(METHOD_OPTIONS)) {
doOptions(req,resp);
} else if (method.equals(METHOD_TRACE)) {
doTrace(req,resp);
} else {
//
// Note that this means NO servlet supports whatever
// method was requested, anywhere on this server.
//
String errMsg = lStrings.getString("http.method_not_implemented");
Object[] errArgs = new Object[1];
errArgs[0] = method;
errMsg = MessageFormat.format(errMsg, errArgs);
resp.sendError(HttpServletResponse.SC_NOT_IMPLEMENTED, errMsg);
}
}
该方法将客户端请求分发给不同的请求类型对应的方法去处理。主要关注doGet()
方法和doPost()
方法。
② doGet()方法
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException
{
String protocol = req.getProtocol();
String msg = lStrings.getString("http.method_get_not_supported");
if (protocol.endsWith("1.1")) {
resp.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED, msg);
} else {
resp.sendError(HttpServletResponse.SC_BAD_REQUEST, msg);
}
}
当请求类型是Get时,调用该方法,在HttpServlet中该方法并没有具体的实现,只是负责处理错误和异常,需要继承它的子类去重写该方法。
③ doPost()方法
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException
{
String protocol = req.getProtocol();
String msg = lStrings.getString("http.method_post_not_supported");
if (protocol.endsWith("1.1")) {
resp.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED, msg);
} else {
resp.sendError(HttpServletResponse.SC_BAD_REQUEST, msg);
}
}
当请求类型是Post时,调用该方法,在HttpServlet中该方法并没有具体的实现,只是负责处理错误和异常,需要继承它的子类去重写该方法。
5.ServletContext接口
ServletContext
上下文对象提供了一系列方法用于不同servlet
对象之间的交流,整个工程中只存在唯一一个ServletContext
实例。它提供了丰富的方法来操作web工程和servlet对象。
ServletContext的四个作用。
1.读取web.xml中声明的context上下文参数 context-param
2. 获取当前的工程路径
3. 获取当前工程在物理磁盘上的绝对路径
4. 像Map一样存储数据
public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
ServletContext servletContext = getServletContext();
System.out.println(servletContext);
System.out.println(servletContext.getContextPath());//获取当前工程名
System.out.println(servletContext.getResourcePaths("/"));//获取当前工程下面的资源目录
System.out.println(servletContext.getRealPath("/"));//获取当前工程的物理磁盘路径
servletContext.setAttribute("name","Xx");//参数name的值为xx, 以map的形式存入servletcontext中。
}
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletContext servletContext = getServletContext();
System.out.println(servletContext);
System.out.println(servletContext.getAttribute("name"));//在另外一个servlet中可以取到name参数对应的值
}
6.编写自己的Servlet
@WebServlet(name = "helloServlet", value = "/hello-servlet")
public class HelloServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String name = request.getParameter("user");
String pass = request.getParameter("password");
System.out.println(name + " " + pass);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req,resp);
}
创建servlet需要使用@webServlet
注解标注servlet名称和要处理的请求,也可以在web.xml
中配置servlet和servlet-mapping。
直接继承HttpServlet并重写doGet()
和doPost()
方法既可。