Servlet规范定义了一个API标准,这一标准的实现通常称为Servlet容器,比如开源的Tomcat、JBoss。容器提供一些基本的服务,使得开发者专注于业务领域。当一个请求到达时,监听在相应端口的容器会接受该请求,将请求的信息转化成一个ServletRequest对象,同时创建一个ServletResponse对象,我们在开发Servlet应用时,就可以直接使用这两个对象(容器传递到service()方法的参数)。因此,所谓容器(服务器、中间件等),就是提供一些底层的、业务无关的基本功能,为真正的Servlet提供服务。
例如,在Http请求到达的时候,请求是一个标准的Http请求,包括请求方法、URI、协议、客户端环境参数、请求参数等等。容器通过Socket接收这些信息,并将其转化成特定于Servlet的ServletRequest对象。我们无需关注底层的网络Socket细节就可以直接使用。同样,容器也创建好一个ServletResponse,它帮我们设置了一些返回操作的基本内容,比如用于写入的OutputStream,容器已经把这个输出流定向到客户端的机器上,因此我们操作ServletResponse对象时,是在容器提供的服务至上的。
容器还负责根据请求的信息找到对应的Servlet,传递Request和Response参数,调用Servlet的service方法,完成请求的响应。
接下来我们事先一个简单的、最基本的容器:
时序图如下:
下面给出源码:
SimpleContainer:
package simpleserver.simplecontainer;
import static simpleserver.simplecontainer.Constant.HOSTNAME;
import static simpleserver.simplecontainer.Constant.LOG_BAKC;
import static simpleserver.simplecontainer.Constant.PORT;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
public class SimpleContainer {
private boolean shutdown = false;
private Log log = LogFactory.getLog(this.getClass());
public static void main(String[] args) {
SimpleContainer server = new SimpleContainer();
server.start();
}
private void start() {
ServerSocket serverSocket = null;
try {
serverSocket = new ServerSocket(PORT, LOG_BAKC,
InetAddress.getByName(HOSTNAME));
} catch (IOException e) {
System.out.println("Server starts failed");
e.printStackTrace();
System.exit(1);
}
log.info("Server starts successfully.");
service(serverSocket);
}
private void service(ServerSocket serverSocket) {
while (!shutdown) {
try {
processRequest(serverSocket);
} catch (Exception e) {
e.printStackTrace();
}
}
}
private void processRequest(ServerSocket serverSocket) throws IOException {
log.info("waitting for incoming request ... ");
Socket socket = serverSocket.accept();
log.info("receive a request from "
+ socket.getRemoteSocketAddress().toString());
InputStream in = socket.getInputStream();
BaseRequest request = new BaseRequest(in);
log.info("Request Object ready!");
OutputStream out = socket.getOutputStream();
BaseResponse response = new BaseResponse(out);
ServletProcessor.processServletRequest(request, response);
socket.close();
}
}
BaseRequest:只给出部分实现,其他都是ServletRequest的空实现
package simpleserver.simplecontainer;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.util.Enumeration;
import java.util.Locale;
import java.util.Map;
import javax.servlet.AsyncContext;
import javax.servlet.DispatcherType;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletContext;
import javax.servlet.ServletInputStream;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
public class BaseRequest implements ServletRequest {
private InputStream inputStream;
private String uri;
private StringBuffer requestContentBuffer = new StringBuffer(2048);
public BaseRequest(InputStream in) {
this.inputStream = in;
prepareContent();
parseAndSetUri();
}
private void prepareContent() {
byte[] buffer = new byte[2048];
int i = -1;
try {
i = inputStream.read(buffer);
} catch (IOException e) {
e.printStackTrace();
}
for (int k = 0; k < i; k++) {
requestContentBuffer.append((char) buffer[k]);
}
System.out.println(requestContentBuffer.toString());
}
private void parseAndSetUri() {
String requestString = requestContentBuffer.toString();
int index1 = requestString.indexOf(' ');
int index2 = -1;
if (index1 != -1) {
index2 = requestString.indexOf(' ', index1 + 1);
}
this.uri = (index2 > index1) ? requestString.substring(index1 + 1,
index2) : null;
}
public String getUri() {
return this.uri;
}
......
}
BaseResponse:
public class BaseResponse implements ServletResponse {
private OutputStream outputStream;
public BaseResponse(OutputStream out) {
this.outputStream = out;
}
......
}
ServletProcessor:
package simpleserver.simplecontainer;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.net.URLClassLoader;
import java.net.URLStreamHandler;
import javax.servlet.Servlet;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
public class ServletProcessor {
private static Log log = LogFactory.getLog(ServletProcessor.class);
public static void processServletRequest(BaseRequest request,
BaseResponse response) {
String uri = request.getUri();
String servletName = MappingHelper.resolve(uri);
log.info("Processing servlet: " + servletName);
Servlet servlet = loadServlet(servletName);
callService(servlet, request, response);
}
private static URLClassLoader createUrlClassLoader() {
URLClassLoader loader = null;
try {
URL[] urls = new URL[1];
URLStreamHandler streamHandler = null;
File classPath = new File(Constant.RESOURCE_ROOT);
// org.apache.catalina.startup.ClassLoaderFactory
String repository = (new URL("file", null,
classPath.getCanonicalPath() + File.separator)).toString();
urls[0] = new URL(null, repository, streamHandler);
loader = new URLClassLoader(urls);
} catch (IOException e) {
e.printStackTrace();
}
return loader;
}
private static Servlet loadServlet(String servletName) {
URLClassLoader loader = createUrlClassLoader();
Servlet servlet = null;
try {
@SuppressWarnings("unchecked")
Class<Servlet> servletClass = (Class<Servlet>) loader
.loadClass(servletName);
servlet = (Servlet) servletClass.newInstance();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
return servlet;
}
private static void callService(Servlet servlet, ServletRequest request,
ServletResponse response) {
try {
servlet.service(request, response);
} catch (ServletException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
MappingHeler:
package simpleserver.simplecontainer;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Properties;
public class MappingHelper {
public static Properties requestMapping;
static {
requestMapping = new Properties();
try {
requestMapping.load(new FileInputStream(Constant.MAPPING_FILE));
} catch (IOException e) {
e.printStackTrace();
}
}
public static String resolve(String requestPath) {
return requestMapping.getProperty(requestPath);
}
}
该类负责请求URL到Servlet的映射,读入一个属性文件,如下:
/servlet/PrimitiveServlet=simpleserver.simplecontainer.webapp.PrimitiveServlet
/servlet/Test=simpleserver.simplecontainer.webapp.TestServlet
另外还有一个帮助类定义常量。
欢迎交流。
分享到:
相关推荐
本主题将深入探讨“一个简单的Servlet容器”的实现,参考自《深入剖析Tomcat》这本书的第二章。 Servlet容器的主要职责是接收HTTP请求,然后调用相应的Servlet来处理这些请求,并将Servlet的响应返回给客户端。在...
这里,我们创建了一个简单的HTML响应,并将其写入到输出流中。实际的Servlet容器会根据请求的URL和方法调用相应的Servlet实例,并让Servlet生成响应内容。 此外,我们注意到有一个`SHUTDOWN_COMMAND`常量,这可能是...
Servlet容器模型的另一个关键特性是多线程模型。由于HTTP请求是无状态的,Servlet容器通常为每个请求创建一个新的线程来调用Servlet的`service()`方法,以提高并发性能。这意味着Servlet必须是线程安全的,避免在多...
文章中提到的`PrimitiveServlet`是一个简单的Servlet示例,它实现了`javax.servlet.Servlet`接口。具体来看: 1. **`init(ServletConfig config)`**:此方法在Servlet首次初始化时被调用,用于完成初始化操作。 2. ...
2. 编写一个实现了EmbeddedServletContainerCustomizer接口的Bean,通过编程方式设置Servlet容器的配置项,如端口号、上下文路径及会话超时时间。 注册Servlet三大组件(Servlet、Filter和Listener)是构建Web应用...
3. **Resin**:由Caucho公司开发,也是一个强大的Servlet容器,特别适合处理高并发请求。Resin的部署方式也包括将Web应用的目录结构放入其指定的webapps目录。 在Servlet容器中,Servlet生命周期包括加载、初始化、...
首先,Servlet容器,如Tomcat,是一个独立的产品,它遵循Java EE(J2EE)规范中的Servlet API,为Servlet提供了一个标准化的执行环境。Servlet与Servlet容器的关系类似于枪和子弹,Servlet容器为Servlet提供了运行...
下面是一个简单的Servlet示例,即`PrimitiveServlet`,它实现了Servlet接口并打印出调用的方法名: ```java public class PrimitiveServlet implements Servlet { public void init(ServletConfig config) throws ...
在上述Java web服务器的基础上实现Servlet容器,主要是扩展了对Servlet请求的处理能力。Servlet容器是Java Web应用的核心组件,它负责管理和调用Servlet实例,处理HTTP请求并生成响应。这里我们先了解Servlet的基本...
在本项目中,"Servlet实现简单购物车"是指利用Servlet技术来构建一个基础的在线购物车系统。这个系统可能包括添加商品到购物车、查看购物车内容、修改商品数量以及清空购物车等功能。 首先,我们需要了解Servlet的...
在这个例子中,我们将探讨如何利用Servlet监听器在系统启动时创建一个自定义容器。 首先,我们需要了解Servlet监听器的概念。Servlet监听器是实现了Java Servlet API中特定接口的类,这些接口定义了对Web应用生命...
总的来说,Jetty 9 Servlet容器以其轻量级、高效和灵活的特性,成为了Java Web开发中一个值得信赖的选择。无论是小型项目还是大型企业级应用,都能从中受益。通过深入理解和熟练掌握Jetty 9,开发者可以构建出更强大...
"JAVA WEB中Servlet和Servlet容器的区别" 在 Java Web 开发中,Servlet 和 Servlet 容器是两个非常重要的概念,但是很多人对它们的区别却不甚了解。本文将对 Servlet 和 Servlet 容器进行详细的介绍,并阐述它们...
tomcatTomcat(全称为Apache Tomcat)是一个开源的Java Servlet容器,由Apache软件基金会下属的Jakarta项目开发。Tomcat实现了Java Servlet、JavaServer Pages(JSP)和Java Expression Language(EL)等Java技术,...
1、编写一个Java类,实现servlet接口。 2、把开发好的Java类部署到web服务器中。 按照一种约定俗成的称呼习惯,通常我们也把实现了servlet接口的java程序,称之为Servlet 二、Servlet的运行过程 Servlet程序...
Jetty 是一个用 Java 实现、开源、基于标准的,并且具有丰富功能的 Http 服务器和 Web 容器,可以免费的用于商业行为。Jetty 这个项目成立于 1995 年,现在已经有非常多的成功产品基于 Jetty,比如 Apache Geromino...
总的来说,"servlet实现的一个简单web程序"是一个学习和实践Servlet技术的好项目,涵盖了Web开发中基础且重要的方面。通过这样的项目,开发者可以深入理解Servlet的工作原理,以及如何利用Servlet构建交互式的Web...
总结来说,这个简单的Servlet示例展示了如何创建一个基础的Servlet,处理请求并返回响应。通过配置`web.xml`,我们可以控制Servlet如何在Web应用中被加载和映射。这对于初学者理解Servlet的工作原理和生命周期至关...