Java的开源给了我们更多机会,去了解组件内部的实现。从事Java Web开发,大家都会跟直接或间接的跟Servlet打交道。今天我们就来谈谈Servlet。
我们在手写Servlet时,会继承HttpServlet类。在HttpServlet类中,有几个重要的方法:doPost()方法、doGet()方法、service()方法。当我们调用自己写的Servlet时,系统会默认调用doGet()方法;或者说,当我们指定一种传输方式,系统会自动调用我们重写的方法。这是采用设计模式中模板模式实现的。
Servlet是由Tomcat之类的servlet容器来调用处理浏览器请求的,并需要集成基类HttpServlet。反编译出HttpServlet的class文件,我们可以看出,该类中存在两个service()方法:
1、 protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException{……} 2、 public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException{……}
public修饰的service方法,其实是重写了父类GenericServlet中的service()方法,它主要完成的功能是接收客户端请求,并将resquest和response传递给service()方法。父类GenericServlet中,则是service()方法的最高级抽象,给出的是service()抽象方法。
1、 public abstract void service(ServletRequest paramServletRequest, ServletResponse paramServletResponse) throws ServletException, IOException;
而protected修饰的service方法,Tomcat容器实际调用的是这个service()方法。service()方法的实现就是根据http求情的类型(get、post),将处理委派给doGet、doPost等方法,由这些子类的方法来最终处理浏览器的求情。
由此可知:HttpServlet定义了一个处理的框架,或者说是模板,实现Servlet只需要继承HttpServlet并重写doPost()和doGet()方法就可以了。
下面看看模版模式的实现:
//父类HttpServlet public abstract class HttpServlet extends GenericServlet implements Serializable { protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {……} 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"); } //调用protected service service(request, response); } } //自己写的Servlet,继承HttpServlet import java.io.IOException; import java.io.PrintStream; import java.io.PrintWriter; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class LoginServlet extends HttpServlet { //重写父类中的doGet方法 public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String strOne = request.getParameter("username"); String strTwo = request.getParameter("password"); System.out.println("username=" + strOne); System.out.println("password=" + strTwo); response.setContentType("text/html"); response.getWriter().println("Login Success!!"); } //重写父类中的doPost方法 public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request,response); } }
总结,这种实现,重复的代码都上升到了父类中去,而变化的部分在子类中具体实现。