专栏首页Spring Boot 2.X 系列Spring Boot 2.X(十):自定义注册 Servlet、Filter、Listener
原创

Spring Boot 2.X(十):自定义注册 Servlet、Filter、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名称,等价于 <servlet-name>

value

String[]

等同于 urlPatterns 属性,两者不应该同时使用

urlPatterns

String[]

指定一组 Servlet 的 URL 匹配模式。等价于<url-pattern>标签

loadOnStartup

int

指定 Servlet 的加载顺序,等价于 <load-on-startup>标签

initParams

WebInitParam[]

指定一组 Servlet 初始化参数,等价于<init-param>标签

asyncSupported

boolean

声明 Servlet 是否支持异步操作模式,等价于<async-supported> 标签

smallIcon

String

此 Servlet 的小图标

largeIcon

String

此 Servlet 的大图标

description

String

该 Servlet 的描述信息,等价于 <description>标签

displayName

String

该 Servlet 的显示名,通常配合工具使用,等价于 <display-name>标签

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名称,等价于 <filter-name>

value

String[]

等同于 urlPatterns 属性,两者不应该同时使用

urlPatterns

String[]

指定一组 Filter 的 URL 匹配模式。等价于<url-pattern>标签

servletNames

String[]

指定过滤器将应用于哪些 Servlet。取值于 @WebServlet 中的 name 属性,或者是 web.xml 中 <servlet-name> 的值

initParams

WebInitParam[]

指定一组 Filter 初始化参数,等价于<init-param>标签

dispatcherTypes

DispatcherType[]

指定 Filter 的转发模式,包括:ASYNC、ERROR、FORWARD、INCLUDE、REQUEST

asyncSupported

boolean

声明 Filter 是否支持异步操作模式,等价于<async-supported> 标签

smallIcon

String

此 Filter 的小图标

largeIcon

String

此 Filter 的大图标

description

String

该 Filter 的描述信息,等价于 <description>标签

displayName

String

该 Filter 的显示名,通常配合工具使用,等价于 <display-name>标签

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

原创声明,本文系作者授权云+社区发表,未经许可,不得转载。

如有侵权,请联系 yunjia_community@tencent.com 删除。

我来说两句

0 条评论
登录 后参与评论

相关文章

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

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

    朝雾轻寒
  • Spring Boot 2.X(十八):集成 Spring Security-登录认证和权限控制

    在企业项目开发中,对系统的安全和权限控制往往是必需的,常见的安全框架有 Spring Security、Apache Shiro 等。本文主要简单介绍一下 Sp...

    朝雾轻寒
  • Spring Boot 2.X(十八):集成 Spring Security-登录认证和权限控制

    在企业项目开发中,对系统的安全和权限控制往往是必需的,常见的安全框架有 Spring Security、Apache Shiro 等。本文主要简单介绍一下 Sp...

    朝雾轻寒
  • springBoot启动时让方法自动执行

    版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。

    chenchenchen
  • Java设计模式之桥梁模式

    梦想中的我自己,身价过亿,有两个大公司,一个是房地产公司,一个是服装制造公司,其实是什么公司我倒是不关心,我关心的是它赚不赚钱,赚了多少,这才是我关心的。先用类...

    CoderJed
  • TestNG用法概括

    应用场景:将通用的功能抽取并封装起来,在方法中使用注解@BeforeSuite和@AfterSuite,在测试类中继承这个类,测试类在运行前会先运行@Befor...

    桑鱼
  • SpringMVC快速使用AOP

    最近突然想到了AOP编程,于是在自己的SpringMVC小项目中引入了。AOP一般用来做些什么呢?这里简单的使用AOP做拦截日志,来介绍下在SpringMVC中...

    幽鸿
  • 设计模式之模板方法模式(一)

    学习了前面的朋友都知道,目前为止,我们的议题都是绕着封装转;我们已经封装了对象创建、方法调用、复杂接口、鸭子、比萨…那接下来呢?

    程序员小跃
  • Spring Boot 2.X(十):自定义注册 Servlet、Filter、Listener

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

    朝雾轻寒
  • java设计模式(7)-外观模式

    上篇文章分享代理模式,这篇整理外观模式,外观模式可以降低类与类之间的耦合程度,减少维护工作量

    爱敲代码的猫

扫码关注云+社区

领取腾讯云代金券