1.Servlet接口
1.1先看下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.2再看下ServletConfig 接口的方法
public interface ServletConfig {
public String getServletName();
public ServletContext getServletContext();
public String getInitParameter(String name);
public Enumeration<String> getInitParameterNames();
}
2. Servlet 的典型实现类
接下来看看Servlet的子类以及其实现代码
- public abstract class HttpServlet extends GenericServlet
- public abstract class GenericServlet implements Servlet, ServletConfig, java.io.Serializable
2.1先看看GenericServlet 类
public abstract class GenericServlet implements Servlet, ServletConfig,
java.io.Serializable {
private static final long serialVersionUID = 1L;
private transient ServletConfig config;
public GenericServlet() {
// NOOP
}
来自于Servlet接口的方法开始/
@Override
public void init(ServletConfig config) throws ServletException {
this.config = config;
// 在此调用子类重写的方法,如果重写了的话
this.init();
}
// 此方法用于被子类重写
public void init() throws ServletException {
// NOOP by default
}
@Override
public ServletConfig getServletConfig() {
return config;
}
@Override
public abstract void service(ServletRequest req, ServletResponse res)
throws ServletException, IOException;
@Override
public String getServletInfo() {
return "";
}
@Override
public void destroy() {
// NOOP by default
}
来自于Servlet接口的方法结束/
来自于ServletConfig 接口的方法开始/
@Override
public String getServletName() {
return config.getServletName();
}
@Override
public ServletContext getServletContext() {
return getServletConfig().getServletContext();
}
@Override
public String getInitParameter(String name) {
return getServletConfig().getInitParameter(name);
}
@Override
public Enumeration<String> getInitParameterNames() {
return getServletConfig().getInitParameterNames();
}
来自于ServletConfig 接口的方法结束/
下面为此类中自定义的两个方法/
public void log(String msg) {
getServletContext().log(getServletName() + ": " + msg);
}
public void log(String message, Throwable t) {
getServletContext().log(getServletName() + ": " + message, t);
}
}
2.2再来看看HttpServlet类的实现代码(代码太多了,只提取关键的代码)
public abstract class HttpServlet extends GenericServlet {
private static final long serialVersionUID = 1L;
private static final String METHOD_DELETE = "DELETE";
private static final String METHOD_HEAD = "HEAD";
private static final String METHOD_GET = "GET";
private static final String METHOD_OPTIONS = "OPTIONS";
private static final String METHOD_POST = "POST";
private static final String METHOD_PUT = "PUT";
private static final String METHOD_TRACE = "TRACE";
private static final String HEADER_IFMODSINCE = "If-Modified-Since";
private static final String HEADER_LASTMOD = "Last-Modified";
private static final String LSTRING_FILE =
"javax.servlet.http.LocalStrings";
private static final ResourceBundle lStrings =
ResourceBundle.getBundle(LSTRING_FILE);
/**
* Does nothing, because this is an abstract class.
*/
public HttpServlet() {
// NOOP
}
// 从父类集成过来的service方法
@Override
public void service(ServletRequest req, ServletResponse res)
throws ServletException, IOException {
HttpServletRequest request;
HttpServletResponse response;
// 将传入的 ServletRequest 强转为 HttpServletRequest 类型
// 将传入的 ServletResponse 强转为 HttpServletResponse 类型
try {
request = (HttpServletRequest) req;
response = (HttpServletResponse) res;
} catch (ClassCastException e) {
throw new ServletException("non-HTTP request or response");
}
// 调用下面的service 方法,针对于不同的请求类型做对应的处理
service(request, response);
}
protected void service(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
// 获取到请求类型
String method = req.getMethod();
// 依据请求方式的不同,调用对应的方法处理
// 如果是Get形式的请求
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);
// 如果是Post形式的请求
} 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);
}
}
// 一般继承 HttpServlet 时,将重写此方法
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);
}
}
protected long getLastModified(HttpServletRequest req) {
return -1;
}
protected void doHead(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
if (DispatcherType.INCLUDE.equals(req.getDispatcherType())) {
doGet(req, resp);
} else {
NoBodyResponse response = new NoBodyResponse(resp);
doGet(req, response);
response.setContentLength();
}
}
// 一般继承 HttpServlet 时,将重写此方法
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);
}
}
protected void doPut(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
String protocol = req.getProtocol();
String msg = lStrings.getString("http.method_put_not_supported");
if (protocol.endsWith("1.1")) {
resp.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED, msg);
} else {
resp.sendError(HttpServletResponse.SC_BAD_REQUEST, msg);
}
}
protected void doDelete(HttpServletRequest req,
HttpServletResponse resp)
throws ServletException, IOException {
String protocol = req.getProtocol();
String msg = lStrings.getString("http.method_delete_not_supported");
if (protocol.endsWith("1.1")) {
resp.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED, msg);
} else {
resp.sendError(HttpServletResponse.SC_BAD_REQUEST, msg);
}
}
protected void doOptions(HttpServletRequest req,
HttpServletResponse resp)
throws ServletException, IOException {
// 方法体省略
}
protected void doTrace(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException
{
// 方法体省略
}
}
2.3我们自己再实现一个Servlet 继承自HttpServlet
public class HelloWorldServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
// 重写在 HttpServlet 中实现的 doPost 方法
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
// 重写在 HttpServlet 中实现的 doGet 方法
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletConfig config = getServletConfig();
String user = config.getInitParameter("user");
System.out.println("user:" + user);
// 获取全部参数名组成的 Enumeration
Enumeration<String> parameters = config.getInitParameterNames();
while (parameters.hasMoreElements()) {
String param = parameters.nextElement();
String value = config.getInitParameter(param);
System.out.println("param: " + param + " value: " + value);
}
String servletName = config.getServletName();
System.out.println("servletName: " + servletName);
ServletContext servletContext = config.getServletContext();
String driver = servletContext.getInitParameter("driver");
System.out.println("driver: " + driver);
PrintWriter writer = resp.getWriter();
writer.write("HelloWorld!");
writer.flush();
writer.close();
}
}
// 控制台打印
// user:root
// param: user value: root
// servletName: helloWorld
// driver: com.mysql.jdbc.Driver
3. 启动时web.xml的配置
<context-param>
<param-name>driver</param-name>
<param-value>com.mysql.jdbc.Driver</param-value>
</context-param>
<servlet>
<servlet-name>helloWorld</servlet-name>
<servlet-class>org.lhyf.servlet.HelloWorldServlet</servlet-class>
<init-param>
<param-name>user</param-name>
<param-value>root</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>helloWorld</servlet-name>
<url-pattern>/helloword</url-pattern>
</servlet-mapping>
4. 总结
所有的servlet必须实现定义的方法。
servlet是一个在Web服务器中运行的小型Java程序。 Servlet通常通过HTTP(超文本传输协议)接收和响应来自Web客户端的请求。要实现此接口,可以编写扩展 javax.servlet.GenericServlet 或扩展 javax.servlet.http.HttpServlet。
这些被称为生命周期方法,按以下顺序调用:
- 构造器:第一次请求Servlet时,创建Servlet的实例,调用构造器(只被调用一次,单例的)
- 然后使用init方法初始化。只被调用一次,在创建好实例后立即被调用,用于初始化当前Servlet(当多次访问同一个Servlet时,构造器和init方法只在第一次访问时被调用。)
- service方法。被多次调用,每次请求都会调用service方法,用来响应请求。
- servlet停止服务,然后使用destroy方法销毁,然后收集垃圾并完成。
除了生命周期方法之外,该接口还提供了getServletConfig方法,servlet可用于获取任何启动信息,以及getServletInfo方法,该方法允许servlet返回有关其自身的基本信息。
load-on-startup 可以指定Servlet被创建的时机,若为负数,则在第一次请求时创建,若为0或正数,则在当前WEB应用被Servlet容器加载时创建并初始化,且数字越小,越早被创建。
ServletConfig 封装了Servlet的配置信息,并且可以获取 ServletContext 对象