Spring Boot 2.x 嵌入式 Servlet 容器

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,集群版 2核4GB 100GB
推荐场景:
搭建个人博客
云原生数据库 PolarDB MySQL 版,Serverless 5000PCU 100GB
简介: Spring Boot使用内嵌Tomcat,默认端口8080,可通过`application.properties`配置端口、上下文路径等。配置方式有两种:1) 直接在配置文件中添加`server.port`和`server.servlet.context-path`;2) 创建`WebServerFactoryCustomizer` Bean来自定义配置,如设置端口`factory.setPort(8083)`,这种方式优先级更高。

一、修改Spring Boot 中内嵌Servlet容器的默认配置

Spring Boot提供了默认提供了内嵌的Tomcat,可以通过命令行运行jar包的方式运行Spring Boot应用,spring-boot-start-web依赖中包含了Tomcat依赖,最新版本为9.0.62。

以往通过Tomcat容器运行Spring应用时,可以通过修改Tomcat的一些配置文件来修改Tomcat的运行状态,比如说端口号等,那么Spring Boot内嵌的Tomcat要如何修改?

有两种方式修改内置Tomcat的配置,第一种是在application.properties中添加tomcat配置和server配置

第二种方式是编写一个WebServerFactoryCustomizer来进行tomcat的配置,在SpringBoot1.x的时候使用的是EmbeddedServletContainerCustomizer到SpringBoot2.x后WebServerFactoryCustomizer替代了EmbeddedServletContainerCustomizer。

java

代码解读

复制代码

@Configuration
public class LilithMvcConfig implements WebMvcConfigurer {
    
    @Bean
    public WebServerFactoryCustomizer<ConfigurableWebServerFactory> customizer(){
        return factory -> {
            factory.setPort(8083);
        };
    }
}

注释application.properties中的配置,重新启动该应用配置生效,tomcat在8083端口启动

这两种配置的优先级是怎样的?

在application.properties中配置

properties

代码解读

复制代码

server.port=8081
server.servlet.context-path=/servlet

保持WebServerFactoryCustomizer中配置的端口不变,重启应用

控制台输出端口号为8083,路径为/servlet,可以确定重写WebServerFactoryCustomizer配置Tomcat的优先级更高,并且和application.properties是互补的。

二、Spring Boot中注册Servlet、Filter、Listener

在Java Web项目中,我们书写的Servlet、Filter、Listener组件都可以通过web.xml将这些组件配置到Tomcat容器中,那么在Spring Boot项目中使用内置Tomcat并且没有web.xml的情况如何注册这些组件?

Spring Boot为Java Web三大组件提供了通过XxxRegistrationBean的方式进行注册

ServletRegistrationBean注册Servlet

创建一个HalloServelet类继承HttpServlet类,并重写doGet()和doPost()方法

java

代码解读

复制代码

public class HalloServlet extends HttpServlet {

    // 处理get请求
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doPost(req,resp);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        resp.getWriter().write("Hallo Servlet");
    }
}

使用ServletRegisterBean,代替在web.xml中注册Servlet,在LilithMvcConfig中增加代码

java

代码解读

复制代码

// 注册Servlet
@Bean
public ServletRegistrationBean<HalloServlet> halloServletServletRegistrationBean(){
    ServletRegistrationBean registrationBean = new ServletRegistrationBean();
    registrationBean.setServlet(new HalloServlet());
    registrationBean.setUrlMappings(Collections.singleton("/hallo"));
    return registrationBean;
}

重启应用,在浏览器访问/hallo浏览器能够正常显示内容,自定义的Servlet成功注册。

FilterRegistrationBean注册Filter

首先自定义一个LilithFilter类实现Filter接口,在打印日志后放行请求

java

代码解读

复制代码

public class LilithFilter implements Filter {

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {

        System.out.println("LilithFilter running");
        chain.doFilter(request,response);
    }
}

在LilithMvcConfig配置类中通过FilterRegistrationBean注册自定义的LilithFilter,并在其中设置过滤器要拦截的请求路径

java

代码解读

复制代码

// 注册Filter
@Bean
public FilterRegistrationBean<LilithFilter> lilithFilterFilterRegistrationBean(){
    FilterRegistrationBean<LilithFilter> filterFilterRegistrationBean = new FilterRegistrationBean<>();
    filterFilterRegistrationBean.setFilter(new LilithFilter());
    // 设置拦截的请求路径
    filterFilterRegistrationBean.setUrlPatterns(Arrays.asList("/hallo"));

    return filterFilterRegistrationBean;
}

重启应用,在浏览器输入 /hallo控制台输出自定义的LilithFilter类中的日志信息,自定义的LilithFilter注册成功并生效

在controller包中新增一个HiController,增加一个hi()方法,请求映射路径为/hi

java

代码解读

复制代码

@Controller
public class HiController {

    @RequestMapping("/hi")
    @ResponseBody
    public String hi(){
        return "Hi Lilith!";
    }
}

