SpringBoot第三站:配置嵌入式服务器使用外置的Servlet容器

目录

1. 配置嵌入式服务器

1.1 如何定制和修改Servlet容器的相关配置

1.server.port=8080

2. server.context-path=/tx

3. server.tomcat.uri-encoding=UTF-8

1.2 注册Servlet三大组件【Servlet,Filter,Listener】

1. servlet

2. filter

3. 监听器Listener

2. 使用外置的Servlet容器

步骤

1)必须创建一个war项目;

2)将嵌入式的Tomcat指定为provided;

3)配置项目的目录结构

4)部署Tomcat

5)必须编写一个SpringBootServletInitializer的子类,并调用configure方法

6)启动服务器就可以使用;


1. 配置嵌入式服务器

1.1 如何定制和修改Servlet容器的相关配置

修改和server有关的配置(ServerProperties)

server.port=8080
server.context‐path=/tx
server.tomcat.uri‐encoding=UTF‐8

1.server.port=8080

  • 含义:该配置项用于指定 Spring Boot 应用启动时所监听的端口号。在 Web 应用中,服务器需要监听一个特定的端口来接收客户端的 HTTP 请求,这里将端口号设置为 8080
  • 示例说明:当启动应用后,在浏览器中输入 http://localhost:8080 (假设应用运行在本地),就可以访问该应用。如果该端口已被其他应用占用,Spring Boot 应用启动时会报错,你需要修改此端口号为其他未被占用的值,如 80819090 等。

2. server.context-path=/tx

  • 含义:此配置项用于设置应用的上下文路径。上下文路径是 URL 中位于主机名和端口号之后、具体请求路径之前的部分,它相当于为应用设置了一个访问前缀。
  • 示例说明:若配置了 server.context-path=/tx,当应用启动后,要访问应用中的资源,URL 就需要加上这个上下文路径。例如,原本访问应用首页的 URL 是 http://localhost:8080,现在则变为 http://localhost:8080/tx。如果要访问某个控制器中映射路径为 /hello 的方法,完整的 URL 就是 http://localhost:8080/tx/hello

3. server.tomcat.uri-encoding=UTF-8

  • 含义:该配置项用于指定 Tomcat 服务器在处理请求 URI 时所使用的字符编码。字符编码决定了如何将字节数据转换为字符数据,设置为 UTF-8 可以确保在处理包含中文、特殊符号等多语言字符的 URI 时不会出现乱码问题。
  • 示例说明:当客户端发送的请求 URI 中包含中文参数,如 http://localhost:8080/tx/search?keyword=你好,服务器会按照 UTF-8 编码来解析这个 URI,从而正确获取到 keyword 参数的值为 你好。如果不设置这个编码,可能会导致解析后的参数值出现乱码。

1.2 注册Servlet三大组件【Servlet,Filter,Listener】

        由于SpringBoot默认是以jar包的方式启动嵌入式的Servlet容器来启动SpringBoot的web应用,没有web.xml文件。

1. servlet

//注册三大组件
@Bean
public ServletRegistrationBean myServlet(){ServletRegistrationBean registrationBean = new ServletRegistrationBean(newMyServlet(),"/myServlet");return registrationBean;
}
package com.qcby.servlet;import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;public class MyServlet extends HttpServlet{// 重写 doGet 方法来处理 GET 请求@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {// 设置响应内容类型resp.setContentType("text/html;charset=UTF-8");// 获取响应输出流PrintWriter out = resp.getWriter();// 输出响应内容out.println("<html>");out.println("<head><title>My Servlet</title></head>");out.println("<body>");out.println("<h1>这是自定义 Servlet 的响应内容</h1>");out.println("</body>");out.println("</html>");}// 重写 doPost 方法来处理 POST 请求@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {doGet(req, resp);}
}

        自己写MyServlet类继承HttpServlet类来实现一个标准的 Servlet,并且要重写doGet 或 doPost 等方法来处理 HTTP 请求

2. filter

