Spring Boot(二):拦截器、过滤器、监听器、事件监听

41 篇文章 0 订阅
16 篇文章 0 订阅

1. 过滤器

          我们常常在项目中会使用 filters 用于录调用日志、排除有 XSS 威胁的字符、执行权限验证等等。Spring Boot 自动添加了 OrderedCharacterEncodingFilter 和 HiddenHttpMethodFilter,并且我们可以自定义 Filter。

  1).  注解式实现

            三个步骤:

  • 自定义过滤器类需要实现Filter接口,实现doFilter方法;
  • 在过滤类上面需要添加@WebFilter注解,参数urlPatterns、filterName;添加@Order注解
  • 在启动类上添加@ServletComponentScan注解或者在过滤类上面需要添加@Component注解

       urlPatterns:配置过滤的请求路径;

       filterName: 过滤器名称;

       @Order:规定多个Filter的执行顺序,按照@Order()的值从小到大执行;

       @ServletComponentScan:加了@ServletComponentScan,无论过滤器类不能加@Componment,单使用                                 @Component会默认过滤/*;

       @Component:表示这个类是一个组件类,会交给spring管理;

//规定多个Filter的执行顺序,按照@Order()的值从小到大执行。
@Order(1) 
//urlPatterns:配置过滤的请求路径  filterName:过滤器名称
@WebFilter(urlPatterns = "/*",filterName = "demoFilter") 
@Component
public class DemoFilter implements Filter{

	@Override
	public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)
			throws IOException, ServletException {
		System.out.println("demoFilter...过滤器实现方式一");
        filterChain.doFilter(servletRequest,servletResponse);
	}

}
//加了@ServletComponentScan,无论过滤器类加不加@Componment都可以,单使用@Component会默认过滤/*,
//@ServletComponentScan
@SpringBootApplication
public class DemoApplication {
	
	public static void main(String[] args) {
		SpringApplication.run(DemoApplication.class, args);
	}

}

2).  注解式实现

       两个步骤: 

  • 实现 Filter 接口,实现 Filter 方法
  • 添加@Configuration 注解,将自定义Filter加入过滤链

         好吧,直接上代码

@Configuration
public class WebConfiguration {

	@Bean
	public FilterRegistrationBean<Filter> configFilter() {
		FilterRegistrationBean<Filter> filterRegistrationBean = new FilterRegistrationBean<Filter>();
		filterRegistrationBean.setFilter(new HelloFilter());
		filterRegistrationBean.addUrlPatterns("/*");
		filterRegistrationBean.setName("helloFilter");
		filterRegistrationBean.setOrder(2);
		return filterRegistrationBean;
	}
	
	/**
	 * 过滤器
	 * @author Admin
	 */
	public class HelloFilter implements Filter {
		@Override
		public void doFilter(ServletRequest servletRequest, ServletResponse reServletResponse, FilterChain filterChain)
				throws IOException, ServletException {
			System.out.println("helloFilter....过滤器实现方式二");
			filterChain.doFilter(servletRequest, reServletResponse);
		}
	}

}

2. 拦截器

      两个步骤: 

  • 实现HandlerInterceptor接口,实现preHandle、postHandle、afterCompletion方法;
  • 注册拦截器
@Component("demoInterceptor")
public class DemoInterceptor implements HandlerInterceptor{
	
	@Override
	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
			throws Exception {
		System.out.println("在请求处理的方法之前执行");
		System.out.println("demoInterceptor...拦截器实现方式一");
		return true;
	}
	@Override
	public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
			ModelAndView modelAndView) throws Exception {
		System.out.println("在请求处理的方法执行后执行");
	}
	@Override
	public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
			throws Exception {
		System.out.println("在DispatcherServlet处理后执行---清理工作");
	}
}
@Configuration
public class InterceptorConfig implements WebMvcConfigurer{
	
	@Autowired
	private DemoInterceptor demoInterceptor;
	//@Autowired
	//private LogInterceptor logInterceptor;
	
	/**
	 * 拦截器的执行顺序和配置顺序有关系,即先配置顺序就在前
	 */
	@Override
	public void addInterceptors(InterceptorRegistry registry) {
		// 注册拦截器
		registry.addInterceptor(demoInterceptor)
		// 拦截的请求路径
		.addPathPatterns("/back")
		// 无需拦截的请求
		.excludePathPatterns("/login");
		//registry.addInterceptor(logInterceptor).addPathPatterns("/*");
	}
	
}

3. 监听器

     1). 注解方式实现

          两个步骤:

  •  编写监听器,需要在监听器类上加上@WebListener注解
  •  扫描监听器,在spring boot启动类上加上@ServletComponentScan注解---扫描监听器

  编写监听器