重启应用,浏览器访问/hi,看是否会拦截控制台没有输出LilithFilter中设置的日志信息,说明没有被拦截,因为LilithFilter过滤器中没有设置拦截该请求,需要注意的是如果LilithFilter中没有设置拦截任何请求,默认拦截所有请求包括静态资源,但是不会jsp请求; /* 会拦截jsp请求。

ServletListenerRegistrationBean注册Listener

增加一个LilithListener类实现Listener接口,实现contextInitialized()方法和contextDestroyed()方法,并打印日志信

java

代码解读

复制代码

public class LilithListener implements ServletContextListener {

    @Override
    public void contextInitialized(ServletContextEvent sce) {
        System.out.println("Web 应用启动了.......");
    }

    @Override
    public void contextDestroyed(ServletContextEvent sce) {
        System.out.println("Web 应用销毁了.......");
    }
}

在LilithMvcConfig配置类中通过ServletListenerRegistrationBean注册自定义的监听器LilithListener

java

代码解读

复制代码

@Bean
public ServletListenerRegistrationBean<LilithListener> servletListenerRegistrationBean(){
    ServletListenerRegistrationBean<LilithListener> servletListenerRegistrationBean = new ServletListenerRegistrationBean<>();
    servletListenerRegistrationBean.setListener(new LilithListener());
    return servletListenerRegistrationBean;
}

重启应用,查看控制台输出的日志信息应用启动和关闭时都输出了自定义监听器LilithListener中定义的内容,说明自定义的监听器生效

Spring MVC的前端控制器DispatcherServlet就是通过这种方式来注册的,首先定义了DispatcherServlet类

接着通过DispatcherServletRegistrationBean注册了DispatcherServlet


转载来源:https://juejin.cn/post/7089854261105786910

相关实践学习
日志服务之使用Nginx模式采集日志
本文介绍如何通过日志服务控制台创建Nginx模式的Logtail配置快速采集Nginx日志并进行多维度分析。
相关文章
|
1天前
|
XML Dubbo Java
Spring之Ioc容器
该文章主要介绍了Spring框架中的IoC(Inversion of Control,控制反转)容器,包括IoC容器的概念、IoC容器在Spring中的实现以及IoC容器的基础包等内容。
Spring之Ioc容器
|
1月前
|
XML Java 应用服务中间件
springboot定制嵌入式的servlet
SpringBoot允许定制嵌入式Servlet容器,如修改配置或更换默认的Tomcat。配置可通过`application.properties`设置`server.port`和`server.tomcat.*`属性。此外,可创建`EmbeddedServletContainerCustomizer` Bean来自定义容器,例如改变端口。要替换默认的Tomcat,需排除`spring-boot-starter-tomcat`依赖,并引入`spring-boot-starter-jetty`。
|
1月前
|
Java Spring 容器
深入理解Spring Boot中的容器与依赖注入
深入理解Spring Boot中的容器与依赖注入
|
3天前
|
Docker 容器
Docker cp 将宿主机上的文件复制到容器中
Docker cp 将宿主机上的文件复制到容器中
7 0
|
28天前
|
Shell Linux Docker
docker常用命令大全(基础、镜像、容器、数据卷)
这些命令仅仅是 Docker 命令行工具的冰山一角,但对于日常操作来说已经非常全面。通过熟练地使用这些基础命令,用户可以有效地管理 Docker 的镜像、容器、数据卷和网络。随着用户对 Docker 的深入使用,更高级的命令和选项将会变得必需,但上面列出的命令已经为用户提供了一个坚实的起点。对于初学者来说,理解和掌握这些常用命令是深入学习 Docker 的基础。
226 5
docker常用命令大全(基础、镜像、容器、数据卷)
|
9天前
|
Shell 云计算 Docker
零基础到容器技术大神,一键解锁Docker实战秘籍!从零搭建,见证你的技术飞跃,让代码在云端翩翩起舞!
【8月更文挑战第5天】在云计算与微服务当道的今天,容器技术如汹涌浪潮般席卷IT领域。对新手而言,它或许充满神秘,但无须担忧,让我们一同揭开它的面纱。容器是一种轻量级软件打包技术,允许应用及其依赖被打包,在独立的虚拟环境中运行。Docker作为容器界的明星,简化了容器的创建与管理。从安装Docker开始,运行首个容器,深入容器内部执行命令,直至构建自定义镜像,我们将逐步掌握这项关键技术。这不仅是一场技术之旅,更是思维方式的革新,让我们携手探索未来。
45 6
|
11天前
|
运维 Ubuntu Shell
Docker命令宝典:解锁容器化技术的无限可能,从镜像管理到容器操作,全面解析与实战指南!
【8月更文挑战第3天】Docker简化了应用的部署与运行,掌握其基本命令对开发者和运维人员至关重要。通过`docker images`可查看本地镜像;使用`docker pull`拉取如最新版Ubuntu镜像;`docker rmi`用于删除不再需要的镜像。运行容器可通过`docker run`命令,结合`-it`等选项提供交互式环境。`docker ps`显示运行中的容器,加上`-a`则列出所有容器。`docker stop`和`docker start`分别用于停止和重启容器,而`docker rm`则删除容器。
42 5
|
14天前
|
弹性计算 Linux Docker
云服务器 ECS产品使用问题之如何进入Docker容器修改孵蛋时间
云服务器ECS(Elastic Compute Service)是各大云服务商阿里云提供的一种基础云计算服务,它允许用户租用云端计算资源来部署和运行各种应用程序。以下是一个关于如何使用ECS产品的综合指南。
|
15天前
|
关系型数据库 分布式数据库 PolarDB
PolarDB产品使用问题之原PolarDB-X集群无法连接且Docker容器已经被删除,如何恢复数据
PolarDB产品使用合集涵盖了从创建与管理、数据管理、性能优化与诊断、安全与合规到生态与集成、运维与支持等全方位的功能和服务,旨在帮助企业轻松构建高可用、高性能且易于管理的数据库环境,满足不同业务场景的需求。用户可以通过阿里云控制台、API、SDK等方式便捷地使用这些功能,实现数据库的高效运维与持续优化。
|
18天前
|
Shell 应用服务中间件 nginx
docker 服务,镜像,容器命令总结
docker 服务,镜像,容器命令总结
107 4
下一篇
云函数