@Bean
public FilterRegistrationBean myFilter(){FilterRegistrationBean registrationBean = new FilterRegistrationBean();registrationBean.setFilter(new MyFilter());registrationBean.setUrlPatterns(Arrays.asList("/hello","/myServlet"));return registrationBean;
}

        MyFilter 类需要实现 javax.servlet.Filter 接口,并重写接口中的 init、doFilter 和 destroy 方法,这样才能成为一个标准的过滤器。

package com.qcby.servlet;import javax.servlet.*;
import java.io.IOException;public class MyFilter implements Filter {// 过滤器初始化方法,在过滤器创建时调用@Overridepublic void init(FilterConfig filterConfig) throws ServletException {// 可以在这里进行一些初始化操作,例如读取配置文件等System.out.println("MyFilter 初始化");}// 过滤方法,每次请求匹配到该过滤器时都会调用@Overridepublic void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)throws IOException, ServletException {// 在请求处理之前可以进行一些预处理操作,例如设置字符编码request.setCharacterEncoding("UTF-8");response.setCharacterEncoding("UTF-8");System.out.println("MyFilter 开始过滤请求");// 调用 FilterChain 的 doFilter 方法将请求传递给下一个过滤器或目标 Servletchain.doFilter(request, response);System.out.println("MyFilter 处理完响应");}// 过滤器销毁方法,在过滤器销毁时调用@Overridepublic void destroy() {// 可以在这里进行一些资源释放操作,例如关闭数据库连接等System.out.println("MyFilter 销毁");}
}

3. 监听器Listener

@Bean
public ServletListenerRegistrationBean myListener(){ServletListenerRegistrationBean<MyListener> registrationBean = newServletListenerRegistrationBean<>(new MyListener());return registrationBean;
}

        MyListener 类需要实现 Servlet 监听器接口,这样才能发挥监听器的作用。Servlet 监听器有多种类型,常见的有 ServletContextListener(用于监听 ServletContext 的创建和销毁)、HttpSessionListener(用于监听 HttpSession 的创建和销毁)、ServletRequestListener(用于监听 ServletRequest 的创建和销毁)等

package com.qcby.servlet;import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;public class MyListener implements ServletContextListener {// 当 ServletContext 被创建时调用@Overridepublic void contextInitialized(ServletContextEvent sce) {// 可以在这里进行一些初始化操作,例如加载配置文件、初始化数据库连接池等System.out.println("ServletContext 初始化,应用启动");}// 当 ServletContext 被销毁时调用@Overridepublic void contextDestroyed(ServletContextEvent sce) {// 可以在这里进行一些资源释放操作,例如关闭数据库连接池等System.out.println("ServletContext 销毁,应用关闭");}
}
  • contextInitialized 方法:当 ServletContext 被创建时调用,通常用于执行一些初始化操作,如加载配置文件、初始化数据库连接池等。
  • contextDestroyed 方法:当 ServletContext 被销毁时调用,通常用于执行一些资源释放操作,如关闭数据库连接池等。
        将 MyListener  注册为监听器。这样,当应用启动和关闭时,MyListener  中的 contextInitialized  和 contextDestroyed  方法会相应地被调用。
        SpringBoot帮我们自动SpringMVC的时候,自动的注册SpringMVC的前端控制器DispatcherServlet;
DispatcherServletAutoConfiguration中:


2. 使用外置的Servlet容器

嵌入式Servlet容器:应用打成可执行的jar

        优点:简单、便携;

        缺点:默认不支持JSP、优化定制比较复杂.;

外置的Servlet容器:外面安装Tomcat---应用war包的方式打包;

步骤

1)必须创建一个war项目;

jar包和war包:

        springboot的jar包是一个可执行的归档文件,它遵循 “胖 JAR”(Fat JAR)的理念,即将应用程序代码、依赖的所有库(包括 Spring Boot 自身的库)以及嵌入式服务器(如 Tomcat、Jetty 等)都打包在一个 JAR 文件中。

        WAR(Web Application Archive)包是传统的 Web 应用程序打包格式,主要用于部署到外部的 Servlet 容器(如 Tomcat、WebLogic 等)中。它的结构遵循标准的 Web 应用程序目录结构,不包含嵌入式服务器。

