SpringBoot集成WebServlet出现自定义单servlet请求失败的问题
一.导言
SpringBoot的真正核心是快速整合以及自动装配,所以在spring家族中springBoot不仅整合了Spring的IOC容器还兼容了WebServlet容器;这使得springBoot项目不仅支持快速开发微服务,同时具备开发MVC模式下的项目。
其中MVC模式的实现者之一就是WebServlet;由于springBoot的整合,在其项目中开发WebServlet也是可行方案之一。但是在使用servlet技术时我们遇到了一个问题:即在SpringBoot中,以Bean的方式注册servlet需要自定义两个及以上的servlet。
这是为什么呢?
二.测试验证问题
首先验证一个servlet的情况
先配置servlet实现类:
public class OneServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("servlet 1 的实现类");
resp.getWriter().print("this is servlet 1");
}
}
在config配置类中注册这个servletBean:
@Configuration
public class RegisterBean {
@Bean
public OneServlet createOneServlet(){
//注册servlet 1
return new OneServlet();
}
}
直接启动springBoot启动器查看是否可以完成一次servlet的请求
地址栏输入:
http://localhost:9000/createOneServlet/
或者:
http://localhost:9000/OneServlet/
显示都是错误页面:

验证两个servlet的情况
拓展一个servlet实现类:
public class TwoServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("servlet 2 的实现类");
resp.getWriter().print("this is servlet 2");
}
}
以及使用Bean的方式完成注入:
@Configuration
public class RegisterBean {
@Bean
public OneServlet createOneServlet(){
//注册servlet 1
return new OneServlet();
}
@Bean
public TwoServlet createTwoServlet(){
//注册servlet 2
return new TwoServlet();
}
}
再次启动springBoot启动器:
运行:
http://localhost:9000/createOneServlet/
结果可以拿到请求,正常处理

运行:
http://localhost:9000/createTwoServlet/
结果依旧可以拿到,正常处理请求:

这就出现了刚开始提到的那个问题:springBoot项目运行时,一个servlet无法进行请求,当有两个时却可以进行请求
解决这问题之前,我们需要一点前言知识,那就是需要先了解SpringMVC中的DispatcherServlet
三.解决单servlet无法正常请求的问题
DispatcherServlet 是 Spring MVC 框架的核心组件,它充当前端控制器(Front Controller)的角色,负责接收所有的 HTTP 请求并将其分发到相应的处理器(Handler)。通过这种方式,DispatcherServlet 实现了请求的集中管理和分发。请求分发:接收所有进入的应用程序的HTTP请求,并根据配置将它们分发给合适的处理器(Controller)。
当然DispatcherServlet的功能还有很多,我们只把关系到问题的部分单独拿出来。我们知道SpringMVC在JavaWeb的基础之上,演化了DispatcherServlet,它的本质依旧是一个servlet,在SpringMVC中将其单独拿出来作为前后端连接的大脑,通常它会将前端所有的请求都拦截下来,然后经过一系列验证之后移交给controller处理,处理完成之后又返回给它,返回给视图层。
由于springBoot中整合了SpringMVC,故而DispatcherServlet存在于spring容器中的。
回到刚刚的问题,一个servlet为什么执行不起来,这还得分析我们注入servlet的方式
@Bean
public OneServlet createOneServlet(){
//注册servlet 1
return new OneServlet();
}
由于我们注入使用的是最简单的注入方式,并没有配置这个servlet的请求路径;
DeepSeek:如果没有显式配置路径映射,Spring Boot 会尝试为 Servlet 分配默认路径,通常是 Servlet 的名称或类名的小写形式。如果默认路径与其他映射冲突,或 Servlet 未正确注册,可能导致无法访问。
在第一种情况下,springBoot是在尝试进行为servlet命名的,只是为其命名的映射路径刚好和DispatcherServlet的拦截请求冲突了,故而失败了
我们在失败的情况下编写一个controller,看相同的请求是不是交给DispatcherServlet处理了
controller:
@RestController
public class ServletTest {
@GetMapping("/createOneServlet/")
public String test(){
return "return from Spring MVC";
}
}
和第一次失败测试一样的请求:
http://localhost:9000/createOneServlet/
结果

