---- 一个简单的servlet容器
上一篇讲到,我们的web容器已经可以读取静态资源,在这一篇中,我将建立一个简单的servlet容器,之所以简单,是因为有它的局限性,在后面我会总结,余下的问题我将在下一篇中一一解决。
本篇的第一个servlet容器主要完成如下功能:
* 等待HTTP请求。
* 构造一个ServletRequest对象和一个ServletResponse对象。
* 假如该请求需要一个静态资源的话,调用StaticResourceProcessor实例的process方法,同时传递ServletRequest和ServletResponse对象。
* 假如该请求需要一个servlet的话,加载servlet类并调用servlet的service方法,同时传递ServletRequest和ServletResponse对象。
注意:在这个servlet容器中,每一次servlet被请求的时候,servlet类都会被加载。
第一个servlet容器由以下类组成:
* HttpServer:容器的启动类,
* Request:实现了ServletRequest
* Response:实现了ServletResponse
* IProcessor:处理器接口,后期会演变为连接器
* StaticResourceProcessor:处理静态资源
* ServletProcessor:处理servlet调用
* MyClassLoader:继承自ClassLoader,用于加载class
* Constants:常量
上一篇已经对部分代码作了解释,接下来,我会对新增的代码作解释。
HttpServer类:
// create Response object
Response response = new Response(output);
response.setRequest(request);
if (request.getUri().startsWith("/servlet/")) { //暂时的实现,如果路径以 /servlet/ 开头则认为是调用servlet
IProcessor processor = new ServletProcessor();
processor.process(request, response);
}
else {
IProcessor processor = new StaticResourceProcessor();
processor.process(request, response);
}
// Close the socket
socket.close();
Response类:
public class Response implements ServletResponse {
//...省略ServletResponse的方法实现
public PrintWriter getWriter() throws IOException {
// autoflush is true, println() will flush,
// but print() will not.
writer = new PrintWriter(output, true);
return writer;
}
}
Request类:
public class Request implements ServletRequest {
//...省略ServletRequest的方法实现
//其余方法与上一篇一致
}
ServletProcessor类:
public class ServletProcessor implements IProcessor {
public void process(Request request, Response response) throws ServletException {
String uri = request.getUri();
String servletName = uri.substring(uri.lastIndexOf("/") + 1);
ClassLoader loader = new MyClassLoader(this.getClass().getClassLoader());
Class< ? > servletClass = null;
try {
servletClass = loader.loadClass(servletName);//加载class
}
catch (ClassNotFoundException e) {
throw new ServletException(e);
}
Servlet servlet = null;
if (null != servletClass) {
try {
servlet = (Servlet) servletClass.newInstance();
servlet.service(request, response);
}
catch (Exception e) {
throw new ServletException(e);
}
}
}
}
StaticResourceProcessor类:
public class StaticResourceProcessor implements IProcessor {
public void process(Request request, Response response) throws ServletException, IOException {
response.sendStaticResource();//直接读取资源
}
}
Constants类:
public class Constants {
/* WEB容器的根目录 */
public static final String WEB_ROOT = System.getProperty("user.dir") + File.separator + "WebContent";
/* class的根路径 */
public static final String CLASS_PATH = WEB_ROOT + File.separator + "WEB-INF" + File.separator + "classes";
}
MyClassLoader类:
public class MyClassLoader extends ClassLoader {
private String classPath = null;
protected MyClassLoader(ClassLoader parent) {
super(parent);
init();
}
private void init() {
classPath = Constants.CLASS_PATH;
}
/*
* 此方法应该被类加载器的实现重写,该实现按照委托模型来加载类
* @see java.lang.ClassLoader#findClass(java.lang.String)
*/
protected Class< ? > findClass(String className) throws ClassNotFoundException {
String classFileName = className.replace('.', '/') + ".class";
URL url = findResource(classFileName);
byte[] bytes = null;
if (null == url) {
throw new ClassNotFoundException("Can't find [" + className + "]");
}
else {
InputStream input = null;
try {
input = url.openStream();
if (input == null) {
throw new ClassNotFoundException("Can't load [" + className + "]");
}
else {
ByteArrayOutputStream baos = new ByteArrayOutputStream(10240);
byte[] buf = new byte[1024];
int bytesRead = 0;
while (bytesRead >= 0) {
baos.write(buf, 0, bytesRead);
bytesRead = input.read(buf);
}
bytes = baos.toByteArray();
}
}
catch (IOException e) {
throw new ClassNotFoundException(className, e);
}
finally {
try {
input.close();
}
catch (IOException ingore) {
}
}
}
Class< ? > theClass = defineClass(className, bytes, 0, bytes.length);
if (theClass == null)
throw new ClassFormatError();
return theClass;
}
/*
* 查找具有给定名称的资源。类加载器实现应该重写此方法,以指定从何处查找资源
* @see java.lang.ClassLoader#findResource(java.lang.String)
*/
protected URL findResource(String name) {
try {
URL url = super.findResource(name);
if (null != url) {
return url;
}
File path = new File(classPath);
if (path.isDirectory()) {
String pathRoot = path.getCanonicalPath();
StringBuffer sb = new StringBuffer(pathRoot);
sb.append(File.separator).append(name);
File resourceFile = new File(sb.toString());
if (resourceFile.exists()) {
System.out.println("Resource [" + name + "] was found, in [" + pathRoot + "]");
url = new URL("file:///" + resourceFile.getCanonicalPath());
}
}
if (null == url) {
return null;
}
else {
return url;
}
}
catch (IOException ex) {
return null;
}
}
}
测试servlet:MyPrimitiveServlet
public class MyPrimitiveServlet implements Servlet {
public void destroy() {}
public ServletConfig getServletConfig() {}
public String getServletInfo() {}
public void init(ServletConfig arg0) throws ServletException {}
public void service(ServletRequest request, ServletResponse response) throws ServletException, IOException {
System.out.println("from service");
PrintWriter out = response.getWriter();
out.println("Hello. MyServletContainer!");
out.print("Violets are blue.");
}
}
运行HttpServer,启动容器测试:
在浏览器中键入:http://localhost:8080/servlet/MyPrimitiveServlet
出现如下界面,则表明servlet调用成功:
第一个servlet容器的主要问题:
1、未实现servlet的生命周期
2、Response的getWriter()输出有问题
3、向上转换Request实例为javax.servlet.ServletRequest存在一定的安全性
在下一篇中,我将一一解决上述问题,且从下一篇开始,整体架构将以模块化组成。
- 大小: 41.1 KB
分享到:
相关推荐
基于QT和Html打造客户端容器的PPT,淘宝的。
cppweb同时也是一个跨平台的微服务开发框架,通过两个核心组件webrouter与webserver提供微服务系统中的接口路由网关、服务注册中心、业务服务容器、定时任务调度中心以及接口...,我们的目标不是实现一个最好cgi容器...
我们将逐步为不同行业用户量身打造行业模板,让您以最快捷的方式,最低的成本创建功能强大的企业网站。PHPWEB是您高效便捷的网站管理工具。PHPWEB可免费用于非商业用途,无需购买授权,直接安装使用。商业用户可以...
JSP+Servlet+Struts+Hibernate+Spring+Ajax》内容包括Web客户端技术、JSP/Servlet技术、Struts 2(*、类型转换、输入校验、上传和下载文件、Struts 2的各种标签、对 AJAX的支持等)、Spring(Ioc容器、装配Java Bean...
JSP+Servlet+Struts+Hibernate+Spring+Ajax》内容包括Web客户端技术、JSP/Servlet技术、Struts 2(*、类型转换、输入校验、上传和下载文件、Struts 2的各种标签、对 AJAX的支持等)、Spring(Ioc容器、装配Java Bean...
js+canvas打造常见的微信大转盘,本文件仅仅是前端代码,但是接口已经在代码中声明,适用于任何后端。暂时没有后端的话可以挂载到你的Apache或者iis等web容器,并且将.json文件添加到可访问列表。
js+canvas打造常见的微信大转盘,本文件仅仅是前端代码,但是接口已经在代码中声明,适用于任何后端。暂时没有后端的话可以挂载到你的Apache或者iis等web容器,并且将.json文件添加到可访问列表。
Zero Ecotope Framework 是一个基于 Vert.x 的中间件容器,它可以帮助软件开发人员在 Vert.x 中快速开发和实施,集中精力处理项目需求中的业务逻辑而忽略开发过程中的部分细节,项目起源于早期在 Vert.x 生态中缺少...
因此我自己根据go语言中文社区提供的资料,还有互联网企业架构设计中的常见组件分类, 共精心挑选了100多个开源项目(项目不限于在github开源的项目), 分成以下十几个大类。 这个项目可以理解为互联网IT人打造的...
这些模块主要被分如下图所示的核心容器、数据访问/集成,、Web、AOP(面向切面编程)、工具、消息和测试模块。 2、使用Spring框架能带来哪些好处? 下面列举了一些使用Spring框架带来的主要好处: ...
这些模块主要被分如下图所示的核心容器、数据访问/集成,、Web、AOP(面向切面编程)、工具、消息和测试模块。 更多信息:Spring 框架教程。 2、使用Spring框架能带来哪些好处? 下面列举了一些使用Spring框架带来的...
本书由旧金山HTML5用户组创建人联合另两位资深Web开发专家共同打造,为读者清晰解读了HTML5规范的缘由、发展和现状,全面展示了如何使用 WebSocket、Geolocation、Web Storage、Canvas及音频视频等前所未有的新...
本书由旧金山HTML5用户组创建人联合另两位资深Web开发专家共同打造,为读者清晰解读了HTML5规范的缘由、发展和现状,全面展示了如何使用 WebSocket、Geolocation、Web Storage、Canvas及音频视频等前所未有的新...
打造安全的容器云平台.pdf 敏捷开发中的安全实践.pdf 永无休止的业务逻辑“漏洞”.pdf 移动APP漏洞引发的思考.pdf 精简_SDL_在企业中的落地.pdf 线上应用业务安全.pdf 让我们做Web安全测试吧!.pdf 软件安全...
mall项目致力于打造一个完整的电商系统,采用现阶段流行技术实现。 项目文档 文档地址: : 备用地址: ://macrozheng.github.io/mall-learning 项目介绍 mall项目是一套电商系统,包括前台商城系统及后台管理系统,...
本书由旧金山HTML5用户组创建人联合另两位资深Web开发专家共同打造,为读者清晰解读了HTML5规范的缘由、发展和现状,全面展示了如何使用 WebSocket、Geolocation、Web Storage、Canvas及音频视频等前所未有的新...
本书由旧金山HTML5用户组创建人联合另两位资深Web开发专家共同打造,为读者清晰解读了HTML5规范的缘由、发展和现状,全面展示了如何使用 WebSocket、Geolocation、Web Storage、Canvas及音频视频等前所未有的新...
罗伟-蘑菇街基于容器的全生命周期 DevOps 运营平台建设 牛晓玲&景韵-转型的灯塔!DevOps 标准认证评估权威指南及案例解读 拍拍贷基础架构的DevOps演进之路-杨波-web 企业如何迈出 DevOps 第一步?-刘相 任发科:...
本书由旧金山HTML5用户组创建人联合另两位资深Web开发专家共同打造,为读者清晰解读了HTML5规范的缘由、发展和现状,全面展示了如何使用 WebSocket、Geolocation、Web Storage、Canvas及音频视频等前所未有的新...
本书由旧金山HTML5用户组创建人联合另两位资深Web开发专家共同打造,为读者清晰解读了HTML5规范的缘由、发展和现状,全面展示了如何使用 WebSocket、Geolocation、Web Storage、Canvas及音频视频等前所未有的新...