servlet的作用是什么?
我们都知道网页分为静态网页(static web)和动态网页(dynamic web)之分。静态网页是只能干瞪眼看着的,而动态网页是可以进行客户端(浏览器)和服务器的交互,比如公司实习生的最佳练手项目之一的页面登陆。我们将输入的账号密码提交到服务器,服务器就会处理这些信息然后做出登陆成功进入某个页面或者失败的反馈。那么中间这个客户端到服务器之间的交互的过程是如何实现的呢?这里就是Servlet的用武之地了!
什么是Servlet?
全称为Java Servlet。是用Java编写的实现了Servlet接口的类(服务端小程序),也被称为小服务程序或服务连接器。主要功能在于接收和响应从客户端发送过来的请求,交互式地浏览和修改数据,生成动态Web内容。(这也是为什么最后出现子类HttpServlet的原因,和http协议完美融合)
Servlet的生命周期?
Servlet从产生到消亡的过程中一共有三个生命周期函数。分别是初始化方法init(),处理客户请求的方法services(),终止方法destroy()。
这部分就不得不提关于Servlet接口实现和类继承关系的存在。
init()方法:
在一个Servlet的生命周期中,init()方法只会被服务器调用执行一次。无论用户执行多少请求,都不会再调用该方法,直到关闭服务器打开再重新创建Servlet才会再次调用init()方法。
因为我们常用的HttpServlet继承中有两个init()方法,当我们重写的时候只需要重写一个无参的init()方法就好了。
为什么呢?在GenericServlet源代码里面有参的init()调用了无参的init(),如果重写有参的init()岂不是要GG?
public void init(ServletConfig config) throws ServletException {
this.config = config;
this.init();
}
services()方法:
这个是可以好好说到说到的一个部分。
如果自己想要实现Servlet接口,就需要实现五个方法,比较麻烦。所以最开始的Servlet接口被GenericServlet抽象类实现(因为只是实现了但是这里仍旧没有给出具体的方法 ,所以GenericServlet仍是抽象类),此时继承以后需要哪个方法重写哪个具体的方法就好了嘛。接着为了更加的方便,HttpServlet继承了GenericServlet抽象类并实现了抽象方法。此时,实现一个Servlet只需要继承HttpServlet就完全ok了。
(当然这里的更加方便并不只是为了Servlet接口的五个方法,毕竟前面该多了Http不是?可以查一下API自行领会,哎呀就是多了一些和Http有关的方法嘛!)
此时的HttpServlet重写了service()方法,并且给出了所有doxxx和getxxx的方法判断,当我们(MyServlet)继承该类的时候,去处理底层代码时,也只需要重写doxxx方法和getxxx方法就完全可以达到改变service()方法的地步,最好不要重写service()的原因是万一重写了我们自己调用doxxx方法或者getxxx方法出错了呢?
所以只需要重写doxxx和getxxx就可以完成service()方法的重写。等待继承来的services()方法的调用中调用doxxx或者getxxx方法
这里可以在HttpServlet源代码中找到案例
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);
}
}
destroy()方法:
这个没有什么特别好说的,当web服务器关闭时,destroy()方法调用,销毁,完事。
所以,正确的大致Servlet开发步骤如下:
* 开发步骤
* 编写一个类,继承HttpServlet
* 重写doGet和doPost方法
* 在doPost方法中调用doGet方法。
* 表单是get方式,调用doGet
* 表单是post方法,调用doPost方法
* doGet和doPost互相调用。
* 在web.xml配置
关于web.xml的配置已经在其他博客中讲过,在此不再提及。