标签:servlet web httpservlet genericservlet
工作也大半年了,由于接触的是物流行业,大部分时间接触的都是业务方面的内容,技术方面要求不是很高,渐渐的发现对某些知识都遗忘了,技术这东西不经常使用的话就会变得很生疏。所以,在工作之余觉得还是有必要去拾起那些快要被淡忘的知识。这篇文章主要是想把servlet中的相关知识结合源码去复习和加强一下,更进一步的分析和理解其中的细节东西和原理。
对于servlet这里不做过多的介绍了,简单介绍一下,servlet其实就是sun公司提供的一种动态web资源开发技术,它的本质还是和我们平时写的java程序差不多,只是要求这个类必须实现servlet接口。而要实现servlet接口必须要实现其中的方法:如下图
从上面的描述,我们就基本上可以写一个简单的servlet demo了:
eg:
/**
* servlet 的实现机制分析
* @author JiangYu
*
*/
public class ServletDemo implements Servlet {
public void destroy() {
}
public ServletConfig getServletConfig() {
return null;
}
public String getServletInfo() {
return null;
}
public void init(ServletConfig config) throws ServletException {
}
public void service(ServletRequest req, ServletResponse res)
throws ServletException, IOException {
}
}
从上面的代码可以看出来,Servlet接口中有五个方法,其中的方法分别有什么作用,以及要在web.xml中配置哪些相关内容,后面再做说明。上面是自己创建的一个servlet,下面我们借助IDE工具帮我们自动建立一个servlet,然后我们进行对比。
package com.jjyy.servlet;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* servlet源码分析
* @author JiangYu
*
*/
public class ServletDemo_1 extends HttpServlet {
public void doGet(HttpServletRequest request,HttpServletResponse response)
throws ServletException, IOException {
}
public void doPost(HttpServletRequest request,HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
通过和对比,我们发现myeclipse帮助我们生产的代码和我们自己写的不一样,这是什么原因,我们的写法到底是不是真确的呢?下面我们可以通过分析上面的两段代码可以发现,用IDE工具生成的代码没有不是直接通过实现servlet接口,而是继承了一个叫HttpServlet的类。
找到了原因之后,我们可以猜到HttpServlet类肯定是实现了servlet接口的。分析源码:
从源代码中可以看到HttpServlet其实是一个抽象类,观察其中的方法,我们可以看到有一个service方法和我们上面重写的方法一样,还有doGet()和doPost()方法等,但是还是不能看出来为何我们写的和工具生成的不一致。在仔细的看这个类:
它也继承了一个叫做GenericServlet的类,这也许可以发现其中的原因了,我们再次的猜测肯定是GenericServlet 实现了Servlet接口,查看GenericServlet的源码可以发现,果然,
GenericServlet实现了Servlet接口,并且还是一个抽象类,再看其中的方法:
到此,我们就可以明白为何我们自己写的和IDE工具生成的不一样了。其实通过分析源码可以发现,这种实现的机制其实是一种设计思想,为了避免我们每次编写servlet类是要实现servlet接口中的五个方法,采用了一种适配的模式,通过一个抽象类去实现接口,可以让我们不去关注那些我们不要的功能,对于某些特定的功能的实现,可以通过继承抽象类复写相应的方法去实现我们要关注的那一部分功能。为了更好的理解,我们可以看一下源码中这些类和接口之间的关系:
虽然,我们知道了它的实现思想了,但是我们的疑问还是没有解决,为何IDE工具生成的是doGet和doPost方法,而不是我们看到的Servlet接口五个方法中的方法呢?接下来我们再看HttpServlet中的方法,发现其中有doGet和doPost方法、service()方法:
再看service()方法:其中通过request来获取method并且来判断调用那个方法;
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);
}
}
再看GenericServlet中的方法:是一个抽象的方法,也就是说它没有实现servlet中的service()方法,而HttpServlet又继承自GenericServlet类并且对service()方法给予了实现。
所以IDE帮我们生成的servlet代码时的doGet和doPost方法是对HttpServlet中的doGet和doPost的重写。
为何重写的是这两个方法呢?这就要我们进一步了解了,(可以看到有七个doXXX,但是常用的就doGet和doPost)。HttpServlet:对HTTP协议进行了优化的Servlet,继承自GenericServlet类,并且实现了其中的service抽象方法,默认的实现中判断了请求的请求方式,并根据请求方式的不同分别调用不同的doXXX()方法。通常我们直接继HttpServlet即可。所以从上面的分析终于知道为何自动生成的代码中只有doGet和doPost方法的原因
对于编写servlet程序,当然还有一个必要的知识就是:配置web应用的web.xml注册Servlet的信息了。因为是回顾知识,这里就不再啰嗦了,看下图就知道了:
未完待续。。。。。。
标签:servlet web httpservlet genericservlet
原文地址:http://blog.csdn.net/before_morning/article/details/44262583