zoukankan      html  css  js  c++  java
  • Spring三大器

    Spring三大器

    监听器listener

    Servlet的监听器Listener,它主要作用是随着web应用的启动而启动,只初始化一次,随着web的停止而销毁。

    主要工作是:进行一些初始化的工作,例如参数或者固定一些固定对象

    • Spring boot框架自带的Listener由框架提供,在Application的run方法中进行初始化并完成加载

    • 自己实现的监听器可完成各种功能,在Spring boot下,可以实现各种特殊的监听器接口来实现各种动作的监听。同时可以通过使用注解@WebListener来完成Listener的初始化工作让其注入到IoC容器,记得在Application启动类上加上注解@ServletComponentScan。

    @WebListener
    public class SocketCounter implements HttpSessionListener {
        @Override
        public void sessionCreated(HttpSessionEvent se) {
            
        }
    
        @Override
        public void sessionDestroyed(HttpSessionEvent se) {
         
        }
    }
    
    
    @ServletComponentScan
    @SpringBootApplication(scanBasePackages = "com.example.socketdemo", exclude = {DataSourceAutoConfiguration.class})
    public class SocketdemoApplication {
        public static void main(String[] args) {
            SpringApplication.run(SocketdemoApplication.class, args);
        }
    }
    

    拦截器Interceptor

    Interceptor的urlPattern针对的是SpringMVC中的Controller控制器处理的请求

    Interceptor是SpringMVC的一个机制,在Spring框架的程序中,优先使用拦截器

    过滤器和拦截器的功能类似 :用于请求调用真正的业务逻辑之前和之后做一些通用性的处理,例如日志打印,或者请求过滤等

    Interceptor 的执行顺序大致为:

    • 请求到达 DispatcherServlet

    • DispatcherServlet 发送至 Interceptor ,执行 preHandle

    • 请求达到 Controller

    • 请求结束后,postHandle 执行

    Spring boot框架下主要通过实现HandlerInterceptor接口来实现请求的拦截,该接口有3个主要方法

    • preHandler() 在handler执行之前,返回boolean,true表示继续执行,false表示拦截

    • postHandler() 在handler执行之后,可以在结果返回之前对结果进行修改

    • afterCompetition() 在请求完全结束调用之后,用爱统计请求耗时等等

    使用拦截器进行方法执行时间统计

    @Slf4j
    @Component
    public class ExecuteTimeInterceptor extends HandlerInterceptorAdapter {
        @Override
        public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
            long startTime = System.currentTimeMillis();
            request.setAttribute("startTime", startTime);
            System.out.println("in pre handle");
            // 拦截器放行
            return true;
        }
    
        @Override
        public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
            // 获取到请求的开始时间
            System.out.println("in post handle");
            long startTime = (Long) request.getAttribute("startTime");
            long endTime = System.currentTimeMillis();
            long executeTime = endTime - startTime;
            //modified the exisitng modelAndView
            System.out.println(String.format("execute time is %s",executeTime));
        }
    
        @Override
        public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
            super.afterCompletion(request, response, handler, ex);
        }
    }
    

    编写config类,将对应的拦截器链注入到容器中。

    @Configuration
    public class MyWebConfig implements WebMvcConfigurer {
    
        // 配置拦截器
        // 将拦截器添加到 registry当中
        // 配置拦截需要拦截的请求路径 /** 全匹配
        @Override
        public void addInterceptors(InterceptorRegistry registry) {
            registry.addInterceptor(new ExecuteTimeInterceptor()).addPathPatterns("/**");
        }
    }
    

    过滤器Filter

    Filter的urlPattern针对的是所有请求,在Servlet 前后起作用。

    Filter由java实现,它依赖于Servlet容器。

    一般情况下 Filter是一个链

    • request -> filter1 -> filter2 ->filter3 -> …. -> request resource.

    • chain.doFilter将请求转发给过滤器链下一个filter , 如果没有filter那就是你请求的资源

    @WebFilter(filterName = "AuthFilter",urlPatterns = "/*")
    public class AuthFilter implements Filter {
    
        List<String> excludedUrlList;
    
        String excludedUrls = "/login";
    
        @Override
        public void init(FilterConfig filterConfig) throws ServletException {
            System.out.println("excludedUrls:" + excludedUrls);
            excludedUrlList = Arrays.asList(StringUtils.split(excludedUrls, ","));
            System.out.println("AuthFilter init success");
        }
    
        @Override
        public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
            HttpServletRequest request = (HttpServletRequest) servletRequest;
            HttpServletResponse response = (HttpServletResponse) servletResponse;
            // 校验是否需要登录
            System.out.println("url is " + ((HttpServletRequest) servletRequest).getRequestURL());
            Boolean result = excludedUrlList.contains(((HttpServletRequest) servletRequest).getRequestURI());
            System.out.println("是否需要重定向到login " + !result);
            if (!result) {
                System.out.println("this request need to go to 重定向页面");
                response.sendRedirect("/login");
                return;
            }
            filterChain.doFilter(servletRequest, servletResponse);
        }
    
        @Override
        public void destroy() {
    
        }
    
    
        private Boolean needLogin(HttpServletRequest request) {
            System.out.println("in needLogin()");
            return true;
        }
    }
    

    Spring Boot中使用自定的Filter:

    1. 实现Filter接口,并重载其核心的三个方法。

    2. 使用注解 @WebFilter(filterName = "AuthFilter",urlPatterns = "/*") 将Filter完成注入,并配置好需要过滤的路径

    拦截器和过滤器的区别

    • 在Spring框架下,尽量使用Interceptor,因为过滤器能做的事拦截器基本都能做
    • Interceptor能够操作上下文等Spring框架的容器中一些对象,而Filter不可以
    • Filter基于针对Servlet的所有请求,而Interceptor只针对Controller的请求进行处理
  • 相关阅读:
    csrf攻击实例
    《四 数据库连接池源码》手写数据库连接池
    《四 spring源码》手写springmvc
    spring和springmvc是单例还是多例
    redis集群设置密码
    mongodb3.6集群搭建:分片集群认证
    mongodb3.6集群搭建:分片+副本集
    Mongo 3.6.1版本Sharding集群配置
    windows计划任务
    Redis slowlog慢查询
  • 原文地址:https://www.cnblogs.com/aguai1992/p/10914477.html
Copyright © 2011-2022 走看看