【JavaEE】Servlet接口、ServletConfig接口、GenericServlet抽象类、ServletContext接口、HttpServlet类源码及方法

Servlet接口、ServletConfig接口、GenericServlet抽象类、ServletContext接口、HttpServlet类源码及方法

1.Servlet接口

Servlet接口定义的方法
【生命周期】
1.int()初始化Servlet。
2.service(), 用来处理request请求。
3.destroy(),将servlet移除容器,然后GC垃圾回收。

【addition methods】
4.getServletInfo()允许servlet返回关于servlet自身的基本信息,如author,version,copyright
5.getServletConfig(),返回ServletConfig实例,是一个servlet configuration object 。

public interface Servlet {
  public void init(ServletConfig config);
  public ServletConfig getServletConfig();
  public void service(ServletRequest req, ServletResponse res);
  public String getServletInfo();
  public void destroy();
}

2.ServletConfig接口

Servlet容器使用的servlet设置信息的对象,用来在初始化期间向servlet传递信息
1.getServletName()返回Servlet实例的名称。
2.getServletContext()返回ServletContext的引用。
3.getInitParameter()返回包含指定name的servlet初始化参数的值。
4.getInitParameterNames()返回初始化参数的所有name,将其包装在Enumeration对象。

 public interface ServletConfig {
     public String getServletName();
     public ServletContext getServletContext();

     public String getInitParameter(String name);
     public Enumeration<String> getInitParameterNames(); 
}

3.GenericServlet抽象类

定义一个通用的,协议无关的Servlet类,直接继承GenericServlet抽象类,使得我们写servlet更容易。
通常特定协议的Servlet继承此GenericServlet。如HttpServlet就是继承自GenericServlet实现的。
GenericServlet实现了Servlet、ServletConfig、Serializable接口。


public abstract class GenericServlet implements Servlet,ServletConfig,Serializable{
    private static final String LSTRING_FILE = "javax.servlet.LocalStrings";
    private static ResourceBundle lStrings =ResourceBundle.getBundle(LSTRING_FILE);
    private transient ServletConfig config;
    public GenericServlet() { }
    /**1.实现的Servlet接口*/
    public void init() throws ServletException { }  
    public void init(ServletConfig config) throws ServletException {
        this.config = config;
        this.init();
    }
    public ServletConfig getServletConfig() {
        return config;
    }   
    public abstract void service(ServletRequest req, ServletResponse res)
        throws ServletException, IOException;   
    public String getServletInfo() {
        return "";
    }
    public void destroy() {}
    /**2.实现ServletConfig接口*/
    public String getServletName() {
        ServletConfig sc = getServletConfig();
        if (sc == null) {
            throw new IllegalStateException(
                lStrings.getString("err.servlet_config_not_initialized"));
        }
        return sc.getServletName();
    }       
    public ServletContext getServletContext() {
        ServletConfig sc = getServletConfig();
        if (sc == null) {
            throw new IllegalStateException(
                lStrings.getString("err.servlet_config_not_initialized"));
        }
        return sc.getServletContext();
    }   
    public String getInitParameter(String name) {
        ServletConfig sc = getServletConfig();
        if (sc == null) {
            throw new IllegalStateException(
                lStrings.getString("err.servlet_config_not_initialized"));
        }
        return sc.getInitParameter(name);
    }
    public Enumeration<String> getInitParameterNames() {
        ServletConfig sc = getServletConfig();
        if (sc == null) {
            throw new IllegalStateException(
                lStrings.getString("err.servlet_config_not_initialized"));
        }
        return sc.getInitParameterNames();
    }   

    /**3.实现log方法,此方法定义在ServletContext接口中*/
    public void log(String msg) {
        getServletContext().log(getServletName() + ": "+ msg);
    }
    public void log(String message, Throwable t) {
        getServletContext().log(getServletName() + ": " + message, t);
    }
}   

4.ServletContext接口

ServletContext定义一系列方法用来与Servlet容器进行分交互。如:获取MIME类型的文件,dispatch Request,写入log文件。
每一个Web应用,每个JVM中只有一个context,

public interface ServletContext { 
    /**1.Path相关操作。
        getRealPath(String path):通过给定的virtual path返回对应的real path.
        getRequestDispatcher(String path):返回给定path的servlet的RequestDispatcher 对象,该对象包含该Servlet的资源。
        getNamedDispatcher(String name):返回给定命名的servlet的RequestDispatcher 对象。
        getResource(String path):返回特定路径的URL对象。
        getResourceAsStream(String path):返回给定path的资源,将其作为输入流
        getResourcePaths(String path):返回web应用中所有资源路径的列表(类似于目录),它们的完整子路径应匹配提供的路径参数。
    */
    public String getRealPath(String path); 
    public RequestDispatcher getRequestDispatcher(String path);
    public RequestDispatcher getNamedDispatcher(String name);
    public URL getResource(String path) throws MalformedURLException;
    public InputStream getResourceAsStream(String path);
    public Set<String> getResourcePaths(String path);

    /**2.ServletContext。
        返回特定URL的ServletContext对象。
    */
    public ServletContext getContext(String uripath);

    /**3.attribute属性的操作。
        getAttribute(String name):返回包含的指定name的属性值
        setAttribute(String name, Object object):
        removeAttribute(String name):从servlet context中移除给定的属性。
        getAttributeNames():返回servlet context中的包含的可用的attribute names。
    */
    public Object getAttribute(String name); 
    public void setAttribute(String name, Object object);   
    public void removeAttribute(String name);    
    public Enumeration<String> getAttributeNames();        
    /**4.Servlet信息相关。
        getServerInfo():返回servlet运行的容器的servlet的名称和版本。
        getServletContextName():返回web应用的名称。
    */

