servlet接口:
public interface Servlet {
public void init(ServletConfig config) throws ServletException;
public ServletConfig getServletConfig();
public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException;
public String getServletInfo();
public void destroy();
}
1. 什么是Servlet?
Servlet就是一个java接口,处理请求和发送响应的过程是由一种叫做Servlet的程序来完成的,并且Servlet是为了实现动态页面而衍生的东西。
①处表示Web服务器接收到客户端发出的HTTP请求后,转发给Servlet容器,同时把控制返回Servlet容器;
②处表示Servlet容器把响应对象ServletResponse中的处理结果转发给Web服务器,通知Web服务器以HTTP响应的方式把结果发送到客户端,同时把控制返回Web服务器
Tomcat是Web应用服务器,是一个servlet/Jsp容器,Tomcat 作为Servlet容器,它监听了端口负责处理客户请求,把请求传送给Servlet,并将Servlet的响应传送回给客户。
Java Servlet API是Servlet容器和Servlet之间的接口,它定义了Servlet的各种方法,还定义了Servlet容器传送给Servlet的对象类,其中最重要的是请求对象ServletRequest和响应对象ServletResponse这两个对象都是由Servlet容器在客户端调用Servlet时产生的,Servlet容器把客户请求信息封装在ServletRequest对象中,然后把这两个对象都传送给要调
用的Servlet,Servlet处理完后把响应结果写入ServletResponse,然后由Servlet容器把响应结果发送到客户端。
3. 创建Servlet的原理
中添加一条配置信息5 (默认为0)
,当值大于0时,容器在应用启动时就会初始化一个servlet对象,当是一个负数时或者没有指定时,则指示容器在该servlet被请求时才加载,也就是会执行初始化方法init(ServletConfig conf)。 HttpServlet与Servlet
查看源码,httpServlet继承了GenericServlet
public abstract class HttpServlet extends GenericServlet
GenericServlet的继承结构,实现了Servlet接口和ServletConfig接口
public abstract class GenericServlet implements Servlet, ServletConfig,
java.io.Serializable {
private static final long serialVersionUID = 1L;
private transient ServletConfig config;
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 {
this.config = config;
this.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();
}
ServletConfig接口的代码
public interface ServletConfig {
public String getServletName();
public ServletContext getServletContext();
public String getInitParameter(String name);
public Enumeration getInitParameterNames();
}
由Servlet接口方法可以看到,Servlet三个关键方法init()、service()、destroy(),其他两个方法:
一个是getServletConfig(),是获取ServletConfig对象,ServletConfig对象可以获取到Servlet的一些信息,包含ServletName、ServletContext、InitParameter、InitParameterNames等(WEB-INF目录下的web.xml中的servlet标签里面的信息)。
其中ServletContext对象是servlet上下文对象,代表当前Web应用,并且它被所有客户端共享
另一个是getServletInfo(),是返回一个String类型的字符串,其中包括了关于Servlet的信息,例如作者、版本和版权。
GenericServlet实现了Servlet接口后,我们可以直接继承GenericServlet,就可以使用上面我们所介绍Servlet接口中的那几个方法了,能拿到ServletConfig,继而获取ServletContext,为了方便GenericServlet除了实现Servlet接口外,还实现了ServletConfig接口,就可以直接获取ServletContext了。
GenericServlet 中有两个init()方法原因:见Servlet详解之两个init方法的作用
Service方法的执行
public abstract class GenericServlet implements Servlet, ServletConfig,
java.io.Serializable {
@Override
public abstract void service(ServletRequest req, ServletResponse res)
throws ServletException, IOException;
}
查看GenericServlet的service()方法,它是一个抽象方法,实际上HttpServlet类继承了GenericServlet,它主要是实现service()方法的细节。
查看HttpServlet的代码
public abstract class HttpServlet extends GenericServlet {
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;
try {
ifModifiedSince = req.getDateHeader(HEADER_IFMODSINCE);
} catch (IllegalArgumentException iae) {
// Invalid date header - proceed as if none was set
ifModifiedSince = -1;
}
if (ifModifiedSince < (lastModified / 1000 * 1000)) {
// 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);
}
}
@Override
public void service(ServletRequest req, ServletResponse res)
throws ServletException, IOException {
HttpServletRequest request;
HttpServletResponse response;
try {
request = (HttpServletRequest) req;
response = (HttpServletResponse) res;
} catch (ClassCastException e) {
throw new ServletException("non-HTTP request or response");
}
service(request, response);
}
}
查看HttpServletRequest的代码
public interface HttpServletRequest extends ServletRequest
因此可以看到下边的service(ServletRequest req, ServletResponse res)
方法主要是将ServletRequest
和ServletResponse
强制转换为了HttpServletRequest和HttpServletResponse,再调用service(HttpServletRequest req, HttpServletResponse resp)
方法,这个方法就是判断浏览器过来的请求方式是get还是post然后分别执行doGet()或doPost()方法,我们写的Servlet集成HttpServlet后,就只要重写doGet()和doPost()方法,而不用直接重写service()方法了,简便了开发。