JAVA-过滤器、拦截器、监听器

1.过滤器

过滤器

package com.cnooc.dictionary.utils.filter;

import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

//计算请求时间案例
//实现了过滤特定url请求的拦截器,并配置到spring中
@Component
@Slf4j
public class MyFilter implements Filter {

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        //启动的时候初始化
        log.info("初始化过滤器: " + filterConfig.getFilterName());
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        //对请求进行预处理
        log.info("过滤器开始对请求进行预处理:");
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        HttpServletResponse response = (HttpServletResponse) servletResponse;

        String requestUri = request.getRequestURI();
        System.out.println("请求的接口为:" + requestUri);
        long startTime = System.currentTimeMillis();
        //通过 doFilter 方法实现过滤功能
        filterChain.doFilter(servletRequest, servletResponse);
        // 上面的 doFilter 方法执行结束后用户的请求已经返回
        long endTime = System.currentTimeMillis();
        System.out.println("该用户的请求已经处理完毕,请求花费的时间为:" + (endTime - startTime));
    }

    @Override
    public void destroy() {
        //停止的时候销毁
        log.info("销毁过滤器");
    }
}

配置过滤器

package com.cnooc.dictionary.utils.filter;

import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.ArrayList;
import java.util.List;

@Configuration
public class MyFilterConfig {

    @Bean
    public FilterRegistrationBean<MyFilter> thirdFilter() {
        FilterRegistrationBean<MyFilter> filterRegistrationBean = new FilterRegistrationBean<>();

        filterRegistrationBean.setFilter(new MyFilter());
        List<String> urls = new ArrayList<>();
        //配置需要过滤的url
        urls.add("/classifyApi/*");
        urls.add("/entryApi/*");
        //拦截url
        filterRegistrationBean.setUrlPatterns(urls);
        //多个过滤器配设置执行顺序
        filterRegistrationBean.setOrder(1);

        return filterRegistrationBean;
    }
}

2.拦截器

下面实现了3个拦截器,并分别配置到spring中

拦截器1

package com.cnooc.dictionary.utils.Interceptor;

import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class LogInterceptor extends HandlerInterceptorAdapter {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
            throws Exception {
        long startTime = System.currentTimeMillis();
        System.out.println("\n-------- LogInterception.preHandle --- ");
        System.out.println("请求路径: " + request.getRequestURL());
        System.out.println("开始时间: " + System.currentTimeMillis());

        request.setAttribute("startTime", startTime);

        return true;
    }
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response,
                           Object handler, ModelAndView modelAndView) throws Exception {

        System.out.println("\n-------- LogInterception.postHandle --- ");
        System.out.println("请求路径: " + request.getRequestURL());

        // You can add attributes in the modelAndView
        // and use that in the view page
    }
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response,
                                Object handler, Exception ex) throws Exception {
        System.out.println("\n-------- LogInterception.afterCompletion --- ");

        long startTime = (Long) request.getAttribute("startTime");
        long endTime = System.currentTimeMillis();
        System.out.println("请求路径: " + request.getRequestURL());
        System.out.println("结束时间: " + endTime);

        System.out.println("耗时: " + (endTime - startTime));
    }
}

拦截器2

package com.cnooc.dictionary.utils.Interceptor;

import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class OldLoginInterceptor extends HandlerInterceptorAdapter {
    /**
     * 在这儿从定向到/admin/login
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
            throws Exception {

        System.out.println("\n-------- OldLoginInterceptor.preHandle --- ");
        System.out.println("Request URL: " + request.getRequestURL());
        System.out.println("Sorry! 这个借口被弃用了, 重定向到 /admin/login");

        response.sendRedirect(request.getContextPath() + "/admin/login");
        return false;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response,
                           Object handler, ModelAndView modelAndView) throws Exception {

        //因为重定向了,这段代码永远不会运行
        System.out.println("\n-------- OldLoginInterceptor.postHandle --- ");
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response,
                                Object handler, Exception ex) throws Exception {

        //这段代码永远不会运行
        System.out.println("\n-------- QueryStringInterceptor.afterCompletion --- ");
    }
}

拦截器3

package com.cnooc.dictionary.utils.Interceptor;

import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class AdminInterceptor extends HandlerInterceptorAdapter {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
            throws Exception {

        System.out.println("\n-------- AdminInterceptor.preHandle --- ");
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response,
                           Object handler, ModelAndView modelAndView) throws Exception {

        System.out.println("\n-------- AdminInterceptor.postHandle --- ");
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response,
                                Object handler, Exception ex) throws Exception {

        System.out.println("\n-------- AdminInterceptor.afterCompletion --- ");
    }
}

配置3个拦截器

package com.cnooc.dictionary.utils.Interceptor;

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class WebConfig implements WebMvcConfigurer {

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        //loginteceptor 允许通过所有的url
        registry.addInterceptor(new LogInterceptor());


        //老的登录被弃用,重定向到新的url
        registry.addInterceptor(new OldLoginInterceptor())
                .addPathPatterns("/admin/oldLogin");


        //此拦截器适用于  /admin/*  包括  /admin/oldLogin  这样的URL
        registry.addInterceptor(new AdminInterceptor())
                .addPathPatterns("/admin/*")
                //排除/admin/oldLogin
                .excludePathPatterns("/admin/oldLogin");
    }
}

3.监听器

使用场景

比如监听 Servlet 上下文用来初始化一些数据、监听 HTTP Session 用来获取当前在线的人数、监听客户端请求的ServletRequest 对象来获取用户的访问信息等等。

监听 Servlet 上下文对象

import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.stereotype.Component;

@Component
public class MyServletContextListener implements ApplicationListener<ContextRefreshedEvent> {
    /**
     * 在spring容器初始化(启动后)完成之后执行。
     * @param contextRefreshedEvent --上下文刷新事件
     */
    @Override
    public void onApplicationEvent(ContextRefreshedEvent contextRefreshedEvent) {
        System.out.println("Spring容器加载完成触发,可用于初始化环境,准备测试数据、加载一些数据到内存");
        //此处可以开启一个线程,用于查询首页数据,并缓存在内容或redis中,供所有的首页进行查询
        //代码省略
    }
}