    public String getServerInfo();      
    public String getServletContextName(); 
    /**5.参数相关。
        getInitParameter(String name):返回ServletContext指定的初始化参数。
        getInitParameterNames():返回context初始化参数的名称集合。
    */
    public String getInitParameter(String name);
    public Enumeration<String> getInitParameterNames(); 
    public boolean setInitParameter(String name, String value);

    /**6.log相关。
        向log file写日志
    */
    public void log(String msg);
    public void log(String message, Throwable throwable);       
}

5.HttpServlet


public abstract class HttpServlet extends GenericServlet{
    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";
    public HttpServlet() { }


    /*1.Servlet容器调用此service(ServletRequest req, ServletResponse res)方法。*/
    public void service(ServletRequest req, ServletResponse res)throws ServletException, IOException{
        HttpServletRequest  request;
        HttpServletResponse response;
        /**java中的instanceof运算符是用来在运行时指出对象是否是特定类的一个实例
           此处用来校验req和res是否为Http类型的参数*/      
        if (!(req instanceof HttpServletRequest &&  res instanceof HttpServletResponse)) {            
            throw new ServletException("non-HTTP request or response");
        }
        request = (HttpServletRequest) req;
        response = (HttpServletResponse) res;
        /**跳转至service(HttpServletRequest req, HttpServletResponse resp)函数。*/
        service(request, response);
    }

    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException{
        //1.获取请求的类型
        String method = req.getMethod();
        //如果是Get方法
        if (method.equals(METHOD_GET)) {
            long lastModified = getLastModified(req);
            //lastModified值为-1,无缓存,实时刷新。HttpServlet的默认值为-1.
            if (lastModified == -1) {
                doGet(req, resp);
            } else {
                long ifModifiedSince = req.getDateHeader(HEADER_IFMODSINCE);
                if (ifModifiedSince < lastModified) {
                    maybeSetLastModified(resp, lastModified);
                    doGet(req, resp);
                } else {
                    //如果缓存时间>=服务器文件修改时间,则直接返回304
                    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 {
            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);
        }
    }
    /**
        设置Last-Modified实体头字段(如果尚未设置并且该值有意义)。在doGet之前调用,
        以确保在写入响应数据之前设置头。一个子类可能已经设置了这个头,所以我们检查。      
    */
    private void maybeSetLastModified(HttpServletResponse resp,long lastModified) {                             
        if (resp.containsHeader(HEADER_LASTMOD))
            return;
        if (lastModified >= 0)
            resp.setDateHeader(HEADER_LASTMOD, lastModified);
    }     

    //HttpServlet默认返回-1,无缓存机制。
    protected long getLastModified(HttpServletRequest req) {
        return -1;
    }

    /**doGet()与doPost()方法:*/
    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 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);
        }
    }
}

6.request请求中的If-Modified-Since标签与response响应中的Last-Modified标签。

参考 http://www.cnblogs.com/zh2000g/archive/2010/03/22/1692002.html

服务器会把这个时间与服务器上实际文件的最后修改时间进行比较。如果时间一致,那么返回HTTP状态码304(不返回文件内容),
客户端接到之后,就直接把本地缓存文件显示到浏览器中。如果时间不一致,就返回HTTP状态码200和新的文件内容,客户端接到之后,
会丢弃旧文件,把新文件缓存起来,并显示到浏览器中。
If-Modified-Since,Http请求消息头标签:
在发送HTTP请求时,把浏览器端缓存页面的最后缓存时间。
一起发到服务器去,在客户端的缓存存储中有服务器发过来的该文件的最后服务器修改时间。

lastModified,Http响应消息头标签:
在浏览器第一次请求某一个URL时,服务器端的返回状态会是200,内容是客户端请求的资源,
同时有一个Last-Modified的属性标记此文件在服务器端最后被修改的时间。

比较If-Modified-Since参数和lastModified 的新旧,决定是否刷新浏览器缓存,如果lastModified 使用默认的-1L,总是刷新。

在HttpServlet类中定义了一个getLastModified方法,语法定义如下: protected long getLastModified(HttpServletRequest req)
HttpServlet类中定义的getLastModified方法总是返回一个负数,
在HttpServlet子类中可以对这个方法进行覆盖,返回一个代表当前输出的响应内容的修改时间,HttpServlet类的
service方法可以根据这个返回值在响应消息中自动生成Last-Modified头字段。
一般情况下,浏览器都会缓存已经访问过的页面内容,getLastModified方法的返回值可以影响浏览器如何处理和利用缓存内容。

GET:它本质就是发送一个请求来取得服务器上的某一资源.
资源通过一组HTTP头和呈现数据(如HTML文本,或者图片或者视频等)返回给客户端。

HEAD:只请求页面的首部。
HEAD和GET本质是一样的,区别在于HEAD不含有呈现数据,而仅仅是HTTP头信息。

POST:向服务器提交数据。这个方法用途广泛,几乎目前所有的提交操作都是靠这个完成。
PUT:这个方法比较少见。HTML表单也不支持这个。本质上来讲, PUT和POST极为相似,都是向服务器发送数据,
但它们之间有一个重要区别,PUT通常指定了资源的存放位置,而POST则没有,
POST的数据存放位置由服务器自己决定。
DELETE:请求服务器删除指定的资源。
OPTIONS:允许客户端查看服务器的性能。
TRACE: 请求服务器在响应中的实体主体部分返回所得到的内容。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值