每篇一句

要么就安逸的穷,要么就拼命的干

前提概要

web开发使用Controller基本能解决大部分的需求,但是有时候我们也需要使用Servlet,因为相对于拦截和监听来说,有时候原生的还是比较好用的。

因此本文就主要介绍web三大组件Servlet、Filter、Listener在SpringBoot中的使用做个介绍。本文重点做使用介绍,以及剖析SpringBoot是如何支持和解析这些方式的

Spring boot 的主 Servlet 为 DispatcherServlet,其默认的url-pattern为“/”。也许我们在应用中还需要定义更多的Servlet,该如何使用SpringBoot来完成呢?

三种方式

本文主要以使用Servelt为例子进行讲解,使用其余组件的方式也差不多。差异性比较大的地方我会尽量指出来,请举一反三

方式一: @ServletComponentScan 扫描的方式(推荐)

看看这个注解的javadoc

 * Enables scanning for Servlet components ({@link WebFilter filters}, {@link WebServlet* servlets}, and {@link WebListener listeners}). Scanning is only performed when using an* embedded web server.

从javadoc中可以看出,该扫描的方式只支持嵌入式的web容器

使用此种扫描方式,显然是基于Servlet3.0的注解的方式。而该注解的解析由SpringBoot提供的@ServletComponentScan来驱动的。

案例如下:

@ServletComponentScan
@SpringBootApplication
public class Boot2Demo1Application {public static void main(String[] args) {SpringApplication.run(Boot2Demo1Application.class, args);}
}/*** @author fangshixiang* @description* @date 2019-01-28 14:39*/
@WebServlet(urlPatterns = "/servlet/demo", asyncSupported = false)
public class DemoServlet extends HttpServlet {@Overridepublic void init() throws ServletException {System.out.println("init my servlet");super.init();}@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {System.out.println("this is my servlet");super.doGet(req, resp);}
}

请求地址:http://localhost:8080/servlet/demo
控制台输出:

init my servlet
this is my servlet

有的朋友可能会问:为毛init方法也是此时才输出呢???为了答疑,这里之直接贴出来答案吧:

init 方法是随 Servlet 实例化而被调用的,因为 load-on-startup 就是用来设置Servlet 实例化时间的。因此,init 方法执行的时刻有两种:

  • load-on-startup 的值大于等于0,则伴随 Servlet 实例化后执行。
  • load-on-startup 的值小于0 或者 不配置(默认行为), 则在第一次 Servlet 请求的时候执行。

备注:看下面启动日志

2019-01-28 15:51:40.926  INFO 16144 --- [ost-startStop-1] o.s.b.w.servlet.ServletRegistrationBean  : Servlet com.sayabc.boot2demo1.servlet.DemoServlet mapped to [/servlet/demo]

可以看出,这种方式的底层原理还是转换成了ServletRegistrationBean,从而交给Spring容器管理了。同理:另外两大组件可以参照这个方式来定义和书写。

此方式优点:完全还原了源生servlet、filter、listener等功能,程序员自己也很方便的、更加细粒度。

方式二:通过ServletRegistrationBean进行组件注册

依托于SpringBoot提供的三个Bean:

ServletRegistrationBean
FilterRegistrationBean
ServletListenerRegistrationBean

实例代码:

    @Beanpublic ServletRegistrationBean MyServlet1() {return new ServletRegistrationBean(new DemoServlet(), "/servlet/*");}

访问路径:http://localhost:8080/servlet/demo控制台有对应日志输出(显然这种方式,init方法不会再执行了,因为自己new的嘛);

启动日志如下:

