Servlet技术(上)

Posted 9761滴

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Servlet技术(上)相关的知识,希望对你有一定的参考价值。

1. Servlet API

Servlet API 文档地址

Servlet API的源文件在apache-tomcat安装路径下的/lib/servlet-api.jar中

 

Servlet API主要由两个Java包组成:javax.servlet和javax.servlet.http

其中javax.servlet包中定义了Servlet接口

 

 

 

servlet接口

GenericServlet抽象类

HttpServlet抽象类

ServletRequest接口

HttpServletRequest接口

ServletResponse接口

HttpServletResponse接口

ServletConfig接口

ServletContext接口

 

Servlet接口

供Servlet容器调用的方法:

init(ServletConfig config) :初始化Servlet对象,容器创建好Servlet对象后,就调用该方法

service(ServletRequest req,ServletResponse res) :负责响应客户的请求,为客户提供相应的服务。容器接收到客户端要访问的特定Servlet对象的请求时,就会调用改方法

destory() :负责释放Servlet对象占用的资源,当Servlet对象结束生命周期时,容器会调用此方法

供Java Web应用中的程序代码访问的方法:

getServletConfig() : 返回一个ServletConfig对象,改对象包含了Servlet的初始化参数信息

getServletInfo() : 返回一个字符串,该字符串中包含了Servlet的创建者、版本和版权等信息

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//

package javax.servlet;

import java.io.IOException;

public interface Servlet {
   void init(ServletConfig var1) throws ServletException;

   ServletConfig getServletConfig();

   void service(ServletRequest var1, ServletResponse var2) throws ServletException, IOException;

   String getServletInfo();

   void destroy();
}

 

GenericServlet抽象类 (运用了装饰设计模式)

该类提供了Servlet接口的通用实现,还实现了ServletConfig接口和Serializable接口,并且该抽象类有一个ServletConfig类型的私有实例变量config,从而使得GenericServlet抽象类与ServletConfig对象关联

GenericServlet类没有实现service()方法,service()方法是该类中唯一的抽象方法,GenericServlet类的子类必须实现该方法。

GenericSeervlet类实现类ServletConfig接口中的所有方法,因此GenericServlet及其子类可以直接调用在ServletConfig接口中定义的getServletContext()、getInitParameter()、getInitParameterNames()等方法

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//

package javax.servlet;

import java.io.IOException;
import java.io.Serializable;
import java.util.Enumeration;

public abstract class GenericServlet implements Servlet, ServletConfig, Serializable {
   private static final long serialVersionUID = 1L;
   private transient ServletConfig config;

   public GenericServlet() {
  }

   public void destroy() {
  }

   public String getInitParameter(String name) {
       return this.getServletConfig().getInitParameter(name);
  }

   public Enumeration<String> getInitParameterNames() {
       return this.getServletConfig().getInitParameterNames();
  }

   public ServletConfig getServletConfig() {
       return this.config;
  }

   public ServletContext getServletContext() {
       return this.getServletConfig().getServletContext();
  }

   public String getServletInfo() {
       return "";
  }

   public void init(ServletConfig config) throws ServletException {
       this.config = config;
       this.init();
  }

   public void init() throws ServletException {
  }

   public void log(String message) {
       this.getServletContext().log(this.getServletName() + ": " + message);
  }

   public void log(String message, Throwable t) {
       this.getServletContext().log(this.getServletName() + ": " + message, t);
  }

   public abstract void service(ServletRequest var1, ServletResponse var2) throws ServletException, IOException;

   public String getServletName() {
       return this.config.getServletName();
  }
}

 

HttpServlet抽象类

该类是GenericServlet抽象类的子类,该类为Servlet接口提供了与HTTP协议相关的通用实现,因此在开发基于HTTP协议的Java Web应用的时候,自定义的Servlet类一般都继承该类而不是GenericServlet类

HttpServlet类实现类service()方法,在该service(ServletRequest req,ServletResponse resp)方法中,将参数ServletRequest和ServletResponse转换成HttpServletRequset和HttpRequestResponse, 然后调用重载的service(HttpServletRequest req,HttpServletResponse resp)方法。

在service(HttpServletRequest req,HttpServletResponse resp)方法中,根据req获取客户端的请求方法(GET、POST、PUT、DELETE等),对于不同的请求方法,调用相应的doGet、doPost等方法,req和resp两个参数也会传给doGet或者doPost方法。

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//

package javax.servlet.http;

