嵌入式tomcat分析,并手写加载springMvc
1. 简介
spring boot的嵌入式容器用起来很爽,所以博主也想搞一个类似可以不依赖外部容器的轮子.
虽然可以直接用maven的插件 tomcatX-maven-plugin 完成,但是高版本的更新太慢,所以有了以下的轮子.
2. tomcat结构介绍
为什么要先放这张图嗯,因为嵌入式的tomcat API 设计也是按照这个结构设计的.博主并不想看他的API文档,想靠这张图猜一下他的API如何使用.
3 maven坐标引入
<dependency><groupId>org.apache.tomcat.embed</groupId><artifactId>tomcat-embed-core</artifactId><version>8.5.34</version></dependency>
这里选择了热门的tomcat8.5
4 . 入门demo
首先作为入门级的demo当然是要简单,目录结构如下
其中MyWeb 这个类是一个非常简单的servlet 测试类,代码如下
public class MyWeb extends HttpServlet {@Overridepublic void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {res.setCharacterEncoding("utf-8");System.out.println("进入请求");PrintWriter writer = res.getWriter();writer.println("<h1>HttpServlet request</h1>");}
}
问题1:为什么我要在target目录下创建WEB-INF
嵌入式的tomcat有2种加载servlet的模式
1. 直接从代码里创建对象,加入容器
2.和外部的tomcat一样,从WEB-INF目录下的web.xml文件中加载,这里我把 target目录当做应用根目录,自然要手动创建.当然也可以手动指定web.xml的路径,这里后面会提及.
=================框架准备好.撸起袖子就是干我是分割线======================================
通过上面的结构图发现,:
tomcat下有一个server,一个server下有多个service,然后一个service下有多个connector(连接器,用于接收请求),一个Container(正真处理请求的)
同样的结构在tomcat的 conf/server.xml 配置文件里也可以体现
其中配置文件里的Engine就是Container
根据这个关系,可以构建一个最简单的项目结构
Tomcat tomcat = new Tomcat();//Server server = tomcat.getServer();//看源码发现,他只能设置一个service,直接拿默认的Service service = tomcat.getService();//创建连接器,并且添加对应的连接器,同时连接器指定端口Connector connector = new Connector();connector.setPort(8888);service.addConnector(connector);//创建一个引擎,放入service中Engine engine = new StandardEngine();service.setContainer(engine);engine.setDefaultHost("localhost");engine.setName("myTomcat");//添加hostHost host = new StandardHost();engine.addChild(host);host.setName("localhost");host.setAppBase("webapps");
别看API挺多,其实对照着 server.xml 文件可以很轻易写出来,
然后就是把我们的项目挂载上去了.
用过tomcat都知道,tomcat的挂载方式,这里我们也对应把xml文件翻译成对应的java代码
<Host><Context path="/前缀" docBase="项目路径" reloadable="true开启热更新">
</Host>
//在对应的host下面创建一个 context 并制定他的工作路径,会加载该目录下的所有class文件,或者静态文件StandardContext context = (StandardContext) tomcat.addContext(host, "/", "/Users/bignosecat/IdeaProjects/xx/tomcat/target");//初始化ContextConfig配置context.addLifecycleListener(new ContextConfig());
这里我直接把我整个项目的编译路径当做项目路径挂载去了tomcat
最后把自己写的servlet加入进去.
//创建一个servletWrapper myservlet = new StandardWrapper();myservlet.setServlet(new MyWeb());myservlet.setName("myServlet");//把servlet加入到contxt中context.addChild(myservlet);
//这里注意,要先添加到contxt中在映射路径,不然会空指针myservlet.addMapping("/chyweb1");
最后一步启动tomcat
//tomcat启动
tomcat.start();
//保持主线程不退出
tomcat.getServer().await();
测试浏览器输入
http://127.0.0.1:8888/chyweb1
到这里最简单的demo完成.
5.静态文件的加载
上面的demo只能处理一个自定义的servlet.而且不能处理jsp以及静态文件.
现在在项目路径下有一个 test.html的静态文件.按照以前tomcat的使用习惯,我在浏览器输入
http://127.0.0.1:8888/test.html
应该可以加载出这个html文件的对应信息,结果出现的是404.
如果熟悉tomcat可以知道,tomcat有个默认的servlet用来处理静态请求.还有一个专门处理jsp的servlet
通过源码分析,发现他还是提供了加载默认的servlet
context.addLifecycleListener(tomcat.getDefaultWebXmlListener());
使用上面这个API可以在初始化的时候加载上面标注出来的方法.
因为现在项目都在逐渐去除JSP,使用前后端分离,所以我这里就手动添加默认的servlet,而不引入jsp的servlet
//创建一个默认的Servlet 用来处理 html 等静态资源,如果上面设置了getDefaultWebXmlListener 可以不添加Wrapper defaultServlet = new StandardWrapper();defaultServlet.setServlet(new DefaultServlet());defaultServlet.setName("default");context.addChild(defaultServlet);defaultServlet.addMapping("/");
添加该servlet后重启项目,再次运行
http://127.0.0.1:8888/test.html
6. web.xml加载
这里如果使用手动添加servlet的方式,每次都很麻烦,而且代码耦合性太大,所以想能不能去像以前一样读web.xml文件.然后加载对应的servlet
通过源码分析发现加入以下配置即可
//初始化ContextConfig配置
context.addLifecycleListener(new ContextConfig());
但是只能在项目路径下的 WEB-INF/web.xml 文件
嗯果然还是tomcat的老套路,但是我就想随意定义web.xml怎么办
博主又在源码中找找找发现
从这段代码中发现,那我只要给他设上值不就可以了吗.
so加入
context.getServletContext().setAttribute("org.apache.catalina.deploy.alt_dd",
"/Users/bignosecat/IdeaProjects/xx/tomcat/src/main/resources/web.xml");
然后我访问了这个web.xml中定义的路径,成功
7. 完整的嵌入Tomcat 启动代码
Tomcat tomcat = new Tomcat();//Server server = tomcat.getServer();//看源码发现,他只能设置一个service,直接拿默认的Service service = tomcat.getService();//创建连接器,并且添加对应的连接器,同时连接器指定端口Connector connector = new Connector();connector.setPort(8888);service.addConnector(connector);//创建一个引擎,放入service中Engine engine = new StandardEngine();service.setContainer(engine);engine.setDefaultHost("localhost");engine.setName("myTomcat");//添加hostHost host = new StandardHost();engine.addChild(host);host.setName("localhost");host.setAppBase("webapps");//在对应的host下面创建一个 context 并制定他的工作路径StandardContext context = (StandardContext) tomcat.addContext(host, "/", "/Users/bignosecat/IdeaProjects/xx/tomcat/target");//初始化ContextConfig配置context.addLifecycleListener(new ContextConfig());//加载指定位置的web.xml//context.getServletContext().setAttribute("org.apache.catalina.deploy.alt_dd","/Users/bignosecat/IdeaProjects/xx/tomcat/src/main/resources/web.xml");//初始化 默认的servlet,这里会 触发tomcat#initWebappDefaults 方法,等价于平时tomcat自动加载默认的conf/web.xml文件//当然也可以手动加载,这里因为我没引用jsp的包,所以不自动加载.context.addLifecycleListener(tomcat.getDefaultWebXmlListener());//创建一个默认的Servlet 用来处理 html 等静态资源,如果上面设置了getDefaultWebXmlListener 可以不添加Wrapper defaultServlet = new StandardWrapper();defaultServlet.setServlet(new DefaultServlet());defaultServlet.setName("default");context.addChild(defaultServlet);defaultServlet.addMapping("/");//创建一个servletWrapper myservlet = new StandardWrapper();myservlet.setServlet(new MyWeb());myservlet.setName("myServlet");context.addChild(myservlet);myservlet.addMapping("/chyweb1");//tomcat启动tomcat.start();//保持主线程不退出tomcat.getServer().await();
8. 整合springmvc
O__O "…,这个还需要整合吗.直接把springmvc的web.xml 加载进嵌入tomcat 就可以了.
9.嵌入tomcat封装
这里博主把这API封装了一道,用于方便调用.代码具体看下面github,下面只演示API的使用
github
gitee
下面是这个框架的使用介绍
测试项目路径如下(一个最简单的springmvc项目):
在github获取项目后,安装进maven 引入坐标
<dependency><groupId>chy.frame</groupId><artifactId>tomcat</artifactId><version>1.0-SNAPSHOT</version></dependency>
在Main中写入然后直接运行即可
public static void main(String[] args) {/*** 构造有3个参数* 1. tomcat的端口* 2. web.xml的路径* 3. 项目静态文件的路径* 路径可以写 绝对路径或者* classpath: 开头 在classes路径下寻找* projectpath: 开头 在项目路径下寻找* */ ChyTomcat chyTomcat = new ChyTomcat(8001,"classpath:web.xml","projectpath:static");//服务开启chyTomcat.start();}
成功启动tomcat,并访问成功所定义的请求
嵌入式tomcat分析,并手写加载springMvc相关推荐
- Tomcat(二):手写嵌入式tomcat
一.什么是嵌入式tomcat 嵌入式tomcat:非传统的部署方式,将tomcat嵌入到主程序中进行运行. 二.嵌入式tomcat的优点 灵活部署.任意指定位置.通过复杂的条件判断 三.Maven集成 ...
- 嵌入式系统串口解析二进制数_嵌入式系统Bootloader分析及DSP56F800串口加载功能实现...
嵌入式系统 Bootloader 分析及 DSP56F800 串口加载功 能实现 张小平 ; 谷勇 ; 丰新龙 [期刊名称] <海军航空工程学院学报> [年 ( 卷 ), 期] 2010( ...
- Vue3.0+Cesium+Tomcat服务下倾斜摄影数据加载详细过程
Vue3.0+Cesium+Tomcat服务下倾斜摄影数据加载 1.Vue-cli 3.0 + cesium 构建 参考资料地址Vue-cli 3.0 + cesium 构建 注意,因为文档中设置默认 ...
- android去广告实现原理,分析某视频软件加载方案和去广告原理
分析某视频软件加载方案和去广告原理0x1用到的工具:AndroidKiller eclipse jd-gui Android逆向助手0x2拿到APK后首先想到的是是否有签名验证,因此用逆向助手重新签名 ...
- js如何在当前页面加载springmvc返回的页面_手写SpringMVC学习
前面我们学习了spring框架源码,做了一些自己手写的学习,最近,我们开始学习springMVC框架的学习 ,springMVC框架,相信大家不陌生了,所以这里不做过多的介绍了. SpringMVC以 ...
- redis 启动加载mysql_Redis分析系列:启动加载过程
从本篇文章开始(命名为Redis分析系列),将会通过分析Redis的源代码(以Redis 2.2.0 RC1为准),来对它的内部实现做一些探讨.本文主要介绍Redis启动加载过程,总体上可以分为如下几 ...
- tomcat 热部署、热加载 精析
1.前言 找了很多篇文章,没有一篇文章讲的清晰.明了,很多人只是会用,但不是能真正说明白,这年头找个懂理论的,真难! 2.热部署 原定义:tomcat处于运行状态时,能够监测webapps下的文件,如 ...
- Myabtis源码分析五-Mybatis配置加载完全图解,建造者模式的使用,涵盖Java各种技术栈
private SqlSessionFactory sqlSessionFactory; @Before public void init() throws IOException { //----- ...
- war包放到webapps下,启动tomcat,tomcat正常,却无法加载项目
由于工作需要,打war包,放到webapps下,启动tomcat,地址栏输入项目路径报错404 1.先确认tomcat是否正常启动:可以正常显示tomcat的图标,tomcat正常启动. 2.查看to ...
最新文章
- mysql 数据库 数组类型转换_mysql数字类型的数据如何进行转换?
- 图灵2010.06书讯
- iphone7wifi模块多少钱_模块炉价格参差不齐,消费者应独具慧眼!
- Spring事务传播行为7种类型 --- 看一遍就能记住!
- JAVA IO基本知识
- 【Spring】SpringBoot 如何使用JMX
- html onblur 函数执行了2次,JavaScript“onblur事件”调用函数失效 原因与解决方法
- 物理学基石 —— 麦克斯韦方程组
- win7 64位Apache http server+PHP配置
- linux(rhel) rescue修复详解
- 独家出品 | 培训机构免费资源汇总
- 腾讯收购Foxmail的意图
- 水下超声波测距c语言程序,超声波测距51C程序
- python 英语翻译_Python 实现中英文翻译
- 知识图谱实战开发案例剖析(22)Protege开发环境安装部署
- 【MySQL】删除记录
- 手风琴效果(js版本以及jquery版本)
- java启动器_Minecraft Java版新启动器正式开放
- Office 被曝 0 day 漏洞,微软确认 Windows 支持诊断工具存在问题;台半导体厂主管薪水大涨,超 10 人跻身亿元俱乐部
- 【知识兔】Excel教程 函数office软件 Excel素材 Excel网课 Excel入门