Spring Boot 2.X(十):自定義注冊(cè) Servlet、Filter、Listener

前言

在 Spring Boot 中已經(jīng)移除了 web.xml 文件,如果需要注冊(cè)添加 Servlet、Filter、Listener 為 Spring Bean,在 Spring Boot 中有兩種方式:

  • 使用 Servlet 3.0 API 的注解 @WebServlet、@WebFilter、@Listener 用來配置。
  • Spring Boot JavaConfig 注解配置 Bean 的方式來進(jìn)行配置。

注冊(cè)之前

在使用 Servlet 時(shí),需要在 Spring Boot 入口類添加 @ServletComponentScan 注解,告訴 Spring Boot 去掃描使用下面注冊(cè)的 Servlet、Filter、Listener。

@SpringBootApplication
@ServletComponentScan
public class SpringBootServletApplication {

    public static void main(String[] args) {
        SpringApplication.run(SpringBootServletApplication.class, args);
    }

}

注冊(cè) Servlet

1.@WebServlet 屬性

屬性 類型 描述
name String 指定Servlet名稱,等價(jià)于 <servlet-name>
value String[] 等同于 urlPatterns 屬性,兩者不應(yīng)該同時(shí)使用
urlPatterns String[] 指定一組 Servlet 的 URL 匹配模式。等價(jià)于<url-pattern>標(biāo)簽
loadOnStartup int 指定 Servlet 的加載順序,等價(jià)于 <load-on-startup>標(biāo)簽
initParams WebInitParam[] 指定一組 Servlet 初始化參數(shù),等價(jià)于<init-param>標(biāo)簽
asyncSupported boolean 聲明 Servlet 是否支持異步操作模式,等價(jià)于<async-supported> 標(biāo)簽
smallIcon String 此 Servlet 的小圖標(biāo)
largeIcon String 此 Servlet 的大圖標(biāo)
description String 該 Servlet 的描述信息,等價(jià)于 <description>標(biāo)簽
displayName String 該 Servlet 的顯示名,通常配合工具使用,等價(jià)于 <display-name>標(biāo)簽

2.示例

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

    /**
     * 
     */
    private static final long serialVersionUID = -3325041776508043481L;

    @Override
    public void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
        doPost(req, resp);
    }
    /*
    *  實(shí)現(xiàn)請(qǐng)求uri和header打印,另外返回一個(gè)json
    */
    @Override
    public void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException {
        System.out.println("RequestURI:" + req.getRequestURI());

        System.out.println("Request Headers:");

        StringBuilder sb = new StringBuilder();
        Enumeration<?> names = req.getHeaderNames();
        while (names.hasMoreElements()) {
            String name = names.nextElement().toString();
            Enumeration<?> hs = req.getHeaders(name);
            sb.append(name).append(":");
            while (hs.hasMoreElements()) {
                sb.append(hs.nextElement()).append(";");
            }
        }
        System.out.println(sb);
        
        ObjectMapper om=new ObjectMapper();
        UserEntity user=new UserEntity();
        user.setId(1L);
        user.setUserName("zwqh");
        user.setUserSex("男");
        user.setHeaders(sb.toString());
        String resultJson=om.writeValueAsString(user);

        resp.setContentType("application/json;charset=UTF-8");
        
        resp.getWriter().print(resultJson);
    }

}

其中@WebServlet(urlPatterns = "/TestServlet")等價(jià)于以下代碼:

<servlet>
<!-- 類名 -->
<servlet-name> TestServlet </servlet-name>
<!-- 所在的包 -->
<servlet-class> cn.zwqh.springbboot.servlet.TestServlet </servlet-class>
</servlet>
<servlet-mapping>
   <servlet-name> TestServlet </servlet-name>
   <!-- 訪問的url路徑地址 -->
   <url-pattern> /TestServlet </url-pattern>
</servlet-mapping>

3.測(cè)試

瀏覽器訪問 http://127.0.0.1:8080/TestServlet

image

日志輸出:
image

注冊(cè) Filter

1.@WebFilter 屬性

