1.  GenericServlet 抽象类:

    1). 是一个 Serlvet. 是 Servlet 接口和 ServletConfig 接口的实现类. 但是一个抽象类. 其中的 service 方法为抽象方法

    2). 如果新建的 Servlet 程序直接继承 GenericSerlvet 会使开发更简洁.

    3). 具体实现:

       ①. 在 GenericServlet 中声明了一个 SerlvetConfig 类型的成员变量, 在 init(ServletConfig) 方法中对其进行了初始化

       ②. 利用 servletConfig 成员变量的方法实现了 ServletConfig 接口的方法

         ③. 还定义了一个 init() 方法, 在 init(SerlvetConfig) 方法中对其进行调用, 子类可以直接覆盖 init() 在其中实现对 Servlet 的初始化.

       ④. 不建议直接覆盖 init(ServletConfig), 因为如果忘记编写 super.init(ServletConfig); 而还是用了 SerlvetConfig 接口的方法,则会出现空指针异常.

       ⑤. 新建的 init(){} 并非 Serlvet 的生命周期方法. 而 init(ServletConfig) 是生命周期相关的方法.

     注:为什么添加一个无参的init()方法?相信你有JavaSE的基础就会明白了!在此就不在赘述了,如果你不知道你可以去看一下关于方法的重载、方法的重写、类与父        类的关系之super的用法。

 GenericServlet的源码:

 public abstract class GenericServletimplements Servlet, ServletConfig, java.io.Serializable{

 private transient ServletConfig config;

     public GenericServlet() { }
/**
* 下面的方法是实现Servlet接口中的方法。
*/
public void destroy() {
} public ServletConfig getServletConfig() {
return config;
} public String getServletInfo() {
return "";
} public abstract void service(ServletRequest req, ServletResponse res)
throws ServletException, IOException; public void init(ServletConfig config) throws ServletException {
this.config = config;
this.init();
} public void init() throws ServletException { } /**
* 下面的方法是实现ServletConfig接口中的方法。
*/ public String getInitParameter(String name) {
return getServletConfig().getInitParameter(name);
} public Enumeration getInitParameterNames() {
return getServletConfig().getInitParameterNames();
} public ServletContext getServletContext() {
return getServletConfig().getServletContext();
} public String getServletName() {
return config.getServletName();
} public void log(String msg) {
getServletContext().log(getServletName() + ": "+ msg);
}
/**
* 下面的方法是GenericServlet抽象类自己定义的方法。
*/ public void log(String message, Throwable t) {
getServletContext().log(getServletName() + ": " + message, t);
}
}

2.  HttpServlet 抽象类:

   1). 是一个 Servlet, 继承自 GenericServlet. 针对于 HTTP 协议所定制.

   2). 在service(ServletRequest, ServletResponse) 方法中直接把 ServletReuqest和ServletResponse 转为 HttpServletRequest 和 HttpServletResponse.并调用了重载的 service(HttpServletRequest, HttpServletResponse)方法,在 重载的 service(HttpServletRequest, HttpServletResponse) 获取了请求方式: request.getMethod(). 根据请求方式有创建了doXxx() 方法(xxx 为具体的请求方式, 比如 Get, Post等等方式。)

HttpServlet源码:

 public abstract class HttpServlet extends GenericServlet
