熵增學院-Anders-劍走偏鋒,瞭解Spring Boot內部Servlet容器 頂 原

還記得大明湖畔的servlet嗎?其實Spring Boot支持內嵌的Tomcat, Jetty和Undertow服務器,多數開發者只需要使用合適的'Starter'來獲取一個完全配置好的實例即可,內嵌服務器默認監聽8080端口的HTTP請求。

這樣子是不是覺得很簡單,很方便,有種開發nodejs的感覺.....

 

1. 在SpringBoot中還有Servlets, Filters和listeners嗎?

使用內嵌servlet容器時,你可以通過使用Spring beans或掃描Servlet組件的方式註冊Servlets,Filters及特定Servlet相關的所有listeners(比如HttpSessionListener)。

將Servlets,Filters和listeners註冊爲Spring beans

所有ServletFilter或Servlet *Listener實例,只要是Spring bean,都會註冊到內嵌容器中。如果想在配置期間引用application.properties的屬性,這是非常方便的。默認情況下,如果上下文只包含單個Servlet,那它將被映射到/。如果存在多個Servlet beans,那麼bean的名稱將被用作路徑的前綴,過濾器將映射到/*

如果基於約定(convention-based)的映射不夠靈活,你可以使用ServletRegistrationBeanFilterRegistrationBeanServletListenerRegistrationBean實現完全的控制。

 

1 創建servlet

package com.gala.servlet;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class TestServlet extends HttpServlet {    
  private static final long serialVersionUID = -2646554587718007415L;    
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {        
    // 設置返回類型爲json
        resp.setContentType("application/json");        
        // 設置返回字符集
        resp.setCharacterEncoding("UTF-8");        
        // 輸出對象
        PrintWriter writer = resp.getWriter();        
        // 輸出error消息
        writer.write("成功執行doGet方法");
        writer.close();
    }
}

2 使用Bean註冊Servlet(單個Servlet)

package com.gala.servlet.conf;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import com.gala.servlet.TestServlet;
@Configuration
public class ServletConfiguration {    
        @Bean
    public ServletRegistrationBean<TestServlet> servletRegistrationBean() {        
        return new ServletRegistrationBean<TestServlet>(new TestServlet(), "/test");
    }
}

 

SpringBoot自動裝配Servlet(多個Servlet)

 

SpringBoot內部提供了註解@ServletComponentScan,這個註解的作用就是自動掃描我們SpringBoot項目內的有關Servlet配置,自動裝配到我們的項目中。

 

TestServlet需要與ServletConfiguration同目錄或在其子目錄中

 

修改ServletConfiguration,增加@ServletComponentScan

package com.gala.servlet.conf;

import org.springframework.boot.web.servlet.ServletComponentScan;
import org.springframework.context.annotation.Configuration;

@Configuration
@ServletComponentScan
public class ServletConfiguration {

}

修改TestServlet,增加@WebServlet(urlPatterns = "/test2")

package com.gala.servlet;

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet(urlPatterns = "/test2")
public class TestServlet extends HttpServlet {

    private static final long serialVersionUID = -2646554587718007415L;

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 設置返回類型爲json
        resp.setContentType("application/json");
        // 設置返回字符集
        resp.setCharacterEncoding("UTF-8");
        // 輸出對象
        PrintWriter writer = resp.getWriter();
        // 輸出error消息
        writer.write("成功執行doGet方法");
        writer.close();
    }
}

 

 

2. 在Filters和listeners怎麼使用

 

內嵌servlet容器不會直接執行Servlet 3.0+的javax.servlet.ServletContainerInitializer接口,或Spring的org.springframework.web.WebApplicationInitializer接口,這樣設計的目的是降低war包內運行的第三方庫破壞Spring Boot應用的風險。

如果需要在Spring Boot應用中執行servlet上下文初始化,你需要註冊一個實現org.springframework.boot.context.embedded.ServletContextInitializer接口的bean。onStartup方法可以獲取ServletContext,如果需要的話可以輕鬆用來適配一個已存在的WebApplicationInitializer。

掃描Servlets, Filters和listeners

當使用一個內嵌容器時,通過@ServletComponentScan可以啓用對註解@WebServlet,@WebFilter和@WebListener類的自動註冊。

注 在獨立的容器(非內嵌)中@ServletComponentScan不起作用,取爲代之的是容器內建的discovery機制。

 

3. 自定義配置servlet容器

 

常見的Servlet容器配置可以通過Spring Environment進行設置,通常將這些屬性定義到application.properties文件中。

常見的服務器配置包括:

網絡設置:監聽進入Http請求的端口(server.port),接口綁定地址server.address等。

Session設置:session是否持久化(server.session.persistence),session超時時間(server.session.timeout),session數據存放位置(server.session.store-dir),session-cookie配置(server.session.cookie.*)。

Error管理:錯誤頁面的位置(server.error.path)等。

SSL。

HTTP壓縮

 

Spring Boot會盡量暴露常用設置,但這並不總是可能的。對於不可能的情況,可以使用專用的命名空間提供server-specific配置(查看server.tomcat,server.undertow)。例如,可以根據內嵌servlet容器的特性對access logs進行不同的設置。

注 具體參考ServerProperties。

 

4. 老生常談的JSP

 

當使用內嵌servlet容器運行Spring Boot應用時(並打包成一個可執行的存檔archive),容器對JSP的支持有一些限制

Tomcat只支持war的打包方式,不支持可執行jar。

Jetty只支持war的打包方式。

Undertow不支持JSPs。

創建的自定義error.jsp頁面不會覆蓋默認的error handling視圖。

本文相關視頻

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章