Spring Boot 2.X(十):自定义注册 Servlet、Filter、Listener

本文涉及的产品
日志服务 SLS,月写入数据量 50GB 1个月
简介: 前言 在 Spring Boot 中已经移除了 web.xml 文件,如果需要注册添加 Servlet、Filter、Listener 为 Spring Bean,在 Spring Boot 中有两种方式: 使用 Servlet 3.0 API 的注解 @WebServlet、@WebFilter、@Listener 用来配置。

前言

在 Spring Boot 中已经移除了 web.xml 文件,如果需要注册添加 Servlet、Filter、Listener 为 Spring Bean,在 Spring Boot 中有两种方式:

  • 使用 Servlet 3.0 API 的注解 @WebServlet、@WebFilter、@Listener 用来配置。
  • Spring Boot JavaConfig 注解配置 Bean 的方式来进行配置。

注册之前

在使用 Servlet 时,需要在 Spring Boot 入口类添加 @ServletComponentScan 注解,告诉 Spring Boot 去扫描使用下面注册的 Servlet、Filter、Listener。

@SpringBootApplication
@ServletComponentScan
public class SpringBootServletApplication {

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

}

注册 Servlet

1.@WebServlet 属性

属性 类型 描述
name String 指定Servlet名称,等价于
value String[] 等同于 urlPatterns 属性,两者不应该同时使用
urlPatterns String[] 指定一组 Servlet 的 URL 匹配模式。等价于标签
loadOnStartup int 指定 Servlet 的加载顺序,等价于 标签
initParams WebInitParam[] 指定一组 Servlet 初始化参数,等价于标签
asyncSupported boolean 声明 Servlet 是否支持异步操作模式,等价于 标签
smallIcon String 此 Servlet 的小图标
largeIcon String 此 Servlet 的大图标
description String 该 Servlet 的描述信息,等价于 标签
displayName String 该 Servlet 的显示名,通常配合工具使用,等价于 标签

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);
    }
    /*
    *  实现请求uri和header打印,另外返回一个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")等价于以下代码:

<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.测试

浏览器访问 http://127.0.0.1:8080/TestServlet

日志输出:

注册 Filter

1.@WebFilter 属性

属性 类型 描述
filterName String 指定Filter名称,等价于
value String[] 等同于 urlPatterns 属性,两者不应该同时使用
urlPatterns String[] 指定一组 Filter 的 URL 匹配模式。等价于标签
servletNames String[] 指定过滤器将应用于哪些 Servlet。取值于 @WebServlet 中的 name 属性,或者是 web.xml 中 的值
initParams WebInitParam[] 指定一组 Filter 初始化参数,等价于标签
dispatcherTypes DispatcherType[] 指定 Filter 的转发模式,包括:ASYNC、ERROR、FORWARD、INCLUDE、REQUEST
asyncSupported boolean 声明 Filter 是否支持异步操作模式,等价于 标签
smallIcon String 此 Filter 的小图标
largeIcon String 此 Filter 的大图标
description String 该 Filter 的描述信息,等价于 标签
displayName String 该 Filter 的显示名,通常配合工具使用,等价于 标签

2.示例

@WebFilter(urlPatterns = { "/TestServlet" }) // 注册拦截器,并添加拦截路径‘/TestServlet’
public class TestFilter implements Filter {

    /**
     * 初始化,只在项目启动的时候执行一次
     */
    @Override
    public void init(FilterConfig filterConfig) {
        System.out.println("===> TestFilter init");
    }
    /**
    * 用于存放过滤器的业务逻辑实现代码
    */
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {

        chain.doFilter(request, response);// 处理请求和响应的分界线
        System.out.println("===> chain.doFilter 后执行处理 response 的相关方法");
        // 在response header里设置一个token
        setToken(response);

    }

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

    /**
     * 销毁,在项目关闭,Servlet 容器销毁前调用
     */
    @Override
    public void destroy() {
        System.out.println("===> TestFilter destroy");
    }

}

3.测试

浏览器访问 http://127.0.0.1:8080/TestServlet

日志打印:

4.Filter 主要使用场景

  • 禁用浏览器的缓存(缓存的处理)
  • 解决中文乱码问题
  • 登录鉴权及权限管理
  • 用户授权,负责检查用户的请求,根据请求过滤用户非法请求
  • 日志记录,详细记录某些特殊的用户请求
  • 其他场景

注册 Listener

1.@Listener 属性

属性 类型 描述
value String 侦听器Listener的描述

2.示例

与 ServletContext 相关的监听

Servlet 的监听器 Listener 是实现了 javax.servlet.ServletContextListener 接口的服务器端程序,随着 Web 应用启动而启动,只初始化一次,也随着 Web 应用停止而销毁。其主要作用是做一些初始化的内容添加工作,如参数和对象等。

@WebListener
public class ContextListener implements ServletContextListener, ServletContextAttributeListener{

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