implements java.io.Serializable { 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 ResourceBundle lStrings =
ResourceBundle.getBundle(LSTRING_FILE);
public 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 { NoBodyResponse response = new NoBodyResponse(resp); doGet(req, response);
response.setContentLength();
} 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);
}
}
private static Method[] getAllDeclaredMethods(Class c) { if (c.equals(javax.servlet.http.HttpServlet.class)) {
return null;
} Method[] parentMethods = getAllDeclaredMethods(c.getSuperclass());
Method[] thisMethods = c.getDeclaredMethods(); if ((parentMethods != null) && (parentMethods.length > 0)) {
Method[] allMethods =
new Method[parentMethods.length + thisMethods.length];
System.arraycopy(parentMethods, 0, allMethods, 0,
parentMethods.length);
System.arraycopy(thisMethods, 0, allMethods, parentMethods.length,
thisMethods.length); thisMethods = allMethods;
} return thisMethods;
}
protected void doOptions(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException { Method[] methods = getAllDeclaredMethods(this.getClass()); boolean ALLOW_GET = false;
boolean ALLOW_HEAD = false;
boolean ALLOW_POST = false;
boolean ALLOW_PUT = false;
boolean ALLOW_DELETE = false;
boolean ALLOW_TRACE = true;
boolean ALLOW_OPTIONS = true; for (int i=0; i<methods.length; i++) {
Method m = methods[i]; if (m.getName().equals("doGet")) {
ALLOW_GET = true;
ALLOW_HEAD = true;
}
if (m.getName().equals("doPost"))
ALLOW_POST = true;
if (m.getName().equals("doPut"))
ALLOW_PUT = true;
if (m.getName().equals("doDelete"))
ALLOW_DELETE = true;
} String allow = null;
if (ALLOW_GET)
if (allow==null) allow=METHOD_GET;
if (ALLOW_HEAD)
if (allow==null) allow=METHOD_HEAD;
else allow += ", " + METHOD_HEAD;
if (ALLOW_POST)
if (allow==null) allow=METHOD_POST;
else allow += ", " + METHOD_POST;
if (ALLOW_PUT)
if (allow==null) allow=METHOD_PUT;
else allow += ", " + METHOD_PUT;
if (ALLOW_DELETE)
if (allow==null) allow=METHOD_DELETE;
else allow += ", " + METHOD_DELETE;
if (ALLOW_TRACE)
if (allow==null) allow=METHOD_TRACE;
else allow += ", " + METHOD_TRACE;
if (ALLOW_OPTIONS)
if (allow==null) allow=METHOD_OPTIONS;
else allow += ", " + METHOD_OPTIONS; resp.setHeader("Allow", allow);
}
protected void doTrace(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException
{ int responseLength; String CRLF = "\r\n";
String responseString = "TRACE "+ req.getRequestURI()+
" " + req.getProtocol(); Enumeration reqHeaderEnum = req.getHeaderNames(); while( reqHeaderEnum.hasMoreElements() ) {
String headerName = (String)reqHeaderEnum.nextElement();
responseString += CRLF + headerName + ": " +
req.getHeader(headerName);
} responseString += CRLF; responseLength = responseString.length(); resp.setContentType("message/http");
resp.setContentLength(responseLength);
ServletOutputStream out = resp.getOutputStream();
out.print(responseString);
out.close();
return;
} 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 / 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);
}
}
private void maybeSetLastModified(HttpServletResponse resp,
long lastModified) {
if (resp.containsHeader(HEADER_LASTMOD))
return;
if (lastModified >= 0)
resp.setDateHeader(HEADER_LASTMOD, lastModified);
}
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);
}
} /*
* A response wrapper for use in (dumb) "HEAD" support.
* This just swallows that body, counting the bytes in order to set
* the content length appropriately. All other methods delegate to the
* wrapped HTTP Servlet Response object.
*/
// file private
class NoBodyResponse extends HttpServletResponseWrapper {
private NoBodyOutputStream noBody;
private PrintWriter writer;
private boolean didSetContentLength; // file private
NoBodyResponse(HttpServletResponse r) {
super(r);
noBody = new NoBodyOutputStream();
} // file private
void setContentLength() {
if (!didSetContentLength)
super.setContentLength(noBody.getContentLength());
} // SERVLET RESPONSE interface methods public void setContentLength(int len) {
super.setContentLength(len);
didSetContentLength = true;
} public ServletOutputStream getOutputStream() throws IOException {
return noBody;
} public PrintWriter getWriter() throws UnsupportedEncodingException { if (writer == null) {
OutputStreamWriter w; w = new OutputStreamWriter(noBody, getCharacterEncoding());
writer = new PrintWriter(w);
}
return writer;
}
} /*
* Servlet output stream that gobbles up all its data.
*/ // file private
class NoBodyOutputStream extends ServletOutputStream { private static final String LSTRING_FILE =
"javax.servlet.http.LocalStrings";
private static ResourceBundle lStrings =
ResourceBundle.getBundle(LSTRING_FILE); private int contentLength = 0; // file private
NoBodyOutputStream() {} // file private
int getContentLength() {
return contentLength;
} public void write(int b) {
contentLength++;
} public void write(byte buf[], int offset, int len)
throws IOException
{
if (len >= 0) {
contentLength += len;
} else {
// XXX
// isn't this really an IllegalArgumentException? String msg = lStrings.getString("err.io.negativelength");
throw new IOException(msg);
}
}
}

    3). 实际开发中, 直接继承 HttpServlet, 并根据请求方式复写 doXxx() 方法即可.

    4). 优点: 直接由针对性的覆盖 doXxx() 方法; 直接使用 HttpServletRequest 和  HttpServletResponse, 不再需要强转.

最新文章

  1. linux vmware安装完成后如何设置桥接上网
  2. mysql 索引查询的问题
  3. 【转】c3p0详细配置
  4. Win10 IoT C#开发 6 - 4x4矩阵键盘扫描
  5. Thinkphp的Volist标签
  6. MICROSOFT REPORT VIEWER 2012之无法加载相关的dll
  7. .net 开发框架
  8. kiki&#39;s game
  9. 1.padding和margin,几种参数
  10. SQLServer 复制和数据库镜像 具体配置部署
  11. [Swift]LeetCode73. 矩阵置零 | Set Matrix Zeroes
  12. 同时执行多个$.getJSON() 数据混乱的问题的解决
  13. Python:SQLMap的工作流程
  14. 898. Bitwise ORs of Subarrays
  15. Tasker to proximity screen off
  16. Apache + WordPress + SSL 完全指南
  17. pg_basebackup: invalid tar block header size
  18. 查看自己电脑外网IP
  19. 【51NOD-0】1089 最长回文子串 V2(Manacher算法)
  20. Vue-cli 构建项目 的`.vue`组件中, scss中添加背景图路径问题

热门文章

  1. spring注解机制和XML配置机制之间的比较
  2. 实验七:Linux内核如何装载和启动一个可执行程序
  3. mongodb 教程三
  4. 编程规范之 if 语句的简单规则
  5. 全表扫描引发的db file sequential read
  6. POJ1836 Alignment(LIS)
  7. POJ 1511 SPFA+邻接表 Invitation Cards
  8. HDOJ 1098 Ignatius&#39;s puzzle
  9. Java的内存管理与内存泄露
  10. Stm32 定时器 定时时间设置及PWM频率 占空比的设置总结