-
手写springboot内嵌tomcat启动
2020-09-08 13:45:57外置和内嵌tomcat区别 外置的tomcat: tomcat启动加载web.xml,通过web.xml配置初始化spring容器,并加载dispatcherservlet 内嵌tomcat: springboot启动,初始化spring容器加载bean,然后启动内嵌tomcat,通过...外置和内嵌tomcat区别
外置的tomcat:
tomcat启动加载web.xml,通过web.xml配置初始化spring容器,并加载dispatcherservlet
内嵌tomcat:
springboot启动,初始化spring容器加载bean,然后启动内嵌tomcat,通过servlet3.1规范的 ServletContainerInitializer加载dispatcherservlet代码示例及流程说明
我会一边贴出代码,一边解释下部分代码
git地址:https://gitee.com/chuanxin1123/yboot
项目结构:
首先是maven依赖:
<dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>5.2.7.RELEASE</version> </dependency> <dependency> <groupId>org.apache.tomcat.embed</groupId> <artifactId>tomcat-embed-jasper</artifactId> <version>8.5.23</version> </dependency>
那么我们在这里分析一下springboot启动流程:
1.初始化ioc
为什么要先初始化ioc,而不是先启动tomcat?因为ioc是必须的,而tomcat可以被其他中间件替换
2.启动tomcat
3.将dispatcherServlet放入到ioc容器,并加载到tomcat上下文中去
那么我们先实现第一步:初始化ioc
@ComponentScan("com.chuan") public class StartApplication { public static void main(String[] args) throws Exception{ //1.初始化ioc, // 为什么要先初始化ioc,而不是先启动tomcat,因为ioc是必须的,而tomcat可以被其他中间件替换 AnnotationConfigWebApplicationContext ac=new AnnotationConfigWebApplicationContext(); ac.register(StartApplication.class); //手动去注册一个bean ac.refresh(); //刷新 } }
然后将dispatcherServlet注入到ioc中,这里为什么不能写在主方法中?因为写在主方法中就是强引用了,必须要使用servlet方式处理并且必须是web项目了。
@Configuration public class MyConfig { @Bean public DispatcherServlet getDispatcherServlet(){ return new DispatcherServlet(); } }
实现第二步:启动tomcat,写一个接口和tomcat实现类
public interface WebServerFactory { //使用接口增加了扩展性,不一定非要用tomcat void createServer() throws Exception; }
@Component public class MyTomcat implements WebServerFactory{ public void createServer() throws Exception { Tomcat tomcat=new Tomcat(); tomcat.setPort(8081); tomcat.addWebapp("/","D://soft"); tomcat.start(); //因为 tomcat.start();是非阻塞型的,所以要阻塞一下,不能让服务停止。 tomcat.getServer().await(); } }
然后修改主方法,调用tomcat启动
@ComponentScan("com.chuan") public class StartApplication { public static void main(String[] args) throws Exception{ //1.初始化ioc, // 为什么要先初始化ioc,而不是先启动tomcat,因为ioc是必须的,而tomcat可以被其他中间件替换 AnnotationConfigWebApplicationContext ac=new AnnotationConfigWebApplicationContext(); ac.register(StartApplication.class); //手动去注册一个bean ac.refresh(); //刷新 //2.启动tomcat WebServerFactory factory = ac.getBean(WebServerFactory.class); factory.createServer(); //3.将dispatcherServlet放入到ioc容器,并加载到tomcat上下文中去 //注意dispatcherServlet不能放在启动里,因为也可以被reactive响应式编程替换掉servlet,也可以不是web项目 } }
但现在tomcat和dispatcherServlet并没有关联起来,需要进行第三步操作:将dispatcherServlet放入到ioc容器,并加载到tomcat上下文中去
创建一个servlet作为顶层servlet,实现了一个ApplicationContextAware 接口。
ApplicationContextAware接口中setApplicationContext方法让Spring容器传递自己生成的ApplicationContext给我们使用,然后通过ac获取到DispatcherServlet的实例。
@Component public class MyServlet implements ApplicationContextAware { private static ApplicationContext context; public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { context=applicationContext; } //从ac中获取实例 public static DispatcherServlet getDispatcherServlet(){ return context.getBean(DispatcherServlet.class); } }
然后通过子类将DispatcherServlet添加到tomcat上下文中去。
这里有两种写法:
1.实现WebApplicationInitializer接口(springboot封装了ServletContainerInitializer接口)
2.实现ServletContainerInitializer接口(spi3.0规范)
从servlet3.0开始,web容器启动时为提供给第三方组件机会做一些初始化的工作,例如注册servlet或者filtes等,servlet规范中通过ServletContainerInitializer实现此功能。每个框架要使 用ServletContainerInitializer就必须在对应的jar包的META-INF/services 目录创建一个名为javax.servlet.ServletContainerInitializer的文件,文件内容指定具体的 ServletContainerInitializer实现类,那么,当web容器启动时就会运行这个初始化器做一些组件内的初始化工作。
实现了onStartup后,在运行中会自动执行该方法,也正是该方法替代了spring中的web.xml,实现了无配置。
写法1:
public class MyServletInit extends MyServlet implements WebApplicationInitializer { public void onStartup(ServletContext servletContext) throws ServletException { ServletRegistration.Dynamic dynamic =servletContext.addServlet("MyDispatcherServlet",super.getDispatcherServlet()); dynamic.setLoadOnStartup(1); dynamic.addMapping("/"); } }
写法2:
public class MyServletInit extends MyServlet implements ServletContainerInitializer { @Override public void onStartup(Set<Class<?>> set, ServletContext servletContext) throws ServletException { ServletRegistration.Dynamic dynamic =servletContext.addServlet("MyDispatcherServlet",super.getDispatcherServlet()); dynamic.setLoadOnStartup(1); dynamic.addMapping("/"); } }
但需要多出一步,在resources下创建一个META-INF/services目录(不是一个叫META-INF.services的文件夹),在该目录下创建一个文件名为javax.servlet.ServletContainerInitializer的文件,里面内容为该实现类的全路径(我的spi3.0实现是简写了)
com.chuan.config.MyServletInit
最后写一个controller启动:
@RestController public class MyController { @RequestMapping("/test") public String test(){ return "test"; } }
结果:启动成功,并且DispatcherServlet功能也正常。
什么替换了web.xml
比如通过web.xml方式启动:
<web-app> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <context-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/applicationContext.xml</param-value> </context-param> <servlet> <servlet-name>app</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:springmvc.xml</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>app</servlet-name> <url-pattern>/*</url-pattern> </servlet-mapping> </web-app>
其中的ContextLoaderListener可以被下面代码替代
AnnotationConfigWebApplicationContext ac=new AnnotationConfigWebApplicationContext(); ac.register(StartApplication.class); //手动去注册一个bean ac.refresh();
而DispatcherServlet则可以被下面代码替代
ServletRegistration.Dynamic dynamic =servletContext.addServlet("MyDispatcherServlet",super.getDispatcherServlet()); dynamic.setLoadOnStartup(1); dynamic.addMapping("/");
-
app应用内嵌h5页面怎么直接打开safari_小程序和h5的区别是什么?如何跳转h5页面?...
2020-12-29 13:52:24小程序和h5的区别是什么?主要在于这几点:(1)开发方法不同。H5的开发工具依赖的外壳主要是浏览器,因此只要有浏览器,就可以使用。比如手机内置的浏览器,APP 的 web-view 组件,以及小程序提供的 web-view 组件,...你了解微信小程序吗?小程序和h5的区别是什么?主要在于这几点:(1)开发方法不同。H5的开发工具依赖的外壳主要是浏览器,因此只要有浏览器,就可以使用。比如手机内置的浏览器,APP 的 web-view 组件,以及小程序提供的 web-view 组件,都可以打开 H5 页面。小程序的开发则是使用开发工具,可以用官方的开发者工具(适合码农),也可以用第三方小程序制作工具(适合纯小白),比如「上线了」sxl.cn。
本展示页所提供的模板及元素仅供展示功能效果,
未经授权不得应用于其他用途
(2)打开方式不同。微信小程序只能在微信APP内打开;而h5页面可以在各种浏览器上打开。(3)浏览体验不同。小程序要快很多,这是因为小程序基于微信客户端实现,对解析进行了优化,并且一旦首次打开小程序,可以直接缓存很多资源。再加上小程序的设计理念本就是“小而轻”,希望能带给访客快捷省时的使用体验。上线了小程序案例,禁止转载而 H5 本质上还是网页,跟之前在 PC 上浏览网页没区别,每次要请求各种图片样式资源,在浏览器内核里渲染,因此体验会差一些。有些开发者在开发小程序时,想要小程序跳转h5、小程序内嵌h5页面功能,这种情况下可以参考以下web-view组件:https://developers.weixin.qq.com/miniprogram/dev/component/web-view.htmlh5跳小程序就简单了,你可以直接在网页中附上小程序码的图片,让访客扫描就好。以上就是关于h5小程序区别、开发问题科普了,如果你想快速拥有一个小程序,可以使用「上线了」sxl.cn小程序制作工具哦,不需要懂任何技术!点击下方“阅读原文”,用「上线了」制作一个自己的小程序试试吧!(电脑端操作更方便哦)「上线了sxl.cn」是一个专注自助建站与小程序开发的SaaS平台,针对众多行业提供多套小程序模板,目前已经帮助三百多万没有技术和设计基础的用户,通过上线了一键生成网站或小程序,快速建立品牌、获取客户、经营生意。2019年8月入选腾讯SaaS加速器首期成员。
推荐阅读
小程序商城圣诞跨年营销方案
网站商家圣诞节跨年营销方案
高质量小程序样式模板大全
-
深入理解PHP原理之错误抑制与内嵌HTML分析
2020-10-28 13:56:31PHP支持内嵌HTML的, 那么对于PHP文件中, PHP标签外的HTML会怎么处理呢? 它和直接输出HTML有什么区别么? -
深入理解PHP原理之错误抑制与内嵌HTML
2010-02-07 14:22:00PHP支持内嵌HTML的, 那么对于PHP文件中, PHP标签外的HTML会怎么处理呢? 它和直接输出HTML有什么区别么?PHP提供了一个错误抑制符’@, 它是通过什么方式来阻止错误输出呢? 我又该在什么时候使用它呢?PHP文件内嵌HTML的...PHP支持内嵌HTML的, 那么对于PHP文件中, PHP标签外的HTML会怎么处理呢? 它和直接输出HTML有什么区别么?
PHP提供了一个错误抑制符’@', 它是通过什么方式来阻止错误输出呢? 我又该在什么时候使用它呢?
PHP文件内嵌HTML的处理方式
在PHP中, 所有在标签外的字符, 在词法分析过程中, 都会翻译成T_INLINE_HTML token, 在语法分析的时候, 所有的T_INLIE_HTML都会被分配ZEND_ECHO输出.
也就是说:
1. <?php
2. while($con) {
3. ?>
4. laruence
5. <?php
6. }
7. ?>会生成一条OPLINE: T_ECHO, 而操作数是”laruence”;
就结果来说, 上面的代码, 其实和下面的结果一样:
1. <?php
2. while($con) {
3. echo "laruence";
4. }
5. ?>但有一个要注意的地方是, 对于PHP标签外的字符, 在词法分析过程中, 都会以400个字符为单位切分, 比如:
1. <?php
2. if(1) {
3. ?>
4. laruence laruence laruence laruence laruence laruence laruence laruence laruence laruence laruence laruence laruence laruence laruence laruence laruence laruence laruence laruence laruence laruence laruence laruence laruence laruence laruence laruence laruence laruence laruence laruence laruence laruence laruence laruence laruence laruence laruence laruence laruence laruence laruence laruence laruence laruence laruence laruence laruence laruence laruence laruence laruence laruence laruence laruence laruence laruence laruence
5. <?php
6. }
7. ?>上面的代码中, 标签外有531个字符(包含空格回车), 会被分成俩条T_INLINE_HTML输出.
错误抑制符
我们知道,在PHP中,可以通过错误抑制符来静默错误提示, 那么它是通过什么方式呢?
在语法分析的过程中, 对于:
1. <?php
2. @include('file');
3. ?>会分别在include语句前后插入俩条Opline(操作), 这俩个操作分别做:
1. 1. 保存当前的error_reporting值, 并设置error_reporting(0); //关闭错误输出
2. 2. 恢复之前保存的error_reporting值.也就是说, 其实上面的代码, 和下面的代码类似:
1. $old = error_reporting(0);
2. include('file');
3. error_reporting($old);另外, 讲一句题外话:”什么时候才应用错误抑制呢?”, 我个人建议, 就是如果这条语句出错了对你影响不大, 你也不关心这个错误是什么, 你也不会安排额外的逻辑来处理这种错误, 那么你可以使用错误抑制. 否则, 请你使用额外的逻辑来判断错误.
-
link和@import的区别
2017-03-18 16:33:10页面中使用CSS的方式主要有3种:行内添加定义style属性值,页面头部内嵌调用和外面链接调用,其中外面引用有两种:link和@import。外部引用CSS两种方式link和@import的方式分别是: XML/HTML代码 XML/HTML代码 ...页面中使用CSS的方式主要有3种:行内添加定义style属性值,页面头部内嵌调用和外面链接调用,其中外面引用有两种:link和@import。外部引用CSS两种方式link和@import的方式分别是:
XML/HTML代码
XML/HTML代码
两者都是外部引用CSS的方式,但是存在一定的区别:
区别1:link是XHTML标签,除了加载CSS外,还可以定义RSS等其他事务;@import属于CSS范畴,只能加载CSS。
区别2:link引用CSS时,在页面载入时同时加载;@import需要页面网页完全载入以后加载。
区别3:link是XHTML标签,无兼容问题;@import是在CSS2.1提出的,低版本的浏览器不支持。
区别4:link支持使用Javascript控制DOM去改变样式;而@import不支持。
补充:@import最优写法
@import的写法一般有下列几种:@import 'style.css' //Windows IE4/ NS4,Mac OS X IE5, Macintosh IE4/IE5/NS4不识别
@import "style.css" //Windows IE4/ NS4, MacintoshIE4/NS4不识别
@import url(style.css) //Windows NS4, Macintosh NS4不识别
@import url('style.css') //Windows NS4, Mac OS X IE5, MacintoshIE4/IE5/NS4不识别
@import url("style.css") //Windows NS4, Macintosh NS4不识别
由上分析知道,@import url(style.css) 和@import url("style.css")是最优的选择,兼容的浏览器最多。从字节优化的角度来看@importurl(style.css)最值得推荐。 -
CSS引入的方式有哪些? link和@import的区别是?
2019-10-01 12:32:46link和@import的区别是 : ①link属于XHTML标签,除了加载CSS外,还能 用于定义RSS, 定义rel连接属性等作用;而@import是CSS提供的,只能用于加载CSS; ②页面被加载的时,link会同 时被加载,而@import引用的CSS... -
CSS引入的方式及link和@import的区别
2017-07-01 14:57:54link和@import的区别:(1)link是XHTML标签,除了加载CSS外,还可以定义RSS等其他事务;@import属于CSS范畴,只能加载CSS。(2)link引用CSS时,在页面载入时同时加载;@import需要页面网页完全载入以后加载。(3)... -
css引入的方式有哪些?link和@import的区别?
2017-09-20 01:26:13引入方式3种:行内添加定义style属性值,页面头部内内嵌调用和外链调用, 区别: 1.link是xhtml标签,除了加载css外,还可以定义RSS等其他事务,@import只能加载CSS 2.link引用CSS时候,页面载入的时候同时... -
页面导入样式文件的四种方式 & link 和 @import 的区别
2020-06-09 09:46:57link与@impoort的区别 link属于html标签,而@import是CSS提供的。link除了加载CSS外,还能用于定义RSS,定义rel链接属性等作用;而@import是CSS提供的,只能用于加载CSS。 import是CSS2.1提出的. -
sam卡和sim卡区别_关于PSAM卡、SAM卡、SIM卡的特征和区别
2020-12-31 09:39:44PSAM卡(Purchase Secure Access Module,销售点终端安全存取模块),内嵌于各类终端设备,为其提供IC卡级别的安全保护, PSAM除具备用户卡功能外,还具有计算功能。PSAM中增加了计算型密钥。PSAM主要应用于商用POS,... -
link与@import的区别
2017-09-12 15:18:05在HTML中引入CSS的方法主要有四种,分别是行内样式、内嵌样式、链接样式、导入样式,其中外部引入的两种就是链接样式和导入样式,也就是link和import。 1、示例 XML/HTML代码 XML/HTML代码 @import url("CSS... -
sam卡和sim卡区别_什么是PSAM卡、SAM卡、SIM卡
2020-12-31 09:39:40PSAM卡指终端安全控制模块,内嵌于各类终端设备,为其提供IC卡级别的安全保护,PSAM除具备用户卡功能外,还具有计算功能。PSAM中增加了计算型密钥。应用范围PSAM主要用于商用POS[销售终端-pos(pointofsale)是一种多... -
Exynos4412 所用外存 —— eMMC
2016-03-03 22:30:31Exynos4412所用外存不是原来的... eMMC(Embeded MultiMedia Card):它并非是一种全新尺寸的存储卡,而是由MMC协会所订立的内嵌式存储器标准规格,而且还是专门为手机和移动嵌入式产品设计的。eMMC简单来说是一个嵌 -
Hive基础(1)
2016-04-17 18:17:512. 元数据和数据的区别,前者如表名、列名、字段名等。3. Hive的三种安装方式 内嵌模式,元数据服务和Hive服务运行在同一个JVM中,同时使用内嵌的Derby数据库作为元数据存储,该模式只能支持同时最多一个用户打开... -
CSS的一些问题
2015-04-01 09:33:26link和@import的区别是? 内联 内嵌 外链 导入 link和@import的区别是: @import url("CSS文件"); 两者都是外部引用CSS的方式,但是存在一定的区别: 区别1:link是XHTML标签,除了加载CSS外,还可以... -
HTML8 工作总结
2017-05-22 15:54:08其实text-shadow和box-shadow差别不大,其中重点要区别的是内嵌阴影和外阴影,以及掌握参数的含义就好了。这里重点说下内嵌阴影,它的格式如下: box-shadow: inset npx mpx kpx color 其中n,m分别是阴影在水平... -
工程硕士学位论文 基于Android+HTML5的移动Web项目高效开发探究
2017-02-28 21:22:19尽我所知,除了文中特别加以标注和致谢的地方外,论文中不包含其他人已经发表或撰写过的研究成果,也不包含为获得东南大学或其它教育机构的学位或证书而使用过的材料。与我一同工作的同志对本研究所做的任何贡献均已... -
如何将一个spring项目重构成spring-boot项目(仅后台)
2018-05-27 19:20:51一.spring---spring-boot的区别 其实讲区别,就是讲spring-boot有不同Spring Boot可以建立独立的Spring应用程序;内嵌了如Tomcat,Jetty和Undertow这样的容器,也就是说可以直接跑起来,用不着再做部署工作了。无需...
-
【原创工具】代码片段管理器.exe
-
神奇的三次握手和四次挥手详解
-
MySQL 查询与高级查询(多表、嵌套和正则表达式)
-
第2章 Java内存区域与内存溢出异常
-
java 二进制(原码 反码 补码),位运算,移位运算(笔记)
-
基于python的dango框架购物商城毕业设计毕设源代码使用教程
-
vue.js 引入 配置 jquery
-
第7章 虚拟机类加载时机
-
MySQL 函数、用户自定义函数
-
使用者介面-源码
-
实验室:MIT IT实验室存储库-源码
-
xxljob源码分析
-
基于电商业务的全链路数据中台落地方案(全渠道、全环节、全流程)
-
Office Tool v6.2.2.4.zip
-
asp.net core 2.1程序部署到IIS报错502.5解决方案
-
贴片天线的机械变形对其共振频率的影响
-
【Linux】服务器安全措施
-
基于Qt的LibVLC开发教程
-
MySQL 数据类型和运算符
-
mybatis IF的使用的坑