一个简单servlet容器
一个简单servlet容器
2.1 javax.servlet.Servlet接口
- Servlet编程需要使用javax.servlet和javax.servlet.http两个包下的接口和类
- 在所有的类中javax.servlet.Servlet接口是最重要的。所有的servlet程序都必须实现该接口或继承实现了该接口的类
- tomcat8中该接口如下:
package javax.servlet;
import java.io.IOException;
public interface Servlet {
public void init(ServletConfig config) throws ServletException;
public ServletConfig getServletConfig();
public void service(ServletRequest req, ServletResponse res)
throws ServletException, IOException;
public String getServletInfo();
public void destroy();
}
- 在Servlet接口中,init()、service()和destroy()方法是和servlet生命周期相关的方法。当实例化某个servlet类后,servlet容器就会调用其init()方法进行初始化。servlet容器只会调用该方法一次,调用后则可以执行service()方法了。
- 在servlet接收任何请求之前,必须是经过初始化的。该方法可以进行覆盖,自定义初始化。
- 当servlet的一个客户端请求到达后,servlet容器就调用相应的servlet的service方法,并将 javax.servlet.ServletRequest对象和javax.servlet.ServletResponse对象作为参数传入。
- ServletRequest对象包含客户端的HTTP请求信息,ServletResponse对象则封装servlet的响应信息。
- 在整个servlet周期内,service会被多次调用。
- 在将servlet容器从服务中移除之前,servlet容器会调用servlet实例的destory方法。
- 使用PrimitiveServlet来测试servlet容器应用程序
import javax.servlet.*;
import java.io.IOException;
import java.io.PrintWriter; public class PrimitiveServlet implements Servlet { public void init(ServletConfig config) throws ServletException {
System.out.println("init");
} public void service(ServletRequest request, ServletResponse response)
throws ServletException, IOException {
System.out.println("from service");
PrintWriter out = response.getWriter();
out.println("Hello. Roses are red.");
out.print("Violets are blue.");
} public void destroy() {
System.out.println("destroy");
} public String getServletInfo() {
return null;
}
public ServletConfig getServletConfig() {
return null;
}
}
2.2应用程序1
- 对一个Servlet的每个HTTP请求,一个功能齐全的servlet容器需要做到以下几点:
- 当第一次调用某个servlet时,要载入该servlet类,并调用其init方法
- 针对每一个request请求,创建一个javax.servlet.ServletRequest实例和一个javax.servlet.ServletResponse实例
- 调用该servlet的service方法,将ServletRequest对象和ServletResponse对象作为参数传入
- 当关闭servlet类时,调用destory方法
- 接下来建立一个Servlet容器,功能如下:
- 等待HTTP请求
- 创建一个ServletRequest对象和一个ServletResponse对象
- 若请求静态资源,则调用StaticResourceProcessor对象的process方法,传入上面的两个对象
- 若请求servlet,则载入相应的servlet类,调用其service方法。
- 类关系UML图如下:
- 基于Java的Servlet容器实现,需要调用Java提供的有关接口,比如javax.servlet.ServletRequest和javax.servlet.ServletResponse。
- 任何一个Servlet都需要实现Servlet接口或者继承实现该接口的类。
- 具体的请求过程以及类型如图:
- 代码示例:
if (request.getUri().startsWith("/servlet/")) {
ServletProcessor1 processor = new ServletProcessor1();
processor.process(request, response);
}
else {
StaticResourceProcessor processor = new StaticResourceProcessor();
processor.process(request, response);
}
在上面代码中可以看出对于静态资源使用StaticResourceProcessor容器,对于动态Servlet资源使用ServletProcessor1容器
package ex02.pyrmont;
public class ServletProcessor1 {
public void process(Request request, Response response) {
String uri = request.getUri();
String servletName = uri.substring(uri.lastIndexOf("/") + 1);
URLClassLoader loader = null; try {
// create a URLClassLoader
URL[] urls = new URL[1];
URLStreamHandler streamHandler = null;
File classPath = new File(Constants.WEB_ROOT);
// the forming of repository is taken from the createClassLoader method in
// org.apache.catalina.startup.ClassLoaderFactory
String repository = (new URL("file", null, classPath.getCanonicalPath() + File.separator)).toString() ;
// the code for forming the URL is taken from the addRepository method in
// org.apache.catalina.loader.StandardClassLoader class.
urls[0] = new URL(null, repository, streamHandler);
loader = new URLClassLoader(urls);
}
catch (IOException e) {
System.out.println(e.toString() );
}
Class myClass = null;
try {
myClass = loader.loadClass(servletName);
}
catch (ClassNotFoundException e) {
System.out.println(e.toString());
} Servlet servlet = null; try {
servlet = (Servlet) myClass.newInstance();
servlet.service((ServletRequest) request, (ServletResponse) response);
}
catch (Exception e) {
System.out.println(e.toString());
}
catch (Throwable e) {
System.out.println(e.toString());
} }
}
上面代码通过newInstance创建了一个Servlet的实例,并调用了service方法,并传入参数request和response。但是该参数是向上转型的。
这通常是不安全的,因为外部人员可以将其向下转型为Request的对象,就可以调用其方法.解决方法是创建Request和Response的外观类(外观类和原类实现同一个接口,在外观类中创建私有接口对象用原类进行赋值即可)。而在调用接口对象时使用外观类就不会导致原类的方法泄露
示例如下:
package ex02.pyrmont;
public class RequestFacade implements ServletRequest { private ServletRequest request = null; public RequestFacade(Request request) {
this.request = request;
} /* implementation of the ServletRequest*/
...
}
package ex02.pyrmont; public class Request implements ServletRequest { private InputStream input;
private String uri; public Request(InputStream input) {
this.input = input;
} public String getUri() {
return uri;
} private String parseUri(String requestString) {
int index1, index2;
index1 = requestString.indexOf(' ');
if (index1 != -1) {
index2 = requestString.indexOf(' ', index1 + 1);
if (index2 > index1)
return requestString.substring(index1 + 1, index2);
}
return null;
} public void parse() {
// Read a set of characters from the socket
StringBuffer request = new StringBuffer(2048);
int i;
byte[] buffer = new byte[2048];
try {
i = input.read(buffer);
}
catch (IOException e) {
e.printStackTrace();
i = -1;
}
for (int j=0; j<i; j++) {
request.append((char) buffer[j]);
}
System.out.print(request.toString());
uri = parseUri(request.toString());
} /* implementation of the ServletRequest*/
}
这样在上面service方法中使用RequestFacade类的实例向上转型就不会出现问题了。
运行结果如下:
一个简单servlet容器的更多相关文章
- 理解与模拟一个简单servlet容器
servlet接口 使用servlet编程需要实现或者继承实现了javax.servlet.Servlet接口的类,其中定义了5个签名方法: public void init(ServletConfi ...
- Tomcat详解系列(1) - 如何设计一个简单的web容器
Tomcat - 如何设计一个简单的web容器 在学习Tomcat前,很多人先入为主的对它的认知是巨复杂的:所以第一步,在学习它之前,要打破这种观念,我们通过学习如何设计一个最基本的web容器来看它需 ...
- 从零构建一个简单的 Python Web框架
为什么你想要自己构建一个 web 框架呢?我想,原因有以下几点: 你有一个新奇的想法,觉得将会取代其他的框架 你想要获得一些名气 你遇到的问题很独特,以至于现有的框架不太合适 你对 web 框架是如何 ...
- java框架之SpringBoot(8)-嵌入式Servlet容器
前言 SpringBoot 默认使用的嵌入式 Servlet 容器为 Tomcat,通过依赖关系就可以看到: 问题: 如何定制和修改 Servlet 容器相关配置? SpringBoot 能否支持其它 ...
- 一个简单的Servlet容器实现
上篇写了一个简单的Java web服务器实现,只能处理一些静态资源的请求,本篇文章实现的Servlet容器基于前面的服务器做了个小改造,增加了Servlet请求的处理. 程序执行步骤 创建一个Serv ...
- how tomcat works 读书笔记(二)----------一个简单的servlet容器
app1 (建议读者在看本章之前,先看how tomcat works 读书笔记(一)----------一个简单的web服务器 http://blog.csdn.net/dlf123321/arti ...
- 一个简单的servlet容器
[0]README 0.1)本文部分文字转自 “深入剖析Tomcat”,旨在学习 一个简单的servlet容器 的基础知识: 0.2)for complete source code, pleas ...
- Tomcat学习笔记(二)—— 一个简单的Servlet容器
1.简介:Servlet编程是通过javax.Servlet和javax.servlet.http这两个包的类和接口实现的,其中javax.servlet.Servlet接口至关重要,所有的Servl ...
- 使用Servlet和JSP实现一个简单的Web聊天室系统
1 问题描述 利用Java EE相关技术实现一个简单的Web聊天室系统,具体要求如下. (1)编写一个登录 ...
随机推荐
- 5. git-lab 项目操作
项目操作 一.给成员授权项目权限 之前我们是给组增加成员. 当有的项目需要给组下面的成员授权不一样的时候. 我们需要在项目里面给成员授权权限 点击管理区域 点这个项目 看下图,我们可以看到 现在这 ...
- 炫酷的CSS3响应式表单
原创YouTube@ Online Tutorials css代码: * { margin: 0; padding: 0; box-sizing: border-box; font-family: ' ...
- day70_10_16drf组件响应模块,异常模块和序列化模块。
一.解析模块 为什么要配置解析模块? 1)drf给我们通过了多种解析数据包方式的解析类. 2)我们可以通过配置来控制前台提交的哪些格式的数据后台在解析,哪些数据不解析. 3)全局配置就是针对每一个视图 ...
- [C10] 异常检测(Anomaly Detection)
异常检测(Anomaly Detection) 问题的动机 (Problem Motivation) 异常检测(Anomaly detection)问题是机器学习算法中的一个常见应用.这种算法的有趣之 ...
- arduino (2) 浊度传感器
z https://detail.tmall.com/item.htm?id=601391726801&spm=a1z09.2.0.0.60082e8dMiX0LM&_u=e1qf7b ...
- INVERSION包
1.安装该包 if (!requireNamespace("BiocManager", quietly = TRUE))install.packages("BiocMan ...
- [LOJ 6432][PKUSC 2018]真实排名
[LOJ 6432][PKUSC 2018]真实排名 题意 给定 \(n\) 个选手的成绩, 选中其中 \(k\) 个使他们的成绩翻倍. 对于每个选手回答有多少种方案使得他的排名不发生变化. \(n\ ...
- keras和tensorflow搭建DNN、CNN、RNN手写数字识别
MNIST手写数字集 MNIST是一个由美国由美国邮政系统开发的手写数字识别数据集.手写内容是0~9,一共有60000个图片样本,我们可以到MNIST官网免费下载,总共4个.gz后缀的压缩文件,该文件 ...
- Nginx的性能优化方案
nginx的优化 . gzip压缩优化 . expires缓存有还 . 网络IO事件模型优化 . 隐藏软件名称和版本号 . 防盗链优化 . 禁止恶意域名解析 . 禁止通过IP地址访问网站 . HTTP ...
- 快速缓存刷新CDN节点的方法
缓存刷新方式有 URL 刷新.目录刷新和 URL 预热.URL 刷新是以文件为单位进行缓存刷新.目录刷新是以目录为单位,将目录下的所有文件进行缓存刷新.URL 预热是以文件为单位进行资源预热. 刷新后 ...