屬性 類型 描述
filterName String 指定Filter名稱,等價(jià)于 <filter-name>
value String[] 等同于 urlPatterns 屬性,兩者不應(yīng)該同時(shí)使用
urlPatterns String[] 指定一組 Filter 的 URL 匹配模式。等價(jià)于<url-pattern>標(biāo)簽
servletNames String[] 指定過濾器將應(yīng)用于哪些 Servlet。取值于 @WebServlet 中的 name 屬性,或者是 web.xml 中 <servlet-name> 的值
initParams WebInitParam[] 指定一組 Filter 初始化參數(shù),等價(jià)于<init-param>標(biāo)簽
dispatcherTypes DispatcherType[] 指定 Filter 的轉(zhuǎn)發(fā)模式,包括:ASYNC、ERROR、FORWARD、INCLUDE、REQUEST
asyncSupported boolean 聲明 Filter 是否支持異步操作模式,等價(jià)于<async-supported> 標(biāo)簽
smallIcon String 此 Filter 的小圖標(biāo)
largeIcon String 此 Filter 的大圖標(biāo)
description String 該 Filter 的描述信息,等價(jià)于 <description>標(biāo)簽
displayName String 該 Filter 的顯示名,通常配合工具使用,等價(jià)于 <display-name>標(biāo)簽

2.示例

@WebFilter(urlPatterns = { "/TestServlet" }) // 注冊(cè)攔截器,并添加攔截路徑‘/TestServlet’
public class TestFilter implements Filter {

    /**
     * 初始化,只在項(xiàng)目啟動(dòng)的時(shí)候執(zhí)行一次
     */
    @Override
    public void init(FilterConfig filterConfig) {
        System.out.println("===> TestFilter init");
    }
    /**
    * 用于存放過濾器的業(yè)務(wù)邏輯實(shí)現(xiàn)代碼
    */
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {

        chain.doFilter(request, response);// 處理請(qǐng)求和響應(yīng)的分界線
        System.out.println("===> chain.doFilter 后執(zhí)行處理 response 的相關(guān)方法");
        // 在response header里設(shè)置一個(gè)token
        setToken(response);

    }

    private void setToken(ServletResponse response) {
        HttpServletResponse res = (HttpServletResponse) response;
        String token = UUID.randomUUID().toString();
        res.setHeader("Token", token);
        System.out.println("===> 設(shè)置了token:" + token);
    }

    /**
     * 銷毀,在項(xiàng)目關(guān)閉,Servlet 容器銷毀前調(diào)用
     */
    @Override
    public void destroy() {
        System.out.println("===> TestFilter destroy");
    }

}

3.測(cè)試

瀏覽器訪問 http://127.0.0.1:8080/TestServlet

image

日志打印:
image

4.Filter 主要使用場(chǎng)景

  • 禁用瀏覽器的緩存(緩存的處理)
  • 解決中文亂碼問題
  • 登錄鑒權(quán)及權(quán)限管理
  • 用戶授權(quán),負(fù)責(zé)檢查用戶的請(qǐng)求,根據(jù)請(qǐng)求過濾用戶非法請(qǐng)求
  • 日志記錄,詳細(xì)記錄某些特殊的用戶請(qǐng)求
  • 其他場(chǎng)景

注冊(cè) Listener

1.@Listener 屬性

屬性 類型 描述
value String 偵聽器Listener的描述

2.示例

與 ServletContext 相關(guān)的監(jiān)聽

Servlet 的監(jiān)聽器 Listener 是實(shí)現(xiàn)了 javax.servlet.ServletContextListener 接口的服務(wù)器端程序,隨著 Web 應(yīng)用啟動(dòng)而啟動(dòng),只初始化一次,也隨著 Web 應(yīng)用停止而銷毀。其主要作用是做一些初始化的內(nèi)容添加工作,如參數(shù)和對(duì)象等。

@WebListener
public class ContextListener implements ServletContextListener, ServletContextAttributeListener{

    public static final String INITIAL_CONTENT = "Content created in servlet Context";

    /**
     * ServletContext創(chuàng)建
     */
    @Override
    public void contextInitialized(ServletContextEvent sce) {
        System.out.println("===> context initialized");
        ServletContext servletContext = sce.getServletContext();
        servletContext.setAttribute("content", INITIAL_CONTENT);
    }

    /**
     * ServletContext銷毀
     */
    @Override
    public void contextDestroyed(ServletContextEvent sce) {
        System.out.println("===> context destroyed");
    }