2019-01-28 15:59:37.412  INFO 14332 --- [ost-startStop-1] o.s.b.w.servlet.ServletRegistrationBean  : Servlet demoServlet mapped to [/servlet/*]

优点:内部可以直接@Autowired注入Spring的Bean,也可配合@Order调整优先级

方式三:@Component

采用此种方式是最简单的方式。Spring Boot也非常友好的给支持了。
示例:

@Component
public class DemoServlet extends HttpServlet {@Overridepublic void init() throws ServletException {System.out.println("init my servlet");super.init();}@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {System.out.println("this is my servlet");super.doGet(req, resp);}
}

日志输出:

2019-01-28 17:20:19.601  INFO 8756 --- [ost-startStop-1] o.s.b.w.servlet.ServletRegistrationBean  : Servlet demoServlet mapped to [/]

显然可以看出,直接使用@Component虽然方便,但是无法自定义urlPatterns,还是收到很多局限的。

备注:别想着这么做能达到效果(虽然我建议SpringBoot支持,哈哈

@Component
@WebServlet(urlPatterns = "/servlet/demo", asyncSupported = false)
public class DemoServlet extends HttpServlet {}

这样直接做是不生效的。还是只能映射到跟路径。因为@WebServlet等注解是依赖于
@ServletComponentScan才能驱动的,因此此种方式虽然方便,但是还是有很多局限性的。

但是,但是,对应Filter,一般我们都希望他拦截所有的请求,因此这么来做是很方便的。比如TokenFilter

@Order(1)
@Component
public class TokenFilter implements Filter{}

这样默认拦截的路径为:Mapping filter: 'tokenFilter' to: [/*],从而会过滤所有的请求。

小知识点:

< url-pattern>/</url-pattern>  会匹配到/login这样的路径型url,不会匹配到模式为*.jsp这样的后缀型url
< url-pattern>/*</url-pattern> 会匹配所有url:路径型的和后缀型的url(包括/login,*.jsp,*.js和*.html等)

所以如果以后发现总是有404错误的时候,别忘了check一下 /的配置是否是/*.

优点:内部可以直接@Autowired注入Spring的Bean,也可配合@Order调整优先级

简单总结

虽然Spring已经足够强大,几乎可以屏蔽我们对Servlet的Api。(Spring4以及以下版本的底层原理还是Servlet技术,但到了Spring5以后,servlet从必选项已经成为可选项了)

但是有的时候我们自己使用原生的方案更为妥当,因此本文针对于此提出一些方案和原理分析,仅供参考


关注A哥

Author A哥(YourBatman)
个人站点 www.yourbatman.cn
E-mail yourbatman@qq.com
微 信 fsx641385712
活跃平台
公众号 BAT的乌托邦(ID:BAT-utopia)
知识星球 BAT的乌托邦
每日文章推荐 每日文章推荐

【小家Spring】SpringBoot中使用Servlet、Filter、Listener三大组件的三种方式以及原理剖析相关推荐

  1. jupyter notebook python3路径_详解修改Anaconda中的Jupyter Notebook默认工作路径的三种方式...

    方式1. 打开Windows的cmd,在cmd中输入jupyter notebook --generate-config如下图: 可以看到路径为D:\Users--找到此路径修改jupyter_not ...

  2. JavaScript中遍历数组的for for-in和forEach三种方式

    JavaScript中遍历数组的for for-in和forEach三种方式 for循环 let arr = [1,2,3,4,5,6];for(let i = 0; i < arr.lengt ...

  3. JavaScript--------------------jQuery中.bind() .live() .delegate() .on()的区别 和 三种方式写光棒事件 动画...

    bind(type,[data],fn) 为每个匹配元素的特定事件绑定事件处理函数. $("a").bind("click",function(){alert( ...

  4. win下配置的ES中的数据在哪里可以看到?三种方式你看那种更加高大上!!!(win_Elasticsearch)

    在上一篇博客<使用logstash将Mysql中的数据导入到ElasticSearch中(详细步骤,win_Elasticsearch)>中我们提到将数据插入到es中,那我怎么知道数据是否 ...

  5. Struts2中jsp前台传值到action后台的三种方式以及valueStack的使用

    struts2中的Action接收表单传递过来的参数有3种方法: 如,登陆表单login.jsp: 1 <form action="login" method="p ...

  6. Spring学习3 - Bean的属性、DI依赖注入三种方式

    文章目录 1. 属性设置 - XML配置文件.以及与其等价的注解形式 2. 依赖注入DI的方式 2.1 属性自动注入 - 不推荐 代码准备阶段 代码测试 2.2 子节点构造器注入 - 不推荐 2.3 ...

  7. mysql中如何获取字段类型_MySQL获取字段类型的三种方式

    1. INFORMATION_SCHEMA.COLUMNS INFORMATION_SCHEMA是每个MySQL实例中的数据库,该实例存储有关MySQL服务器维护的所有其他数据库的信息. 如查询某一个 ...

  8. 把对象的创建交给spring来管理——  1.创建bean的三种方式     2.bean对象的作用范围     3.bean对象的生命周期

    把对象的创建交给spring来管理 spring对bean的管理细节     1.创建bean的三种方式     2.bean对象的作用范围     3.bean对象的生命周期 创建Bean的三种方式 ...

  9. 【Linux】部署Springboot项目到Linux服务器以及linux服务器下载文件的三种方式详解

    Linux学习之路 初识Linux Linux内核 由芬兰人林纳斯·托瓦兹(Linus Torvalds)在赫尔辛基大学上学时出于个人爱好而编写 Linux 是一套免费使用和自由传播的类Unix操作系 ...

最新文章

  1. ADO.NET 2.0 - 读者询问能否使用 SqlBulkCopy 对象来大量复制文字文件
  2. 数据库中的goto语法
  3. plsqldev远程连接mysql_PLSQL Developer连接远程Oracle数据库
  4. lucky前面加a还是an_微信昵称前加个“A” 不是微商就是销售?看看这个“A”的含义!...
  5. C#操作HttpClient工具类库
  6. 精讲23种设计模式-基于观察者模式~设计异步多渠道群发框架
  7. 在另一台服务器上还原被误删的 MySQL 数据
  8. jq点击更多收起效果
  9. 安卓为什么卡及其解决方案
  10. Matlab 求全要素生产率,如何用DEAP进行全要素生产率分析
  11. zzbird的bbsmax出了?
  12. cad手机看图 android,CAD手机看图
  13. 教育研究方法 的思维导图
  14. Gram矩阵计算实例
  15. 使用spss求标准化的线性回归方程
  16. 基于触摸屏PLC的温度采集及简单控制
  17. anaconda安装完怎么打开_10分钟带你安装和配置Anaconda
  18. detach()函数理解
  19. Mac IDEA 自带Maven换国内源
  20. redux的原理、工作流程及其应用

热门文章

  1. D - JDK17源码阅读 - 集合框架 - Collection<E> 接口 - 集合框架核心接口
  2. 微信小程序npm安装第三方包
  3. 解决win11桌面右键创建只有一个带盾牌的文件夹问题
  4. 学习记录:unity的json存储
  5. 如何给公司名称进行脱敏?
  6. 店铺的安全问题一定要注意
  7. Java 实现快速排序法对数组进行排序
  8. nmap扫描mysql的命令_端口扫描命令nmap
  9. win10系统优化计算机,电脑升级win10后,必做的5项优化,至少提升20%的运行速度...
  10. Javascript共通方法汇总