HttpServlet机制研究

来源:互联网 发布:淘宝测男女的试纸准吗 编辑:程序博客网 时间:2024/04/29 19:06

写个例子吧

SignContractServlet

package org.test;import java.io.IOException;import javax.servlet.ServletException;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;public class SignContractServlet extends HttpServlet {private static final long serialVersionUID = 1L;public void destroy(){super.destroy();System.out.println(SignContractServlet.class.getName()+" is destried");}public void init()throws ServletException{System.out.println(SignContractServlet.class.getName()+" is inited");    }public void doGet(HttpServletRequest req, HttpServletResponse resp)throws ServletException, IOException {System.out.println("doGet here is SignContractServlet");doPost(req, resp);}public void doPost(HttpServletRequest req, HttpServletResponse resp)throws ServletException, IOException {System.out.println("doPost here is SignContractServlet");//所有访问都被转到这里,在这里进行编码设置,防止乱码。resp.setContentType("text/xml");resp.setHeader("Cache-Control", "no-cache");resp.setCharacterEncoding("UTF-8");//resp.sendRedirect("");}//如果有此方法,servlet默认走此方法,而不走doGet和doPost,在实际中我们可以把这个方法改革名字作为一个处理业务逻辑的方法protected void service(HttpServletRequest req, HttpServletResponse resp)throws ServletException, IOException {System.out.println("service here is revoking.I am the default method.");}}

web.xml配置:

    <servlet><servlet-name>signContractServlet</servlet-name><servlet-class> org.test.SignContractServlet</servlet-class></servlet><servlet-mapping><servlet-name>signContractServlet</servlet-name><url-pattern>/crm/SignContractServlet</url-pattern></servlet-mapping>

访问
http://localhost:8080/frame/crm/SignContractServlet

看后台打印:
org.test.SignContractServlet is inited
service here is revoking.I am the default method.

现在是不是有点奇怪了?doGet,doPost方法没被调用?是的,没被调用。
网上查了下,HttpServlet类中有个service方法:

protected void service(HttpServletRequest req, HttpServletResponse resp)
        throws ServletException, IOException

这个方法处理请求,他会判断你的请求类型。
就好比是个代理,帮你处理所有请求,请求类型自动帮你判断。所以我们重写的
doGet,doPost方法就没被调用。

好了,现在为了调用doGet,doPost方法,我们把service方法注释掉(或者改个名字)。
再试一次,打印:

org.test.SignContractServlet is inited
doGet here is SignContractServlet
doPost here is SignContractServlet

结果已经证明就是如此。
现在我们看看这个service方法到底是什么玩意,HttpServlet源码中:

    protected void service(HttpServletRequest req, HttpServletResponse resp)        throws ServletException, IOException    {        String method = req.getMethod();        if(method.equals("GET"))        {            long lastModified = getLastModified(req);            if(lastModified == -1L)            {                doGet(req, resp);            } else            {                long ifModifiedSince = req.getDateHeader("If-Modified-Since");                if(ifModifiedSince < (lastModified / 1000L) * 1000L)                {                    maybeSetLastModified(resp, lastModified);                    doGet(req, resp);                } else                {                    resp.setStatus(304);                }            }        } else        if(method.equals("HEAD"))        {            long lastModified = getLastModified(req);            maybeSetLastModified(resp, lastModified);            doHead(req, resp);        } else        if(method.equals("POST"))            doPost(req, resp);        else        if(method.equals("PUT"))            doPut(req, resp);        else        if(method.equals("DELETE"))            doDelete(req, resp);        else        if(method.equals("OPTIONS"))            doOptions(req, resp);        else        if(method.equals("TRACE"))        {            doTrace(req, resp);        } else        {            String errMsg = lStrings.getString("http.method_not_implemented");            Object errArgs[] = new Object[1];            errArgs[0] = method;            errMsg = MessageFormat.format(errMsg, errArgs);            resp.sendError(501, errMsg);        }    }

源码之中,我们看到,service方法首先获取到请求的类型:
String method = req.getMethod();
类型有7个,分别是:
GET,HEAD,POST,PUT,DELETE,OPTIONS,TRACE。
如果有例外,就报出一个501错误,resp.sendError(501, errMsg);
这个方法我们最好不好重写,为什么呢?因为它已经有了自己的逻辑。
我们重写只会破坏它原本的逻辑。


还有为什么会有这7个请求类型呢?
网上搜到的资料:


#################################################################

HTTP 目前支持 7 种请求方法: GET 、 POST 、  PUT 、 DELETE 、 TARCE、HEAD 、 OPTIONS .
前四个都是客户端请求数据这类相关的方法.

GET      请求获取由Request-URI所标识的资源。
POST 在Request-URI所标识的资源后附加新的数据。
PUT 请求服务器存储一个资源,并用Request-URI作为其标识。
DELETE 请求服务器删除由Request-URI所标识的资源。
 
TRACE 请求服务器回送收到的请求信息,主要用语测试或诊断。
HEAD 请求获取由Request-URI所标识的资源的响应消息报头。
OPTIONS 请求查询服务器的性能,或查询与资源相关的选项和需求。

#################################################################

我们再看看HttpServlet的源码,下面手机所有方法:

protected void doGet(HttpServletRequest req, HttpServletResponse resp)protected long getLastModified(HttpServletRequest req)protected void doHead(HttpServletRequest req, HttpServletResponse resp)protected void doPost(HttpServletRequest req, HttpServletResponse resp)protected void doPut(HttpServletRequest req, HttpServletResponse resp)protected void doDelete(HttpServletRequest req, HttpServletResponse resp)private static Method[] getAllDeclaredMethods(Class c)protected void doOptions(HttpServletRequest req, HttpServletResponse resp)protected void doTrace(HttpServletRequest req, HttpServletResponse resp)protected void service(HttpServletRequest req, HttpServletResponse resp)private void maybeSetLastModified(HttpServletResponse resp, long lastModified)public void service(ServletRequest req, ServletResponse res)
上面确实有对应的7个get方法,而service方法就是这7个的一个综合服务。
其实客户端使用的请求只有上面4个,GET 、 POST 、  PUT 、 DELETE 。对应
4个方法,doGet,doPost,doPut,doDelete。
而我们最常用的就是doGet,doPost方法,这2个方法的区别简单是一个是get请求,参数在url后,
在地址栏会看到,长度也有限制。而post请求把提交的数据则放置在是HTTP包的包体中,
理论上POST没有限制,适用于较大量的数据。

好,现在开始想想上面4个方法的区别,
GET      请求获取由Request-URI所标识的资源---简单的理解为查询资源。
POST     在Request-URI所标识的资源后附加新的数据---简单的理解为修改更新资源。
PUT      请求服务器存储一个资源,并用Request-URI作为其标识---简单的理解为新增资源。
DELETE   请求服务器删除由Request-URI所标识的资源---简单的理解为删除资源。
 
HttpServlet继承了父类抽象类GenericServlet如下:
public abstract class GenericServlet
其中:

    public void destroy()    {    }    public void init()        throws ServletException    {    }public abstract void service(ServletRequest servletrequest, ServletResponse servletresponse)        throws ServletException, IOException;

destroy,init方法和service不同,service是抽象方法在子类HttpServlet已经继承实现了。而destroy,init方法就是为了让我们重写用的,以实现我们的实际需求。








原创粉丝点击