可以发现,配置一个controller之后确实请求被DispatcherServlet接管了,故而有springMVC框架进行返回
知道了问题所在就可以进行修改了,推荐两种解决方案
1.更改DispatcherServlet的默认拦截路径
在SpringBoot中DispatcherServlet的默认拦截路径是 "/*" ;故而将其改到其它位置后,他就不会影响SpringBoot为没有配置映射路径的servlet命名了
更改application.properties文件:
spring.mvc.servlet.path= /test/
将DispatcherServlet的默认匹配路径更改到 “ /test/* ” 下
注销controller类的实现:
// @GetMapping("/createOneServlet/")
// public String test(){
// return "return from Spring MVC";
// }
再次启动,测试单servlet未配置路径是否有问题:
http://localhost:9000/createOneServlet/
结果:

可以看到,servlet成功将其请求处理了
2.配置单个servlet的请求路径
配置servlet实现类使用@WebServlet注解:
@WebServlet(urlPatterns = "/createOneServlet")
public class OneServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("servlet 1 的实现类");
resp.getWriter().print("this is servlet 1");
}
}
在springBoot启动器上配置自动扫描servlet的注解@ServletComponentScan:
@SpringBootApplication
@ServletComponentScan
public class ServletTestApplication { public static void main(String[] args) {
SpringApplication.run(ServletTestApplication.class, args);
} }
启动测试:
http://localhost:9000/createOneServlet/
结果:

可以发现依旧运行出来了结果
如上就是推荐在SpringBoot中注册servlet的两种方式
为什么两个自定义servlet不写映射却可以呢?
DeepSeek:两个自定义 Servlet 可以访问的原因
自动注册:当有多个 Servlet 时,Spring Boot 会为每个 Servlet 生成默认路径,通常基于类名或者Bean。
路径唯一性:多个 Servlet 的默认路径通常不会冲突,因此可以正常访问。
也就是基于这样的原因,DispatcherServlet没有产生拦截,因为这两个自定义servlet已经在Servlet容器中完成注册,根据Java servlet的匹配规范,即最长匹配原则,/(类名|Bean)的匹配长度比DispatcherServlet精度更改,故而两个servlet的情况下,即使不修改SpringMVC的配置依旧可以正常访问。
------END------
本文虽经反复斟酌,但仍可能存在疏漏或不当之处,衷心希望得到各位同行的批评指正,以期进一步完善。
SpringBoot集成WebServlet出现自定义单servlet请求失败的问题的更多相关文章
- SpringBoot 拦截器和自定义注解判断请求是否合法
应用场景举例: 当不同身份的用户请求一个接口时,用来校验用户某些身份,这样可以对单个字段数据进行精确权限控制,具体看代码注释 自定义注解 /** * 对比请求的用户身份是否符合 * @author l ...
- 关于SpringBoot集成myBatis时,mapper接口注入失败的问题
问题描述: 在Spring Boot集成myBatis时,发现启动时,mapper接口一直注入失败. 现象如下: VehicleDAO就是需要的mapper对象,一个简单的接口. 已经在applica ...
- SpringBoot集成Spring Security(4)——自定义表单登录
通过前面三篇文章,你应该大致了解了 Spring Security 的流程.你应该发现了,真正的 login 请求是由 Spring Security 帮我们处理的,那么我们如何实现自定义表单登录呢, ...
- SpringBoot自定义servlet、注册自定义的servlet、过滤器、监听器、拦截器、切面、webmvcconfigureradapter过时问题
[转]https://www.cnblogs.com/NeverCtrl-C/p/8191920.html 1 servlet简介 servlet是一种用于开发动态web资源的技术 参考博客:serv ...
- springboot扫描自定义的servlet和filter代码详解_java - JAVA
文章来源:嗨学网 敏而好学论坛www.piaodoo.com 欢迎大家相互学习 这几天使用spring boot编写公司一个应用,在编写了一个filter,用于指定编码的filter,如下: /** ...
- SpringBoot集成thymeleaf(自定义)模板中文乱码的解决办法
楼主今天在学习SpringBoot集成thymelaf的时候报了中文乱码的错误,经过网上的搜索,现在得到解决的办法,分享给大家: package com.imooc.config; import or ...
- SpringBoot(10) Servlet3.0的注解:自定义原生Servlet、自定义原生Listener
一.自定义原生Servlet 1.启动类里面增加注解 @ServletComponentScan 2.Servlet上添加注解 @WebServlet(name = "userServle ...
- springboot集成swagger添加消息头(header请求头信息)
springboot集成swagger上篇文章介绍: https://blog.csdn.net/qiaorui_/article/details/80435488 添加头信息: package co ...
- 基于Springboot集成security、oauth2实现认证鉴权、资源管理
1.Oauth2简介 OAuth(开放授权)是一个开放标准,允许用户授权第三方移动应用访问他们存储在另外的服务提供者上的信息,而不需要将用户名和密码提供给第三方移动应用或分享他们数据的所有内容,OAu ...
- SpringBoot09 自定义servlet、注册自定义的servlet、过滤器、监听器、拦截器、切面、webmvcconfigureradapter过时问题
1 servlet简介 servlet是一种用于开发动态web资源的技术 参考博客:servlet基础知识 httpservlet详解 2 在springboot应用中添加servlet sp ...
随机推荐
- Not all slots covered! Only 5461 slots are available. Set checkSlotsCoverage = false to avoid this check
Not all slots covered! Only 5461 slots are available. Set checkSlotsCoverage = false to avoid this c ...
- fabric2.0开发 基本环境安装配置(docker docker-compose go node git等)(1)
转载:https://blog.csdn.net/tank_ft/article/details/105298053 基本环境:Ubuntu16.04 linux 在安装相关软件之前建议没有更换国内源 ...
- [转]VS2019+CUDA11.1 没有CUDA出现
1.VS2019+CUDA11.1 没有CUDA出现 2.VS+CUDA 新建项目里没有CUDA选项(附详细图文步骤) 3.No Cuda 10.1 runtime Template in Visua ...
- 单点认证(SSO)方案调研总结
SSO方案 SSO介绍 单点登录(SSO)是一种身份验证解决方案,可让用户通过一次性用户身份验证登录多个应用程序和网站.这意味着用户只需输入一次用户名和密码,即可访问所有相互信任的系统,而无需在每个系 ...
- UML的9种常用图与建模工具详解
UML即Unified Model Language,是一种建模语言,也是标准建模语言.在软件开发中,当系统规模比较复杂时,需要用图形抽象地来表达复杂的概念,让整个软件设计更具有可读性,可理解性,以便 ...
- 富数-AnonymFL
本文学习文章"2022 WAIC|「全匿踪联邦学习」AnonymFL正式发布:破解用户ID暴露难题,实现真正合规可信的隐私计算",记录笔记. 引言 2022年08月26日,富数科技 ...
- el-table合计行
用到属性 showSummary 是否显示合计,方法 summaryMethod 计算合计的自定义方法. <el-table ref="elTable" :data=&quo ...
- AllPairs工具助力正交表测试用例设计
AllPairs工具助力正交表测试用例设计 正交表法是一种高效的测试方法,特别适用于软件测试中需要处理多个控件及其多种取值组合的情况.以下是对正交表法的详细解释: 一.正交表法概述 正交表法是一种利用 ...
- Linux查看和操作文件内容命令
Linux查看和操作文件内容命令 文件查看命令 在Linux中,有多种命令可以帮助我们查看文件的内容.以下是其中一些常用的命令及其简要说明: cat命令 cat 命令用于显示文件的内容,特别适用于查看 ...
- 『Python底层原理』--CPython如何运行Python代码
Python作为一种广泛使用的编程语言,其简洁的语法和强大的功能深受开发者喜爱. 然而,对于许多Python用户来说,CPython(Python的官方实现)的内部工作机制仍然是一个神秘的黑盒. 今天 ...