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

发布于:2025-03-20 ⋅ 阅读:(16) ⋅ 点赞:(0)

目录

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(new
            MyServlet(),"/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 请求
    @Override
    protected 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 请求
    @Override
    protected 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 {

    // 过滤器初始化方法,在过滤器创建时调用
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        // 可以在这里进行一些初始化操作,例如读取配置文件等
        System.out.println("MyFilter 初始化");
    }

    // 过滤方法,每次请求匹配到该过滤器时都会调用
    @Override
    public 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 方法将请求传递给下一个过滤器或目标 Servlet
        chain.doFilter(request, response);

        System.out.println("MyFilter 处理完响应");
    }

    // 过滤器销毁方法,在过滤器销毁时调用
    @Override
    public void destroy() {
        // 可以在这里进行一些资源释放操作,例如关闭数据库连接等
        System.out.println("MyFilter 销毁");
    }
}

3. 监听器Listener

监听器作用

        在 Spring Boot 应用启动期间,有多个关键阶段,例如上下文刷新前、刷新后等。通过自定义监听器监听这些事件,你可以在特定阶段执行初始化操作,像加载配置、初始化缓存等。

        当应用关闭时,你可以监听相应事件,进行资源释放、数据保存等收尾工作。

        借助监听器,你可以实现事件驱动架构,把不同业务逻辑解耦。例如,当用户注册成功后,触发一个用户注册事件,其他监听器可以监听该事件并执行相应操作,如发送欢迎邮件、添加积分等。

@Bean
public ServletListenerRegistrationBean myListener(){
    ServletListenerRegistrationBean<MyListener> registrationBean = new
            ServletListenerRegistrationBean<>(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 被创建时调用
    @Override
    public void contextInitialized(ServletContextEvent sce) {
        // 可以在这里进行一些初始化操作,例如加载配置文件、初始化数据库连接池等
        System.out.println("ServletContext 初始化,应用启动");
    }

    // 当 ServletContext 被销毁时调用
    @Override
    public 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)配置项目的目录结构

 

 

 

或者如果在Maven项目里,可以直接创建这三个包和xml文件,然后再打开刚才那个位置(配置目录结构)配置

 

4)部署Tomcat

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


public class ServletInitializer extends SpringBootServletInitializer {

   @Override
   protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
      //传入SpringBoot应用的主程序
      return application.sources(RomateservletApplication.class);
   }

}

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

原理

        jar包:

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

        war包:

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

在yml配置文件里,设置视图解析器前缀,后缀

外置的Servlet容器是访问jsp的。