Servlet、GenericServlet、HttpServlet之间的关系以及HttpServletRequest,HttpServletResponse。

序言

三个类
 javax.servlet.Servlet
 javax.servlet.GenericServlet
 javax.servlet.http.HttpServlet
  • 在学习Servlet时,先学习的Servlet接口,这是最底层的一个接口,直接使用比较麻烦而且方法少

  • GenericServlet Abstract类就诞生了,是一个抽象类,实现了Servlet。是Servlet的扩展

  • 同理,HttpServlet Abstract类是对Servlet的扩展。又增添了新的方法。

一、Servlet、GenericServlet、HttpServlet

当编写一个servlet时,必须直接或间接实现servlet接口,最可能实现的方法就是扩展javax.servlet.GenericServlet或javax.servlet.http.HttpServlet当实现javax.servlet.Servlet接口时必须实现5个方法

  • init(ServletConfig config)

  • service(ServletRequest request,ServletResponse response)

  • destroy()

  • getservletconfig()

  • getservletinfo()

1、Servlet

Servlet源码


public interface Servlet {
    void init(ServletConfig var1) throws ServletException;
 
    ServletConfig getServletConfig();
 
    void service(ServletRequest var1, ServletResponse var2) throws ServletException, IOException;
 
    String getServletInfo();
 
    void destroy();
}
  1. service是执行应用逻辑的入口点,包容器调用此方法来响应进来得请求,只是在servlet被成功初始化后才能调用它

  2. 其实servlet和applet差不多,当一个servlet被实例化后,包容器自动去调用固定的方法首先是init(),然后是service()…

2、GenericServlet

GenericServlet源码

package javax.servlet;
import java.io.IOException;
import java.io.Serializable;
import java.util.Enumeration;
import java.util.ResourceBundle;
public abstract class GenericServlet
  implements Servlet, ServletConfig, Serializable
{
  private static final String LSTRING_FILE = "javax.servlet.LocalStrings";
  private static ResourceBundle lStrings = ResourceBundle.getBundle("javax.servlet.LocalStrings");
  private transient ServletConfig config;
  public void destroy(){}
  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 getInitParameterNames(){
    ServletConfig sc = getServletConfig();
    if (sc == null) {
      throw new IllegalStateException(lStrings.getString("err.servlet_config_not_initialized"));
    }
    return sc.getInitParameterNames();
  }
  
  public ServletConfig getServletConfig(){
    return this.config;
  }
  public ServletContext getServletContext()
  {
    ServletConfig sc = getServletConfig();
    if (sc == null) {
      throw new IllegalStateException(lStrings.getString("err.servlet_config_not_initialized"));
    }
    return sc.getServletContext();
  }
  
  public String getServletInfo(){
    return "";
  }
  
  public void init(ServletConfig config)
    throws ServletException{
    this.config = config;
    init();
  }
  
  public void init()
    throws ServletException{
  }
  
  public void log(String msg){
    getServletContext().log(getServletName() + ": " + msg);
  }
  
  public void log(String message, Throwable t){
    getServletContext().log(getServletName() + ": " + message, t);
  }
  
  public abstract void service(ServletRequest paramServletRequest, ServletResponse paramServletResponse)
    throws ServletException, IOException;
  public String getServletName(){
    ServletConfig sc = getServletConfig();
    if (sc == null) {
      throw new IllegalStateException(lStrings.getString("err.servlet_config_not_initialized"));
    }
    return sc.getServletName();
  }
  
}
  1. GenericServlet类提供了servlet接口的基本实现,所以他的子类都必须实现service()方法

3、HttpServlet

HttpServlet源码

package javax.servlet.http;
 
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Method;
import java.text.MessageFormat;
import java.util.Enumeration;
import java.util.ResourceBundle;
 
import javax.servlet.DispatcherType;
import javax.servlet.GenericServlet;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
public abstract class HttpServlet extends GenericServlet {
 
    private static final long serialVersionUID = 1L;
 
    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";
 
    private static final String LSTRING_FILE =
        "javax.servlet.http.LocalStrings";
    private static final ResourceBundle lStrings =
        ResourceBundle.getBundle(LSTRING_FILE);
 
 
    /**
     * Does nothing, because this is an abstract class.
     */
    public HttpServlet() {
        // NOOP
    }
 