监听 HTTP Session 对象


import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;

/**
 * 获取实时用户数量
 */
@Component
@Slf4j
public class MyHttpSessionListener implements HttpSessionListener {

    public static Integer count = 0;   //记录在线的用户数量

    @Override
    public synchronized void sessionCreated(HttpSessionEvent httpSessionEvent) {
        log.info("新用户上线了");
        count++;
        httpSessionEvent.getSession().getServletContext().setAttribute("count", count);
    }

    @Override
    public synchronized void sessionDestroyed(HttpSessionEvent httpSessionEvent) {
        log.info("用户下线了");
        count--;
        httpSessionEvent.getSession().getServletContext().setAttribute("count", count);
    }
}

监听请求Request对象

import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import javax.servlet.ServletRequestEvent;
import javax.servlet.ServletRequestListener;
import javax.servlet.http.HttpServletRequest;

/**
 * 实现request访问前后的方法
 */
@Component
@Slf4j
public class MyServletRequestListener implements ServletRequestListener {

    @Override
    public void requestInitialized(ServletRequestEvent servletRequestEvent) {
        HttpServletRequest request = (HttpServletRequest) servletRequestEvent.getServletRequest();
        log.info("session id为:{}", request.getRequestedSessionId());
        log.info("request url为:{}", request.getRequestURL());
        request.setAttribute("name", "zyd");
    }

    @Override
    public void requestDestroyed(ServletRequestEvent servletRequestEvent) {
        log.info("request end");
        HttpServletRequest request = (HttpServletRequest) servletRequestEvent.getServletRequest();
        log.info("request域中保存的name值为:{}", request.getAttribute("name"));

    }
}

自定义监听器

自定义监听器步骤

创建自定义事件,继承ApplicationEvent。
发布我们的自定义事件,一般通过实现ApplicationEventPublisherAware 接口来完成。
定义事件监听器,一般是实现ApplicationListener接口或者使用@EventListener注解。

1.创建自定义事件

import org.springframework.context.ApplicationEvent;

/**
 * 创建自定义事件,继承ApplicationEvent
 */
public class MyApplicationEvent extends ApplicationEvent {

    private static final long serialVersionUID = -9110297575225719030L;
    private final String address;
    public final String test;

    public MyApplicationEvent(Object source, String address, String test) {
        super(source);
        this.address = address;
        this.test = test;
    }

    @Override
    public String toString() {
        return "MyApplicationEvent [address=" + address + ", test=" + test + "]";
    }
    // accessor and other methods...
}

2.发布自定义事件

import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.List;

/**
 * 一调用MyApplicationEventService类的sendEmail()或testListener()方法,监听器就会触发。
 */
@Component
public class MyApplicationEventService implements ApplicationEventPublisherAware {

    private List<String> blackList;
    private ApplicationEventPublisher publisher;

    @Override
    public void setApplicationEventPublisher(ApplicationEventPublisher publisher) {
        this.publisher = publisher;
    }

    //自己的方法1
    public void sendEmail(String address, String text) {
        blackList = new ArrayList<>();
        blackList.add("known.spammer@example.org");
        blackList.add("known.hacker@example.org");
        blackList.add("john.doe@example.org");
        if (blackList.contains(address)) {
            publisher.publishEvent(new MyApplicationEvent(this, address, text));
            return;
        }
        // send email...
    }

    //自己的方法2
    public void testListener(String address, String text) {
        MyApplicationEvent event = new MyApplicationEvent(this, address, text);
        publisher.publishEvent(event);
    }
}

3.定义事件监听器


import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component;

/**
 * 自己的业务代码可以写到监听器中
 * 事件监听器方式1: 实现接口
 */
@Component
public class MyApplicationListener implements ApplicationListener<MyApplicationEvent> {

    @Override
    public void onApplicationEvent(MyApplicationEvent event) {
        //监听到了
        //操作此处的event中的数据
        System.out.println("my listener start");
        System.out.println(event.toString());
        System.out.println("my listener end");

    }
}

import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;

/**
 * 自己的业务代码可以写到监听器中
 * 事件监听器2  使用注解
 */
@Component
public class MyApplicationListener2 {

    @EventListener
    //使用注解还可以监听多个事件,如下
//    @EventListener({ContextRefreshedEvent.class, MyApplicationEvent .class})
    public void onApplicationEvent(MyApplicationEvent event) {
        
        //监听到了
        //操作此处的event中的数据
        System.out.println("my listener start");
        System.out.println(event.toString());
        System.out.println("my listener end");
    }
}

4.测试调用监听

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("listener")
public class ListenerController {

    @Autowired
    private MyApplicationEventService myApplicationEventService;

    @GetMapping("/listener")
    public String testMyListener() {
        /*myApplicationEventService.sendEmail("john.doe@example.org", "123123"); */
        myApplicationEventService.testListener("john.doe@example.org", "123");
        return "SUCCESS";
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值