    /**
     * context屬性新增
     */
    @Override
    public void attributeAdded(ServletContextAttributeEvent scae) {
        System.out.println("===> context attribute added");
    }

    /**
     * context屬性移除
     */
    @Override
    public void attributeRemoved(ServletContextAttributeEvent scae) {
        System.out.println("===> context attribute removed");
    }

    /**
     * context屬性替換
     */
    @Override
    public void attributeReplaced(ServletContextAttributeEvent scae) {
        System.out.println("===> context attribute replaced");
    }
}
與 HttpSession 相關(guān)的監(jiān)聽
@WebListener
public class SessionListener implements HttpSessionListener, HttpSessionIdListener, HttpSessionAttributeListener,
        HttpSessionActivationListener {

    /**
     * session被創(chuàng)建時(shí)
     */
    @Override
    public void sessionCreated(HttpSessionEvent se) {
        System.out.println("===> session created");
    }

    /**
     * session被銷毀時(shí)
     */
    @Override
    public void sessionDestroyed(HttpSessionEvent se) {
        System.out.println("===> session destroyed");
    }

    /**
     * sessionId改變
     */
    @Override
    public void sessionIdChanged(HttpSessionEvent se, String oldSessionId) {
        System.out.println("===> session id changed");
    }

    /**
     * session屬性新增
     */
    @Override
    public void attributeAdded(HttpSessionBindingEvent se) {
        System.out.println("===> session attribute added");
    }

    /**
     * session屬性移除
     */
    @Override
    public void attributeRemoved(HttpSessionBindingEvent se) {
        System.out.println("===> session attribute removed");
    }

    /**
     * session屬性替換
     */
    @Override
    public void attributeReplaced(HttpSessionBindingEvent se) {
        System.out.println("===> session attribute replaced");
    }
    /**
     * session的鈍化,內(nèi)存的數(shù)據(jù)寫入到硬盤上的過程。
     */
    @Override
    public void sessionWillPassivate(HttpSessionEvent se) {
        System.out.println("===> session will passivate");
    }
    /**
     * session的活化,將硬盤的數(shù)據(jù)恢復(fù)到內(nèi)存中。
     */
    @Override
    public void sessionDidActivate(HttpSessionEvent se) {
        System.out.println("===> session did activate");
    }

}
與 ServletRequest 相關(guān)的監(jiān)聽
@WebListener
public class RequestListener implements ServletRequestListener,ServletRequestAttributeListener {
    /**
     * 請(qǐng)求即將進(jìn)入Web應(yīng)用程序的范圍/請(qǐng)求初始化時(shí)
     */
    @Override
    public void requestInitialized(ServletRequestEvent sre) {
        System.out.println("===> request initialized");
    }
    /**
     * 請(qǐng)求即將進(jìn)入Web應(yīng)用程序的范圍/請(qǐng)求銷毀時(shí)
     */
    @Override
    public void requestDestroyed(ServletRequestEvent sre) {
        System.out.println("===> request destroyed");
    }
    /**
     * request屬性新增
     */
    @Override
    public void attributeAdded(ServletRequestAttributeEvent srae) {
        System.out.println("===> request attribute added");
    }
    /**
     * request屬性移除
     */
    @Override
    public void attributeRemoved(ServletRequestAttributeEvent srae) {
        System.out.println("===> request attribute removed");
    }
    /**
     * request屬性替換
     */
    @Override
    public void attributeReplaced(ServletRequestAttributeEvent srae) {
        System.out.println("===> request attribute replaced");
    }
}

3.項(xiàng)目相關(guān)日志輸入(啟動(dòng)和停止)

image

先執(zhí)行 contextInitialzed 方法在執(zhí)行 TestFilter 類的 init 方法,
contextDestroyed 方法在 TestFilter 類 destroy 方法執(zhí)行后執(zhí)行。

示例代碼

github

碼云

非特殊說明,本文版權(quán)歸 朝霧輕寒 所有,轉(zhuǎn)載請(qǐng)注明出處.

原文標(biāo)題:Spring Boot 2.X(十):自定義注冊(cè) Servlet、Filter、Listener

原文地址: https://www.zwqh.top/article/info/17

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容