	protected long getLastModified(HttpServletRequest req) {
        return -1;
    }
    protected void doHead(HttpServletRequest req, HttpServletResponse resp)
        throws ServletException, IOException {
 
        if (DispatcherType.INCLUDE.equals(req.getDispatcherType())) {
            doGet(req, resp);
        } else {
            NoBodyResponse response = new NoBodyResponse(resp);
            doGet(req, response);
            response.setContentLength();
        }
    }

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);
        }
    }

 protected void doPut(HttpServletRequest req, HttpServletResponse resp)
        throws ServletException, IOException {
 
        String protocol = req.getProtocol();
        String msg = lStrings.getString("http.method_put_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 doDelete(HttpServletRequest req,
                            HttpServletResponse resp)
        throws ServletException, IOException {
 
        String protocol = req.getProtocol();
        String msg = lStrings.getString("http.method_delete_not_supported");
        if (protocol.endsWith("1.1")) {
            resp.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED, msg);
        } else {
            resp.sendError(HttpServletResponse.SC_BAD_REQUEST, msg);
        }
    }

 private static Method[] getAllDeclaredMethods(Class<?> c) {
 
        if (c.equals(javax.servlet.http.HttpServlet.class)) {
            return null;
        }
 
        Method[] parentMethods = getAllDeclaredMethods(c.getSuperclass());
        Method[] thisMethods = c.getDeclaredMethods();
 
        if ((parentMethods != null) && (parentMethods.length > 0)) {
            Method[] allMethods =
                new Method[parentMethods.length + thisMethods.length];
            System.arraycopy(parentMethods, 0, allMethods, 0,
                             parentMethods.length);
            System.arraycopy(thisMethods, 0, allMethods, parentMethods.length,
                             thisMethods.length);
 
            thisMethods = allMethods;
        }
 
        return thisMethods;
    }

protected void doOptions(HttpServletRequest req,
            HttpServletResponse resp)
        throws ServletException, IOException {
 
        Method[] methods = getAllDeclaredMethods(this.getClass());
 
        boolean ALLOW_GET = false;
        boolean ALLOW_HEAD = false;
        boolean ALLOW_POST = false;
        boolean ALLOW_PUT = false;
        boolean ALLOW_DELETE = false;
        boolean ALLOW_TRACE = true;
        boolean ALLOW_OPTIONS = true;
 
        for (int i=0; i<methods.length; i++) {
            Method m = methods[i];
 
            if (m.getName().equals("doGet")) {
                ALLOW_GET = true;
                ALLOW_HEAD = true;
            }
            if (m.getName().equals("doPost"))
                ALLOW_POST = true;
            if (m.getName().equals("doPut"))
                ALLOW_PUT = true;
            if (m.getName().equals("doDelete"))
                ALLOW_DELETE = true;
        }
 
        String allow = null;
        if (ALLOW_GET)
            allow=METHOD_GET;
        if (ALLOW_HEAD)
            if (allow==null) allow=METHOD_HEAD;
            else allow += ", " + METHOD_HEAD;
        if (ALLOW_POST)
            if (allow==null) allow=METHOD_POST;
            else allow += ", " + METHOD_POST;
        if (ALLOW_PUT)
            if (allow==null) allow=METHOD_PUT;
            else allow += ", " + METHOD_PUT;
        if (ALLOW_DELETE)
            if (allow==null) allow=METHOD_DELETE;
            else allow += ", " + METHOD_DELETE;
        if (ALLOW_TRACE)
            if (allow==null) allow=METHOD_TRACE;
            else allow += ", " + METHOD_TRACE;
        if (ALLOW_OPTIONS)
            if (allow==null) allow=METHOD_OPTIONS;
            else allow += ", " + METHOD_OPTIONS;
 
        resp.setHeader("Allow", allow);
    }
 

 protected void doTrace(HttpServletRequest req, HttpServletResponse resp)
        throws ServletException, IOException
    {
 
        int responseLength;
 
        String CRLF = "\r\n";
        StringBuilder buffer = new StringBuilder("TRACE ").append(req.getRequestURI())
            .append(" ").append(req.getProtocol());
 
        Enumeration<String> reqHeaderEnum = req.getHeaderNames();
 
        while( reqHeaderEnum.hasMoreElements() ) {
            String headerName = reqHeaderEnum.nextElement();
            buffer.append(CRLF).append(headerName).append(": ")
                .append(req.getHeader(headerName));
        }
 
        buffer.append(CRLF);
 
        responseLength = buffer.length();
 
        resp.setContentType("message/http");
        resp.setContentLength(responseLength);
        ServletOutputStream out = resp.getOutputStream();
        out.print(buffer.toString());
        out.close();
        return;
    }

 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;
                try {
                    ifModifiedSince = req.getDateHeader(HEADER_IFMODSINCE);
                } catch (IllegalArgumentException iae) {
                    // Invalid date header - proceed as if none was set
                    ifModifiedSince = -1;
                }
                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);
        }
    }
private void maybeSetLastModified(HttpServletResponse resp,
                                      long lastModified) {
        if (resp.containsHeader(HEADER_LASTMOD))
            return;
        if (lastModified >= 0)
            resp.setDateHeader(HEADER_LASTMOD, lastModified);
    }

@Override
    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");
        }
        service(request, response);
    }
  }
}
  1. HttpServlet类扩展了GenericServlet并且提供了servlet接口中具体于http的实现,它更象一个其他所有的servlet都要扩展的类,其中他定义了两种形式的service方法:
service(ServletRequest request,ServletResponse response)
  1. 此方法是genericservlet的service()方法的实现,他把resquest,response对象分别转化为 HttpServletRequest 和 HttpServletResponse 并且调用下面重载的service()方法,所以不应当重载上面的service()方法:
protect void service (HttpServletRequest req , HttpServletResponseresp)    

6. 他用http的request,response对象作为参数,并且由上面的方法调用,httpservlet实现这个方法后就成为一个http请求的分发者,他把请求代理给doget(),dopost()…等              doxxxx()方法

  1. 当包容器为一个servlet收到一个请求时,包容器调用公共的service方法在把参数转换为httpservirequest,httpservletresponse 后,这个公共的方法调用保护的service根据http请求方法的类型,保护的service方法调用doxxxx()方法之一.

  2. doget()方法是当得到一个get类型的请求时调用 dopost()方法是当得到一个post类型的请求时调用

  3. httpservlet是从genericservlet继承而来,因此httpservlet也有init和destroy这两个生命周期函数以及service方法,只是httpservlet还有两个重要的dopost方法和doget方法,并用他们来支持http的post和get方法,就是说如果要支持http的get方法,就要覆盖doget方法,如果要支持http的post方法,就要覆盖dopost方法。而get方法和post方法的主要区别在于:

  4. post方法的数据传递方式比较安全,不会将传递的信息显示在浏览器的网址后,而get方法则会将传递的信息显示在浏览器的网址后,

例如用get方法的浏览器网址:http://127.0.0.1:8080/response.jsp?name=myself;

而用post方法则为:http://127.0.0.1:8080/response.jsp;这种区别当用在密码传输时就显的更为重要。

二、HttpServletRequest,HttpServletResponse

1、介绍

HttpServletRequest对象代表客户端的请求,当客户端通过HTTP协议访问服务器时,HTTP请求头中的所有信息都封装在这个对象中,通过这个对象提供的方法,可以获得客户端请求的所有信息。

2、Request常用方法

获得客户机信息

getRequestURL方法返回客户端发出请求时的完整URL。
getRequestURI方法返回请求行中的资源名部分。
getQueryString 方法返回请求行中的参数部分。
getPathInfo方法返回请求URL中的额外路径信息。额外路径信息是请求URL中的位于Servlet的路径之后和查询参数之前的内容,它以“/”开头。
getRemoteAddr方法返回发出请求的客户机的IP地址。
getRemoteHost方法返回发出请求的客户机的完整主机名。
getRemotePort方法返回客户机所使用的网络端口号。
getLocalAddr方法返回WEB服务器的IP地址。
getLocalName方法返回WEB服务器的主机名。

== 范例:通过request对象获取客户端请求信息==

package gacl.request.study;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
 * @author gacl
 * 通过request对象获取客户端请求信息
 */
public class RequestDemo01 extends HttpServlet {

    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        /**
         * 1.获得客户机信息
         */
        String requestUrl = request.getRequestURL().toString();//得到请求的URL地址
        String requestUri = request.getRequestURI();//得到请求的资源
        String queryString = request.getQueryString();//得到请求的URL地址中附带的参数
        String remoteAddr = request.getRemoteAddr();//得到来访者的IP地址
        String remoteHost = request.getRemoteHost();
        int remotePort = request.getRemotePort();
        String remoteUser = request.getRemoteUser();
        String method = request.getMethod();//得到请求URL地址时使用的方法
        String pathInfo = request.getPathInfo();
        String localAddr = request.getLocalAddr();//获取WEB服务器的IP地址
        String localName = request.getLocalName();//获取WEB服务器的主机名
        response.setCharacterEncoding("UTF-8");//设置将字符以"UTF-8"编码输出到客户端浏览器
        //通过设置响应头控制浏览器以UTF-8的编码显示数据,如果不加这句话,那么浏览器显示的将是乱码
        response.setHeader("content-type", "text/html;charset=UTF-8");
        PrintWriter out = response.getWriter();
        out.write("获取到的客户机信息如下:");
        out.write("<hr/>");
        out.write("请求的URL地址:"+requestUrl);
        out.write("<br/>");
        out.write("请求的资源:"+requestUri);
        out.write("<br/>");
        out.write("请求的URL地址中附带的参数:"+queryString);
        out.write("<br/>");
        out.write("来访者的IP地址:"+remoteAddr);
        out.write("<br/>");
        out.write("来访者的主机名:"+remoteHost);
        out.write("<br/>");
        out.write("使用的端口号:"+remotePort);
        out.write("<br/>");
        out.write("remoteUser:"+remoteUser);
        out.write("<br/>");
        out.write("请求使用的方法:"+method);
        out.write("<br/>");
        out.write("pathInfo:"+pathInfo);
        out.write("<br/>");
        out.write("localAddr:"+localAddr);
        out.write("<br/>");
        out.write("localName:"+localName);
    }

    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        doGet(request, response);
    }

}

猜你喜欢

转载自blog.csdn.net/qq_40036754/article/details/84936916