    /**
     * ServletContext创建
     */
    @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 相关的监听
@WebListener
public class SessionListener implements HttpSessionListener, HttpSessionIdListener, HttpSessionAttributeListener,
        HttpSessionActivationListener {

    /**
     * session被创建时
     */
    @Override
    public void sessionCreated(HttpSessionEvent se) {
        System.out.println("===> session created");
    }

    /**
     * session被销毁时
     */
    @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的钝化,内存的数据写入到硬盘上的过程。
     */
    @Override
    public void sessionWillPassivate(HttpSessionEvent se) {
        System.out.println("===> session will passivate");
    }
    /**
     * session的活化,将硬盘的数据恢复到内存中。
     */
    @Override
    public void sessionDidActivate(HttpSessionEvent se) {
        System.out.println("===> session did activate");
    }

}
与 ServletRequest 相关的监听
@WebListener
public class RequestListener implements ServletRequestListener,ServletRequestAttributeListener {
    /**
     * 请求即将进入Web应用程序的范围/请求初始化时
     */
    @Override
    public void requestInitialized(ServletRequestEvent sre) {
        System.out.println("===> request initialized");
    }
    /**
     * 请求即将进入Web应用程序的范围/请求销毁时
     */
    @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.项目相关日志输入(启动和停止)

先执行 contextInitialzed 方法在执行 TestFilter 类的 init 方法,
contextDestroyed 方法在 TestFilter 类 destroy 方法执行后执行。

示例代码

github

码云

非特殊说明,本文版权归 朝雾轻寒 所有,转载请注明出处.

原文标题:Spring Boot 2.X(十):自定义注册 Servlet、Filter、Listener

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

如果文章对您有帮助,请扫码关注下我的公众号,文章持续更新中...

相关实践学习
日志服务之使用Nginx模式采集日志
本文介绍如何通过日志服务控制台创建Nginx模式的Logtail配置快速采集Nginx日志并进行多维度分析。
相关文章
|
4天前
|
NoSQL Java Redis
Spring Boot 自动配置机制:从原理到自定义
Spring Boot 的自动配置机制通过 `spring.factories` 文件和 `@EnableAutoConfiguration` 注解,根据类路径中的依赖和条件注解自动配置所需的 Bean,大大简化了开发过程。本文深入探讨了自动配置的原理、条件化配置、自定义自动配置以及实际应用案例,帮助开发者更好地理解和利用这一强大特性。
42 14
|
1月前
|
存储 运维 安全
Spring运维之boot项目多环境(yaml 多文件 proerties)及分组管理与开发控制
通过以上措施,可以保证Spring Boot项目的配置管理在专业水准上,并且易于维护和管理,符合搜索引擎收录标准。
42 2
|
2月前
|
SQL JSON Java
mybatis使用三:springboot整合mybatis,使用PageHelper 进行分页操作,并整合swagger2。使用正规的开发模式:定义统一的数据返回格式和请求模块
这篇文章介绍了如何在Spring Boot项目中整合MyBatis和PageHelper进行分页操作,并且集成Swagger2来生成API文档,同时定义了统一的数据返回格式和请求模块。
76 1
mybatis使用三:springboot整合mybatis,使用PageHelper 进行分页操作,并整合swagger2。使用正规的开发模式:定义统一的数据返回格式和请求模块
|
24天前
|
安全 Java 应用服务中间件
如何将Spring Boot应用程序运行到自定义端口
如何将Spring Boot应用程序运行到自定义端口
38 0
|
2月前
|
缓存 NoSQL Java
Springboot自定义注解+aop实现redis自动清除缓存功能
通过上述步骤,我们不仅实现了一个高度灵活的缓存管理机制,还保证了代码的整洁与可维护性。自定义注解与AOP的结合,让缓存清除逻辑与业务逻辑分离,便于未来的扩展和修改。这种设计模式非常适合需要频繁更新缓存的应用场景,大大提高了开发效率和系统的响应速度。
83 2
|
4月前
|
Java 数据安全/隐私保护 Spring
揭秘Spring Boot自定义注解的魔法:三个实用场景让你的代码更加优雅高效
揭秘Spring Boot自定义注解的魔法:三个实用场景让你的代码更加优雅高效
|
4月前
|
JSON 安全 Java
|
4月前
|
监控 安全 Java
【开发者必备】Spring Boot中自定义注解与处理器的神奇魔力:一键解锁代码新高度!
【8月更文挑战第29天】本文介绍如何在Spring Boot中利用自定义注解与处理器增强应用功能。通过定义如`@CustomProcessor`注解并结合`BeanPostProcessor`实现特定逻辑处理,如业务逻辑封装、配置管理及元数据分析等,从而提升代码整洁度与可维护性。文章详细展示了从注解定义、处理器编写到实际应用的具体步骤,并提供了实战案例,帮助开发者更好地理解和运用这一强大特性,以实现代码的高效组织与优化。
230 0
|
5月前
|
消息中间件 Java Kafka
Spring boot 自定义kafkaTemplate的bean实例进行生产消息和发送消息
Spring boot 自定义kafkaTemplate的bean实例进行生产消息和发送消息
213 5
|
5月前
|
Java Spring 容器
Spring boot 自定义ThreadPoolTaskExecutor 线程池并进行异步操作
Spring boot 自定义ThreadPoolTaskExecutor 线程池并进行异步操作
256 3
下一篇
DataWorks