@WebListener
public class FirstListener implements ServletContextListener {
	@Override
	public void contextDestroyed(ServletContextEvent sce) {
		System.out.println("FirstListener---- 监听器实现方式一销毁");
	}
	/**
	 * 监听器实现方法一
	 *      1.需要在监听器上加上@WebListener注解
	 *      2.在spring boot启动类上加上@ServletComponentScan注解---扫描注册监听器
	 */
	@Override
	public void contextInitialized(ServletContextEvent sce) {
		System.out.println("FirstListener---- 监听器实现方式一");
	}
	
}

     扫描监听器 

@ServletComponentScan
@SpringBootApplication
public class ReycoApplication {

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

2). 注册bean的方式实现

    两个步骤:

  •  编写监听器
  •  编写一个配置类,对监听器进行bean注册 

     编写监听器

/**
 *  监听器实现方法二:
 *        1.创建监听器
 *        2.编写一个配置类,对监听器进行bean注册
 * @author reyco
 *
 */
public class SecondListener implements ServletContextListener {
	
	@Override
	public void contextDestroyed(ServletContextEvent sce) {
		System.out.println("SecondListener---- 监听器实现方式二销毁");
	}
	
	@Override
	public void contextInitialized(ServletContextEvent sce) {
		System.out.println("SecondListener---- 监听器实现方式二");
	}
	
}

     注册监听器

@Configuration
public class ListenerConfig {

	@Bean
	public ServletListenerRegistrationBean<SecondListener> getServletListenerRegistrationBean(){
		ServletListenerRegistrationBean<SecondListener> bean = new ServletListenerRegistrationBean<SecondListener>();
		bean.setListener(new SecondListener());
		return bean;
	}
	
}

4. 事件机制

       在实际项目中,我们往往需要自定义一些事件和监听器来满足业务场景,比如:支付系统:客户付款后需要发送邮件付款消息,平时我们在service中引入邮件服务,发送邮件服务也可能在一个事物内,这个时候第三方邮件服务器挂掉后,抛出异常整个逻辑都会回滚,这完全不符合逻辑。正常情况我的付款不需要依赖邮件服务,邮件发送成功与否都不应该影响我的付款操作。这个时候就需要这种事件监听。

1). 注解式

    三个步骤:

  • 编写自定义事件需要继承 ApplicationEvent 对象;
  • 自定义监听器来监听自定义事件
  • 在 Service 中注入 ApplicationContext,在业务代码处理完之后,通过 ApplicationContext 对象手动发布自定义事件,这样我们自定义的监听器就能监听到,然后处理监听器中写好的业务逻辑。

编写自定义事件

/**
 * 登录记录日志自定义事件
 * @author reyco
 *
 */
public class LoginLogEvent extends ApplicationEvent{
	
	/**
	 * 模拟登录信息
	 */
	private String logInfo;
	
	public String getLogInfo() {
		return logInfo;
	}
	public void setLogInfo(String logInfo) {
		this.logInfo = logInfo;
	}
	public LoginLogEvent(Object source,String logInfo) {
		super(source);
		this.logInfo = logInfo;
	}
	
}

 自定义监听器

@Component
public class LoginLogListener {
		
	/**
	 * 监听器
	 * @param loginLogEvent
	 */
	// @Async:异步执行,需要在入口类添加@EnableAsync注解,开启异步模式,异步执行不支持事物
	@Async   
	@EventListener
	public void save(LoginLogEvent loginLogEvent) {
		String logInfo = loginLogEvent.getLogInfo();
		System.out.println("insert登录日志,logInfo="+logInfo);
	}
	
}
@EnableAsync
@SpringBootApplication
public class DemoApplication {
	
	public static void main(String[] args) {
		SpringApplication.run(DemoApplication.class, args);
	}

}

发布自定义事件

@Service
public class LoginService {
	
	@Autowired
	private ApplicationContext applicationContext; 
	 
	public void login(){
		LoginLogEvent loginLogEvent = new LoginLogEvent(this, "登录日志信息");
		applicationContext.publishEvent(loginLogEvent);
	}
}

1). 编程式

     这里只需要修改监听器这一块,其他都一样。

/**
 * 自定义监听器
 * @author reyco
 *
 */
@Component
public class LoginLogListener implements ApplicationListener<LoginLogEvent>{

	@Override
	public void onApplicationEvent(LoginLogEvent loginLogEvent) {
		String logInfo = loginLogEvent.getLogInfo();
		System.out.println("insert登录日志,logInfo="+logInfo);
	}

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

java的艺术

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值