(利用idea创建好目录结构)

2)将嵌入式的Tomcat指定为provided;

        如果要将 Spring Boot 项目打包成 WAR 包,需要进行一些额外的配置。以 Maven 为例,需要在pom.xml中进行如下配置:

<packaging>war</packaging><dependencies><!-- 排除嵌入式Tomcat依赖 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId><exclusions><exclusion><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-tomcat</artifactId></exclusion></exclusions></dependency>

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-tomcat</artifactId><scope>provided</scope>
</dependency>

3)配置项目的目录结构

 

 

 

4)部署Tomcat

5)必须编写一个SpringBootServletInitializer的子类,并调用configure方法


public class ServletInitializer extends SpringBootServletInitializer {@Overrideprotected SpringApplicationBuilder configure(SpringApplicationBuilder application) {//传入SpringBoot应用的主程序return application.sources(RomateservletApplication.class);}}

6)启动服务器就可以使用;

原理

        jar包:

                执行SpringBoot主类的main方法,启动ioc容器,创建嵌入式的Servlet容器;

        war包:

                启动服务器,服务器启动SpringBoot应用【SpringBootServletInitializer】,启动ioc容器;

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/73679.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Docker 使用指南

Docker 是一种开源的容器化平台&#xff0c;它通过使用容器来进行应用程序的打包、分发和部署。下面是 Docker 的基本概念和优势&#xff1a; 容器化&#xff1a;Docker 使用容器来封装应用程序及其所有依赖项&#xff0c;使其能够在任何环境中运行&#xff0c;并且与底层系统隔…

C# WPF编程-启动新窗口

C# WPF编程-启动新窗口 新建窗口&#xff1a; 工程》添加》窗口 命名并添加新的窗口 这里窗口名称为Window1.xaml 启动新窗口 Window1 win1 new Window1(); win1.Show(); // 非模态启动窗口win1.ShowDialog(); // 模态启动窗口 模态窗口&#xff1a;当一个模态窗口被打开时&a…

谈谈 undefined 和 null

*** 补充 null 和 ‘’

Ubuntu快速安装使用gRPC C++

目录 引言一、快速安装1. 安装必要依赖库2. 安装gRPC 二、测试使用三、参考博客 引言 关于gRPC随着云原生微服务的火热也流行了起来&#xff0c;而且学好一个gRPC框架对目前来说也是必须的了。然而对于一个基础的小白来说&#xff0c;这个gRPC的框架运用起来是及其的困难&…

高数1.5 极限的运算法则

1. 预备知识 2.四则求极限法则 3.复合运算求极限法则

Python中的“泛型”和“多重继承”

“泛型”和“多重继承”属于 Python 的语法规则。 1. 泛型&#xff08;Generic[T]&#xff09; 通俗解释 泛型允许你在定义类或函数时&#xff0c;不指定具体的类型&#xff0c;而是使用一个“占位符”&#xff08;通常命名为 T&#xff09;。这就像你制作一个盒子&#xff0…

pandas学习笔记(一)——基础知识和应用案例

pandas学习笔记 基础语法参考菜鸟教程&#xff1a;https://www.runoob.com/pandas/pandas-tutorial.html # jupyter import pandas as pd import matplotlib from matplotlib import pyplot as plt import numpy as npmatplotlib.use(TkAgg)data {timestamp: [1, 2, 3, 4, 5…

海绵音乐 3.4.0 | 免费AI音乐创作软件,支持多种风格智能生成

海绵音乐是一款专为Android用户设计的免费AI音乐创作软件&#xff0c;搭载深度神经网络作曲引擎&#xff0c;支持流行、电子、古风等12种音乐风格智能生成。提供多轨道编辑界面&#xff08;8轨同步混音&#xff09;&#xff0c;可自定义鼓点、旋律和和弦进行实时混音&#xff0…

2025 香港 Web3 嘉年华:全球 Web3 生态的年度盛会

自 2023 年首届香港 Web3 嘉年华成功举办以来&#xff0c;这一盛会已成为全球 Web3 领域规模最大、影响力最深远的行业活动之一。2025 年 4 月 6 日至 9 日&#xff0c;第三届香港 Web3 嘉年华将在香港盛大举行。本届活动由万向区块链实验室与 HashKey Group 联合主办、W3ME 承…

【Dify平台】Function Call 模式模式和ReAct模型有什么不同?

本文原创作者:姚瑞南 AI-agent 大模型运营专家,先后任职于美团、猎聘等中大厂AI训练专家和智能运营专家岗;多年人工智能行业智能产品运营及大模型落地经验,拥有AI外呼方向国家专利与PMP项目管理证书。(转载需经授权) 目录 1. DIFY 平台的 Function Call 模式 2. ReAct…

解决 React Native 0.76 中 com.facebook.react.settings 插件缺失问题

在使用 React Native 0.76 创建项目时&#xff0c;遇到以下错误&#xff1a; FAILURE: Build failed with an exception. * Where: Settings file /Users/wangxp/learn/AwesomeProject/android/settings.gradle line: 2 * What went wrong: Plugin [id: com.facebook.react.se…

Linux目录结构以及文件操作

Linux目录结构以及文件操作 ubuntu属于Linux的发行版&#xff0c;带图形界面。但是跑在嵌入式设备中的Linux操作系统往往不带图形界面&#xff0c;直接使用命令来操作。Linux区分大小写。 在Linux系统上&#xff0c;文件被看作字节序列。 普通文件&#xff08;—&#xff09…

React19源码系列之FiberRoot节点和Fiber节点

在上一篇文章&#xff0c;看了createRoot函数的大致流程。 createContainer函数创建并返回了FiberRoot 。FiberRoot是由createFiberRoot函数创建&#xff0c; createFiberRoot函数还将 FiberRoot和 根Fiber 通过current属性建立起了联系。将FiberRoot作为参数传给 ReactDOMRoo…

vue3+antd+a-menu配置

antd是用的3版本 <a-menu v-model:selectedKeys"selectedKeys" mode"inline" click"toPage"><template v-for"i in menus"><a-menu-item v-if"!i.children" :key"i.path"><span>{{ i.nam…

【2025年3月最新】Cities_Skylines:城市天际线1全DLC解锁下载与教程

亲测2025年3月11日能用&#xff0c;能解锁全部DLC 使用教程 点击下载 点击下载

基于Django的交通指示图像识别分析系统

【Django】基于Django的交通指示图像识别分析系统 &#xff08;完整系统源码开发笔记详细部署教程&#xff09;✅ 目录 一、项目简介二、项目界面展示三、项目视频展示 一、项目简介 本项目旨在通过大量交通标志数据训练后&#xff0c;得到较好的识别模型&#xff0c;便于用户…

SAP HANA on AWS Amazon Web Services

SAP HANA on AWS Amazon Web Services

【设计模式】】工厂模式

三、工厂模式 3.1 工厂模式 创建一个类对象的传统方式是使用关键字new, 因为用new 创建的类对象是一个堆对象&#xff0c;可以实现多态。工厂模式通过把创建对象的代码包装起来&#xff0c;实现创建对象的代码与具体 的业务逻辑代码相隔离的目的(将对象的创建和使用进行解耦)…

单片机外设快速入门篇(五)——GPIO篇

文章目录 一、GPIO输入模式​二.GPIO输出模式三.GPIO配置步骤 一、GPIO输入模式 ​1. 浮空输入&#xff08;Floating Input&#xff09;​ ​原理&#xff1a;引脚电平完全由外部电路决定&#xff0c;无内部上拉或下拉电阻。 ​特点&#xff1a; 悬空时电平不确定&#xff08;…

Python递归与递推的练习(初步了解复杂度,全排列的价值,奇妙的变换,数正方形,高塔登顶方案)

一.了解复杂度 1.1 为什么要考虑复杂度 在比赛中&#xff0c;编程题会有时间和空间的限制&#xff0c;所以我们需要根据时间复杂度和空间复杂度来判断用什么样的算法。 在本章中递归的时间复杂度比递推慢好多所有我们在写代码时对递归和递推的选择中应该尽量考虑递推。 复杂度…