-
Tomcat和Servlet
- Tomcat是一个轻量级的应用服务器。能够解析JAVA代码生成.class.文件,同时j将JAVA转换成相应的HTML代码,适用于解析JSP文件。Tomcat在实际应用中又被称为容器。
- Servlet是JAVAEE的一部分,是一个普通的JAVA类,但能够处理HTTP的请求和响应过程,又被成为服务器连接器,常使用于数据操作层。
相异性
1.Tomcat和Servlet都能处理HTTP的请求和响应过程,这是因为两者都支持HTTP协议。而HTTP协议是基于TCP协议上的,再者TCP协议是基于JAVA Socket类上的,从本质上说Tomcat和Servelt是对JAVA io流的不同程度的封装和应用。
2.Tomcat有九大内置对象处理请求和响应还有配置信息,Servlet也有“九大对象”处理请求和响应还有配置信息。它们一一对象。原因其实是Tomcat实现了Servlet接口和ServeltConfig接口,但Tomcat中九大内置对象不用实例化就能直接使用,而在Servlet中需要实例化“九大对象”才能使用,其原因为容器(Tomcat)在底层对九大内置对象进行了实例化。由于Tomcat实现了Serclet接口因此“九大内置对象”和“九大对象是一一对应的:
- request -->ServletRequest request = new HttpServletRequest();
- responce -->ServletResponse responce = new HttpServletResponce();
- session -->HttpSession session = new request.getSession();
- application -->ServletContext application = resquest.getServletContext()
- out -->PrintWriter out = respoce.getWriter();
- config -->ServletConfig config = this.getServletConfig()
- pageContext -->ServletContext context=this.getServletContext();
- page -->Object page=this
- exception
3.Tomecat和Servlet都需要配置依赖,其中Tomcat是Apache旗下的一个免费且开源的项目,可以在Apache官网自行下载。Servlet是JAVAEE的一部分,但为了轻量化JAVAEE而作为插件的方式安装并使用Servlet。
Tomcat的pom.xml配置
//诺存在build标签应将所有相应的插件依赖配置在其中
<build>
//可以包含多个依赖
<plugins>
//单个依赖
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<version>2.2</version>
<configuration>
<port>9090</port> //配置端口号
<path>/</path> //配置相对路径
<uriEncoding>UTF-8</uriEncoding>
</configuration>
</plugin>
</plugins>
</build>
Servlet的pom.xml配置
//可以包含多个依赖
<dependencies>
//单个依赖
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.0</version>
<scope>provided</scope>
</dependency>
</dependencies>
4.Tomcat和Servle都能t处理请求,请求包含:get、post、put、delete、options等,最常见的是get和post请求。其中get请求是绝大部分请求的默认请求方式,而post请求常见于form表单和json的数据传输。--Tomcat是在<%JAVA代码块%>小脚本中使用java语言处理请求、而Servlet中是通过相应的的方法处理请求,而Servlet是一个接口,无法实现方法,因此所有的请求实际上是后代实现处理的。
4.1 Servlet作为一个接口,其代表的是一个服务的生命周期。其中主要有3个方法:
4.1.1:void init(ServletConfig var1):初始化,由于一个服务可能是长时间的,对于需要中途进行一些初始化的内容构造函数是无法进行中途初始化的
4.1.2 void service(ServletRequest var1, ServletResponse var2):服务,可以处理所有请求,并响应。
4.1.3:void destroy():销毁,在服务结束或者容器死亡(Tomcat碟机或者关闭)(容器有很多,本文中直指Tomcat)后执行。由于服务关闭或者容器死亡是有过程的:即需要时间,因此在时间较短时有可能destroy()方法不会执行,因此不建议将一些流的关闭放在该方法中
Servlet接口源码
4.2 ServletConfig接口:一个完整的服务除了需要一个完整的生命周期外还需要提供相应的配置方便客户端访问,在JAVA中提供了ServletConfig接口,其作用为提供配置信息。注意,Servlet和ServletConfig时同级的接口
4.2.1 String getServletName();获取服务名
4.2.2 String getServletName();获取服务所在的上下文
4.2.3 String getInitParameter(String var1);获取在pom.xml的配置
ServletConfig接口源码
4.3 单一性原则:GenericServlet抽象类,在JAVA中始终秉持着单一性原则,从类方面看,接口、抽象类、普通类其被赋予的职能是不同。从继承和实现上来看,为了高可复用性而甘愿逐层继承。例如,GenericServlet抽象,只是实现了Servlet接口和ServletConfig接口,并没有进行方法的拓展,而是将拓展任务遗留给后代,而多个后代可以进行多种的拓展!
GenericServlet源码
//
// 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;
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 GenericServlet() {
}
public void destroy() {
}
public String getInitParameter(String name) {
ServletConfig sc = this.getServletConfig();
if (sc == null) {
throw new IllegalStateException(lStrings.getString("err.servlet_config_not_initialized"));
} else {
return sc.getInitParameter(name);
}
}
public Enumeration<String> getInitParameterNames() {
ServletConfig sc = this.getServletConfig();
if (sc == null) {
throw new IllegalStateException(lStrings.getString("err.servlet_config_not_initialized"));
} else {
return sc.getInitParameterNames();
}
}
public ServletConfig getServletConfig() {
return this.config;
}
public ServletContext getServletContext() {
ServletConfig sc = this.getServletConfig();
if (sc == null) {
throw new IllegalStateException(lStrings.getString("err.servlet_config_not_initialized"));
} else {
return sc.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 msg) {
this.getServletContext().log(this.getServletName() + ": " + msg);
}
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() {
ServletConfig sc = this.getServletConfig();
if (sc == null) {
throw new IllegalStateException(lStrings.getString("err.servlet_config_not_initialized"));
} else {
return sc.getServletName();
}
}
}
4.4 单一性原则:HttpServlet抽象类,HttpServlet继承了GenericServlet抽象类并在其原本的功能上进行了拓展
4.4.1 各种请求处理的方法:doGet()、doPost()、doHead()、doPut()等
4.4.2 实现继承的service();
4.4.3 重载service()方法;并调用继承的service();
HttpServlet源码
//
// 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.Method;
import java.text.MessageFormat;
import java.util.Enumeration;
import java.util.ResourceBundle;
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 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 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 {
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 Method[] getAllDeclaredMethods(Class<? extends HttpServlet> c) {
Class<?> clazz = c;
Method[] allMethods;
for(allMethods = null; !clazz.equals(HttpServlet.class); clazz = clazz.getSuperclass()) {
Method[] thisMethods = clazz.getDeclaredMethods();
if (allMethods != null && allMethods.length > 0) {
Method[] subClassMethods = allMethods;
allMethods = new Method[thisMethods.length + allMethods.length];
System.arraycopy(thisMethods, 0, allMethods, 0, thisMethods.length);
System.arraycopy(subClassMethods, 0, allMethods, thisMethods.length, subClassMethods.length);
} else {
allMethods = thisMethods;
}
}
return allMethods != null ? allMethods : new Method[0];
}
protected void doOptions(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
Method[] methods = this.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) {
String methodName = methods[i].getName();
if (methodName.equals("doGet")) {
ALLOW_GET = true;
ALLOW_HEAD = true;
} else if (methodName.equals("doPost")) {
ALLOW_POST = true;
} else if (methodName.equals("doPut")) {
ALLOW_PUT = true;
} else if (methodName.equals("doDelete")) {
ALLOW_DELETE = true;
}
}
StringBuilder allow = new StringBuilder();
if (ALLOW_GET) {
allow.append("GET");
}
if (ALLOW_HEAD) {
if (allow.length() > 0) {
allow.append(", ");
}
allow.append("HEAD");
}
if (ALLOW_POST) {
if (allow.length() > 0) {
allow.append(", ");
}
allow.append("POST");
}
if (ALLOW_PUT) {
if (allow.length() > 0) {
allow.append(", ");
}
allow.append("PUT");
}
if (ALLOW_DELETE) {
if (allow.length() > 0) {
allow.append(", ");
}
allow.append("DELETE");
}
if (ALLOW_TRACE) {
if (allow.length() > 0) {
allow.append(", ");
}
allow.append("TRACE");
}
if (ALLOW_OPTIONS) {
if (allow.length() > 0) {
allow.append(", ");
}
allow.append("OPTIONS");
}
resp.setHeader("Allow", allow.toString());
}
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());
}
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 = req.getDateHeader("If-Modified-Since");
if (ifModifiedSince < lastModified) {
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 {
if (req instanceof HttpServletRequest && res instanceof HttpServletResponse) {
HttpServletRequest request = (HttpServletRequest)req;
HttpServletResponse response = (HttpServletResponse)res;
this.service(request, response);
} else {
throw new ServletException("non-HTTP request or response");
}
}
}
5.自定义Servlet类,需要继承HttpServlet抽象类,重写service()方法或者其他的请求处理方法(doxxx)