import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
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("javax.servlet.http.LocalStrings");

   public HttpServlet() {
  }

   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(405, msg);
      } else {
           resp.sendError(400, msg);
      }

  }

   protected long getLastModified(HttpServletRequest req) {
       return -1L;
  }

   protected void doHead(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
       if (DispatcherType.INCLUDE.equals(req.getDispatcherType())) {
           this.doGet(req, resp);
      } else {
           NoBodyResponse response = new NoBodyResponse(resp);
           this.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(405, msg);
      } else {
           resp.sendError(400, 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(405, msg);
      } else {
           resp.sendError(400, 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(405, msg);
      } else {
           resp.sendError(400, msg);
      }

  }

   private static Method[] getAllDeclaredMethods(Class<?> c) {
       if (c.equals(HttpServlet.class)) {
           return null;
      } else {
           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;
       Class clazz = null;

       try {
           clazz = Class.forName("org.apache.catalina.connector.RequestFacade");
           Method getAllowTrace = clazz.getMethod("getAllowTrace", (Class[])null);
           ALLOW_TRACE = (Boolean)getAllowTrace.invoke(req, (Object[])null);
      } catch (NoSuchMethodException | SecurityException | IllegalAccessException | IllegalArgumentException | InvocationTargetException | ClassNotFoundException var14) {
      }

       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 = "GET";
      }

       if (ALLOW_HEAD) {
           if (allow == null) {
               allow = "HEAD";
          } else {
               allow = allow + ", HEAD";
          }
      }

       if (ALLOW_POST) {
           if (allow == null) {
               allow = "POST";
          } else {
               allow = allow + ", POST";
          }
      }

       if (ALLOW_PUT) {
           if (allow == null) {
               allow = "PUT";
          } else {
               allow = allow + ", PUT";
          }
      }

       if (ALLOW_DELETE) {
           if (allow == null) {
               allow = "DELETE";
          } else {
               allow = allow + ", DELETE";
          }
      }

       if (ALLOW_TRACE) {
           if (allow == null) {
               allow = "TRACE";
          } else {
               allow = allow + ", TRACE";
          }
      }

       if (ALLOW_OPTIONS) {
           if (allow == null) {
               allow = "OPTIONS";
          } else {
               allow = allow + ", OPTIONS";
          }
      }

       resp.setHeader("Allow", allow);
  }

   protected void doTrace(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
       String CRLF = "\\r\\n";
       StringBuilder buffer = (new StringBuilder("TRACE ")).append(req.getRequestURI()).append(" ").append(req.getProtocol());
       Enumeration reqHeaderEnum = req.getHeaderNames();

       while(reqHeaderEnum.hasMoreElements()) {
           String headerName = (String)reqHeaderEnum.nextElement();
           buffer.append(CRLF).append(headerName).append(": ").append(req.getHeader(headerName));
      }

       buffer.append(CRLF);
       int responseLength = buffer.length();
       resp.setContentType("message/http");
       resp.setContentLength(responseLength);
       ServletOutputStream out = resp.getOutputStream();
       out.print(buffer.toString());
       out.close();
  }

   protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
       String method = req.getMethod();
       long lastModified;
       if (method.equals("GET")) {
           lastModified = this.getLastModified(req);
           if (lastModified == -1L) {
               this.doGet(req, resp);
          } else {
               long ifModifiedSince;
               try {
                   ifModifiedSince = req.getDateHeader("If-Modified-Since");
              } catch (IllegalArgumentException var9) {
                   ifModifiedSince = -1L;
              }

               if (ifModifiedSince < lastModified / 1000L * 1000L) {
                   this.maybeSetLastModified(resp, lastModified);
                   this.doGet(req, resp);
              } else {
                   resp.setStatus(304);
              }
          }
      } else if (method.equals("HEAD")) {
           lastModified = this.getLastModified(req);
           this.maybeSetLastModified(resp, lastModified);
           this.doHead(req, resp);
      } else if (method.equals("POST")) {
           this.doPost(req, resp);
      } else if (method.equals("PUT")) {
           this.doPut(req, resp);
      } else if (method.equals("DELETE")) {
           this.doDelete(req, resp);
      } else if (method.equals("OPTIONS")) {
           this.doOptions(req, resp);
      } else if (method.equals("TRACE")) {
           this.doTrace(req, resp);
      } else {
           String errMsg = lStrings.getString("http.method_not_implemented");
           Object[] errArgs = new Object[]{method};
           errMsg = MessageFormat.format(errMsg, errArgs);
           resp.sendError(501, errMsg);
      }

  }

   private void maybeSetLastModified(HttpServletResponse resp, long lastModified) {
       if (!resp.containsHeader("Last-Modified")) {
           if (lastModified >= 0L) {
               resp.setDateHeader("Last-Modified", lastModified);
          }

      }
  }

   public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
       HttpServletRequest request;
       HttpServletResponse response;
       try {
           request = (HttpServletRequest)req;
           response = (HttpServletResponse)res;
      } catch (ClassCastException var6) {
           throw new ServletException(lStrings.getString("http.non_http"));
      }

       this.service(request, response);
  }
}
<

以上是关于Servlet技术(上)的主要内容,如果未能解决你的问题,请参考以下文章

jsp页面被tomcat引擎运行的时候组装成java片段,但是这些java片段怎么没有main方法作为程序的入口啊?

Java基础——JSP

sun公司当时为什么要发明jsp技术?jsp技术有什么意义?

JSP基础学习

Java web中使用到的技术

servlet