首页 > 其他分享 >Spring 过滤器 拦截器 监听器 Aop

Spring 过滤器 拦截器 监听器 Aop

时间:2024-10-11 17:33:03浏览次数:9  
标签:INFO web --- 拦截器 10 Spring 2024 监听器 com

目录

Spring 过滤器 拦截器 监听器 Aop

1. 过滤器

1. 简介
	过滤器Filter用于对数据进行过滤和预处理  
	过滤器只能在请求前后使用 
	依赖于servlet容器 基于函数回调实现 其生命周期由servlet容器管理 
	过滤器只能初始化一次 且销毁只发生在服务停止或重新发布 即程序启动调用filter的init()有且一次 或有且一次当程序停止时调用filter的destroy()  调用doFilter()只在符合条件下执行
	无法获取ioc容器中的bean

2. 使用场景
2.1 敏感数据过滤
2.2 URL层面的权限验证
2.3 设置编码格式
2.4 压缩响应信息、预处理请求信息等等...

3. 使用方式
3.1 @WebFilter注解修饰类 + 该类实现Filter接口 + 类重写doFilter方法(可选重写init和destroy方法) + 启动类@ServletComponentScan + (可选)Order(过滤器执行顺序序号)

3.2 @WebFilter注解修饰类 + 该类实现Filter接口 + 类重写doFilter方法(可选重写init和destroy方法) + @Configuration修饰的配置类并通过FilterRegistrationBean注册Filter

3.3 该类实现Filter接口 + 类重写doFilter方法(可选重写init和destroy方法) +  @Configuration修饰的配置类并通过FilterRegistrationBean注册Filter

3.4 @Component注解修饰类 +  该类实现Filter接口 + 类重写doFilter方法(可选重写init和destroy方法) + (可选)Order(过滤器执行顺序序号)
package com.ntt.web.config;


import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

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


// 方式1 @WebFilter + 实现Filter接口 + 启动类 @ServletComponentScan  拦截*
@WebFilter(filterName = "filter1", urlPatterns = {"/*"})
@Slf4j
@Order(1)
class Filter1 implements Filter
{

    @Override
    public void init(FilterConfig fg) throws ServletException
    {
        log.info("filter1-init");
    }

    @Override
    public void destroy()
    {
        log.info("filter1-destroy");
    }


    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException
    {
        log.info("filter1-start");
        // 可对请求前后数据进行预处理
        HttpServletRequest req = (HttpServletRequest) request;
        HttpServletResponse res = (HttpServletResponse) response;
        chain.doFilter(req, res);  // 可添加响应逻辑是否对该URI访问资源放行或做其它处理
        log.info("filter1-end");
    }

}

// 方式2  @WebFilter + 实现Filter接口 +  @Configure修饰的配置类并通过FilterRegistrationBean注册Filter
//@WebFilter  // 为避免多次注册 当启动类使用@ServletComponentScan修饰 建议屏蔽该注解
@Slf4j
class Filter2 implements Filter
{

    @Override
    public void init(FilterConfig fg) throws ServletException
    {
        log.info("filter2-init");
    }

    @Override
    public void destroy()
    {
        log.info("filter2-destroy");
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException
    {
        log.info("filter2-start");
        HttpServletRequest req = (HttpServletRequest) request;
        HttpServletResponse res = (HttpServletResponse) response;
        chain.doFilter(req, res);
        log.info("filter2-end");
    }
}

// 方式3 实现Filter接口 +类重写doFilter方法(可选重写init和destroy方法)  +  @Configure修饰的配置类并通过FilterRegistrationBean注册Filter
@Slf4j
class Filter3 implements Filter
{

    @Override
    public void init(FilterConfig fg) throws ServletException
    {
        log.info("filter3-init");
    }

    @Override
    public void destroy()
    {
        log.info("filter3-destroy");
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException
    {
        log.info("filter3-start");
        HttpServletRequest req = (HttpServletRequest) request;
        HttpServletResponse res = (HttpServletResponse) response;
        chain.doFilter(req, res);
        log.info("filter3-end");
    }
}

// 方式4   @Component + 实现Filter接口 不指定过滤url 默认/*
@Component
@Slf4j
@Order(4)
class Filter4 implements Filter {

    @Override
    public void init(FilterConfig fg) throws ServletException
    {
        log.info("filter4-init");
    }

    @Override
    public void destroy()
    {
        log.info("filter4-destroy");
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException
    {
        log.info("filter4-start");
        HttpServletRequest req = (HttpServletRequest) request;
        HttpServletResponse res = (HttpServletResponse) response;
        chain.doFilter(req, res);
        log.info("filter4-end");
    }
}

// 配置类
@Configuration
public class FilterConfig{
    @Bean
    public FilterRegistrationBean<Filter> Filter2()
    {
        FilterRegistrationBean<Filter> fb = new FilterRegistrationBean<>();
        fb.setFilter(new Filter2());
        fb.addUrlPatterns("/*");
        fb.setName("filter2");
        fb.setOrder(2);
        return fb;
    }

    @Bean
    public FilterRegistrationBean<Filter> Filter3()
    {
        FilterRegistrationBean<Filter> fb = new FilterRegistrationBean<>();
        fb.setFilter(new Filter3());
        fb.addUrlPatterns("/*");
        fb.setName("filter3");
        fb.setOrder(3);
        return fb;
    }

}
package com.ntt.web;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.servlet.ServletComponentScan;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
import org.springframework.context.annotation.Configuration;

// 启动类
@SpringBootApplication
@Configuration
@ServletComponentScan
public class CmsApplication extends SpringBootServletInitializer {

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

    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
        return application.sources(CmsApplication.class);
    }
}
package com.ntt.web.controller;

import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

// 控制器类
@RestController
@RequestMapping("/api/v1")
@Slf4j
public class TestController {

    @GetMapping(value = "/filter")
    public void filter()
    {
        log.info("调用地址:/filter");
    }

    @GetMapping(value = "/interceptor")
    public void interceptor()
    {
        log.info("调用地址:/interceptor");
    }
    
    @GetMapping(value = "/listener")
    public void listener(HttpServletRequest req)
    {
        Integer count = (Integer) req.getSession().getServletContext().getAttribute("count");
        log.info("调用地址:/listener;count:{}", count);
    }
    
    @GetMapping(value = "/aop")
    public Object aop() {
        log.info("调用地址:/aop");
	//        Integer err = 1 /0; // 抛出异常触发通知afterThrowing
        return "aop";
    }

    @GetMapping(value = "/")
    public void get()
    {
        log.info("调用地址:/");
    }
}
  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::                (v2.5.6)

2024-10-09 14:53:42.960  INFO 29568 --- [           main] com.ntt.web.CmsApplication               : Starting CmsApplication using Java 
2024-10-09 14:53:42.962  INFO 29568 --- [           main] com.ntt.web.CmsApplication               : No active profile set, falling back to default profiles: default
2024-10-09 14:53:44.213  INFO 29568 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat initialized with port(s): 9999 (http)
2024-10-09 14:53:44.229  INFO 29568 --- [           main] o.apache.catalina.core.StandardService   : Starting service [Tomcat]
2024-10-09 14:53:44.229  INFO 29568 --- [           main] org.apache.catalina.core.StandardEngine  : Starting Servlet engine: [Apache Tomcat/9.0.54]
2024-10-09 14:53:44.231  INFO 29568 --- [           main] o.a.catalina.core.AprLifecycleListener   : Loaded Apache Tomcat Native library [1.2.32] using APR version [1.7.0]
2024-10-09 14:53:44.341  INFO 29568 --- [           main] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
2024-10-09 14:53:44.341  INFO 29568 --- [           main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 1338 ms
2024-10-09 14:53:44.461  INFO 29568 --- [           main] com.ntt.web.config.Filter1               : filter1-init
2024-10-09 14:53:44.462  INFO 29568 --- [           main] com.ntt.web.config.Filter2               : filter2-init
2024-10-09 14:53:44.462  INFO 29568 --- [           main] com.ntt.web.config.Filter3               : filter3-init
2024-10-09 14:53:44.462  INFO 29568 --- [           main] com.ntt.web.config.Filter4               : filter4-init
 _ _   |_  _ _|_. ___ _ |    _ 
| | |\/|_)(_| | |_\  |_)||_|_\ 
     /               |         
                        3.5.1 
2024-10-09 14:53:48.262  INFO 29568 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 9999 (http) with context path ''
2024-10-09 14:53:48.272  INFO 29568 --- [           main] com.ntt.web.CmsApplication               : Started CmsApplication in 5.718 seconds (JVM running for 8.262)
2024-10-09 14:53:48.743  INFO 29568 --- [nio-9999-exec-1] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring DispatcherServlet 'dispatcherServlet'
2024-10-09 14:53:48.743  INFO 29568 --- [nio-9999-exec-1] o.s.web.servlet.DispatcherServlet        : Initializing Servlet 'dispatcherServlet'
2024-10-09 14:53:48.744  INFO 29568 --- [nio-9999-exec-1] o.s.web.servlet.DispatcherServlet        : Completed initialization in 1 ms
2024-10-09 14:53:48.750  INFO 29568 --- [nio-9999-exec-1] com.ntt.web.config.Filter2               : filter2-start
2024-10-09 14:53:48.750  INFO 29568 --- [nio-9999-exec-1] com.ntt.web.config.Filter3               : filter3-start
2024-10-09 14:53:48.750  INFO 29568 --- [nio-9999-exec-1] com.ntt.web.config.Filter4               : filter4-start
2024-10-09 14:53:48.750  INFO 29568 --- [nio-9999-exec-1] com.ntt.web.config.Filter1               : filter1-start
2024-10-09 14:53:48.764  INFO 29568 --- [nio-9999-exec-1] com.ntt.web.controller.TestController    : 调用地址:/filter
2024-10-09 14:53:48.780  INFO 29568 --- [nio-9999-exec-1] com.ntt.web.config.Filter1               : filter1-end
2024-10-09 14:53:48.781  INFO 29568 --- [nio-9999-exec-1] com.ntt.web.config.Filter4               : filter4-end
2024-10-09 14:53:48.781  INFO 29568 --- [nio-9999-exec-1] com.ntt.web.config.Filter3               : filter3-end
2024-10-09 14:53:48.781  INFO 29568 --- [nio-9999-exec-1] com.ntt.web.config.Filter2               : filter2-end
2024-10-09 14:55:57.211  INFO 29568 --- [ionShutdownHook] com.ntt.web.config.Filter1               : filter1-destroy
2024-10-09 14:55:57.211  INFO 29568 --- [ionShutdownHook] com.ntt.web.config.Filter2               : filter2-destroy
2024-10-09 14:55:57.212  INFO 29568 --- [ionShutdownHook] com.ntt.web.config.Filter3               : filter3-destroy
2024-10-09 14:55:57.212  INFO 29568 --- [ionShutdownHook] com.ntt.web.config.Filter4               : filter4-destroy
2024-10-09 14:55:57.229  INFO 29568 --- [ionShutdownHook] com.alibaba.druid.pool.DruidDataSource   : {dataSource-0} closing ...

2. 拦截器

1.简介
	拦截器interceptor依赖于Spring容器 是aop面向切面编程的一种方式 拦截处理器的执行 执行顺序晚于过滤器 属于全局行为 功能近似与过滤器
	HandlerInterceptor接口相关方法
		preHandle: 处理器执行前执行 返回false则直接执行afterCompletion方法 多个执行顺序为顺序
		postHandle: 处理器执行后 视图渲染前执行 若异常 则执行执行afterCompletion方法 多个执行顺序为逆序
		afterCompletion: 视图渲染后执行 最后均会被执行该方法 多个执行顺序为逆序
	过滤器和拦截器执行流程
		filter->interceptor.preHandle->handler->interceptor.postHandle->interceptor.afterCompletion->filter

2.使用场景
2.1 登录或权限验证
2.2 日志额外信息记录打印
2.3 性能监控
2.4 用户行为记录等等...

3.使用方式
3.1 实现HandlerInterceptor接口 + @Configuration修饰的配置类重写addInterceptors方法 注册拦截器
3.2 实现HandlerInterceptor接口 +  @Configuration修饰的配置类 + @Bean MappedInterceptor方法 注册拦截器 + (可选) @Order指定顺序
package com.ntt.web.config;

import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.lang.Nullable;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.handler.MappedInterceptor;

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

// 方式1 实现HandlerInterceptor接口 + @Configuration修饰的配置类重写addInterceptors方法 注册拦截器
@Slf4j
class Interceptor1 implements HandlerInterceptor
{
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception
    {
        log.info("Interceptor1-preHandle");
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable ModelAndView modelAndView) throws Exception
    {
        log.info("Interceptor1-postHandle");
        HandlerInterceptor.super.postHandle(request, response, handler, modelAndView);
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) throws Exception {
        log.info("Interceptor1-afterCompletion");
        HandlerInterceptor.super.afterCompletion(request, response, handler, ex);
    }
}

@Slf4j
class Interceptor2 implements HandlerInterceptor, Ordered
{
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception
    {
        log.info("Interceptor2-preHandle");
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable ModelAndView modelAndView) throws Exception
    {
        log.info("Interceptor2-postHandle");
        HandlerInterceptor.super.postHandle(request, response, handler, modelAndView);
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) throws Exception {
        log.info("Interceptor2-afterCompletion");
        HandlerInterceptor.super.afterCompletion(request, response, handler, ex);
    }

    @Override
    public int getOrder() {
        return 2;
    }
}

// 方式2 实现HandlerInterceptor接口 +  @Configuration修饰的配置类 + @Bean MappedInterceptor方法 注册拦截器 + (可选) @Order指定顺序
@Slf4j
class Interceptor3 implements HandlerInterceptor
{
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception
    {
        log.info("Interceptor3-preHandle");
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable ModelAndView modelAndView) throws Exception
    {
        log.info("Interceptor3-postHandle");
        HandlerInterceptor.super.postHandle(request, response, handler, modelAndView);
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) throws Exception {
        log.info("Interceptor3-afterCompletion");
        HandlerInterceptor.super.afterCompletion(request, response, handler, ex);
    }

}

//
@Configuration
public class InterceptorConfig implements WebMvcConfigurer
{
    private final String[] allowUrls = {"/api/v1/interceptor"};

    private final String[] banUrls = {"/api/v1/filter"};

//    @Bean
//    @Order(3)  
//    public MappedInterceptor interceptor3(){
//        return new MappedInterceptor(allowUrls, banUrls, new Interceptor3());
//    }


    @Override
    public void addInterceptors(InterceptorRegistry registry)
    {
        // 添加拦截器
        registry.addInterceptor(new Interceptor1())
                .addPathPatterns(allowUrls)
                .excludePathPatterns(banUrls)
                .order(1);
        registry.addInterceptor(new Interceptor2())
                .addPathPatterns(allowUrls)
                .excludePathPatterns(banUrls)
                .order(2);
        registry.addInterceptor(new Interceptor3())
                .addPathPatterns(allowUrls)
                .excludePathPatterns(banUrls)
                .order(3);

    }
}

2024-10-09 16:20:25.351  INFO 6480 --- [nio-9999-exec-1] com.ntt.web.config.Interceptor1          : Interceptor1-preHandle
2024-10-09 16:20:25.351  INFO 6480 --- [nio-9999-exec-1] com.ntt.web.config.Interceptor2          : Interceptor2-preHandle
2024-10-09 16:20:25.351  INFO 6480 --- [nio-9999-exec-1] com.ntt.web.config.Interceptor3          : Interceptor3-preHandle
2024-10-09 16:20:25.358  INFO 6480 --- [nio-9999-exec-1] com.ntt.web.controller.TestController    : 调用地址:/interceptor
2024-10-09 16:20:25.373  INFO 6480 --- [nio-9999-exec-1] com.ntt.web.config.Interceptor3          : Interceptor3-postHandle
2024-10-09 16:20:25.373  INFO 6480 --- [nio-9999-exec-1] com.ntt.web.config.Interceptor2          : Interceptor2-postHandle
2024-10-09 16:20:25.374  INFO 6480 --- [nio-9999-exec-1] com.ntt.web.config.Interceptor1          : Interceptor1-postHandle
2024-10-09 16:20:25.374  INFO 6480 --- [nio-9999-exec-1] com.ntt.web.config.Interceptor3          : Interceptor3-afterCompletion
2024-10-09 16:20:25.374  INFO 6480 --- [nio-9999-exec-1] com.ntt.web.config.Interceptor2          : Interceptor2-afterCompletion
2024-10-09 16:20:25.374  INFO 6480 --- [nio-9999-exec-1] com.ntt.web.config.Interceptor1          : Interceptor1-afterCompletion

3.监听器

1. 简介
	监听器是一种Servlet特殊类 用于监听web中的相关对象创建、销毁、修改等事件操作  主要是ServletContext HttpSession ServletRequest 监听
	
2. 使用场景
2.1 监听ServletContext 关于应用web初始化的信息 缓存数据信息
2.2 监听HttpSession 关于用户会话信息
2.3 监听SerVletRequest  关于用户的请求信息 等...

3. 使用方法
3.1 实现ServletContextListener接口 + [@WebListener修饰类 + 启动类@ServletComponentScan] 或 @Component修饰类 或 @Configuration配置类 & @Bean 修饰ServletListenerRegistrationBean方法 注册监听器
3.2 实现HttpSessionListener接口 + [@WebListener修饰类 + 启动类@ServletComponentScan] 或 @Component修饰类 或 @Configuration配置类 & @Bean 修饰ServletListenerRegistrationBean方法 注册监听器
3.3 实现ServletRequestListener接口 + [@WebListener修饰类 + 启动类@ServletComponentScan] 或 @Component修饰类 或 @Configuration配置类 & @Bean 修饰ServletListenerRegistrationBean方法 注册监听器
package com.ntt.web.config;

import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.web.servlet.ServletListenerRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;

import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.ServletRequestEvent;
import javax.servlet.ServletRequestListener;
import javax.servlet.annotation.WebListener;
import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;


// 方式1 @Component修饰类 + 实现对应listener接口
@Component
@Slf4j
class Listener1 implements ServletContextListener
{
    @Override
    public void contextInitialized(ServletContextEvent sce)
    {
        log.info("ServletContextListener-start");
    }

    @Override
    public void contextDestroyed(ServletContextEvent sce)
    {
        log.info("ServletContextListener-end");
    }
}

// 方式2 @WebListener修饰类 + 实现对应listener接口 + @ServletComponentScan修饰启动类
@WebListener
@Slf4j
class Listener2 implements HttpSessionListener
{
    private static Integer count = 0;

    @Override
    public synchronized void sessionCreated(HttpSessionEvent se)
    {
        count ++;
        HttpSession sn = se.getSession();
        sn.setMaxInactiveInterval(60);
        sn.getServletContext().setAttribute("count", count);
        log.info("HttpSessionListener-start");
    }


    @Override
    public synchronized void sessionDestroyed(HttpSessionEvent se)
    {
        count --;
        HttpSession sn = se.getSession();
        sn.setMaxInactiveInterval(60);
        sn.getServletContext().setAttribute("count", count);
        log.info("HttpSessionListener-end");
    }
}


// 方式3 实现对应listener接口 + @Configuration配置类 & @Bean 修饰ServletListenerRegistrationBean方法 注册监听器
@Slf4j
class Listener3 implements ServletRequestListener
{
    @Override
    public void requestDestroyed (ServletRequestEvent sre) {
        log.info("ServletRequestListener-start");
    }


    @Override
    public void requestInitialized (ServletRequestEvent sre) {
        log.info("ServletRequestListener-end");
    }
}


@Configuration
public class ListenerConfig {

//    @Bean  // 实际测试采用该方式注册
//    public ServletListenerRegistrationBean<Listener2> Listener2(){
//        ServletListenerRegistrationBean<Listener2> rb = new ServletListenerRegistrationBean<>();
//        rb.setListener(new Listener2());
////        rb.setOrder(1);
//        return rb;
//    }

    @Bean
    public ServletListenerRegistrationBean<Listener3> Listener3(){
        ServletListenerRegistrationBean<Listener3> rb = new ServletListenerRegistrationBean<>();
        rb.setListener(new Listener3());
//        rb.setOrder(2);
        return rb;
    }
}
2024-10-10 16:35:13.414  INFO 41960 --- [           main] com.ntt.web.config.Listener1             : ServletContextListener-start
2024-10-10 16:35:17.113  INFO 41960 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 9999 (http) with context path ''
2024-10-10 16:35:17.123  INFO 41960 --- [           main] com.ntt.web.CmsApplication               : Started CmsApplication in 5.375 seconds (JVM running for 7.518)
2024-10-10 16:35:17.951  INFO 41960 --- [nio-9999-exec-1] com.ntt.web.config.Listener3             : ServletRequestListener-end
2024-10-10 16:35:17.957  INFO 41960 --- [nio-9999-exec-1] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring DispatcherServlet 'dispatcherServlet'
2024-10-10 16:35:17.957  INFO 41960 --- [nio-9999-exec-1] o.s.web.servlet.DispatcherServlet        : Initializing Servlet 'dispatcherServlet'
2024-10-10 16:35:17.958  INFO 41960 --- [nio-9999-exec-1] o.s.web.servlet.DispatcherServlet        : Completed initialization in 1 ms
2024-10-10 16:35:17.979  INFO 41960 --- [nio-9999-exec-1] com.ntt.web.config.Listener2             : HttpSessionListener-start
2024-10-10 16:35:17.980  INFO 41960 --- [nio-9999-exec-1] com.ntt.web.controller.TestController    : 调用地址:/listener;count:1
2024-10-10 16:35:17.997  INFO 41960 --- [nio-9999-exec-1] com.ntt.web.config.Listener3             : ServletRequestListener-start
2024-10-10 16:35:47.376  INFO 41960 --- [ionShutdownHook] com.ntt.web.config.Listener2             : HttpSessionListener-end
2024-10-10 16:35:47.376  INFO 41960 --- [ionShutdownHook] com.ntt.web.config.Listener1             : ServletContextListener-end
2024-10-10 16:35:47.394  INFO 41960 --- [ionShutdownHook] com.alibaba.druid.pool.DruidDataSource   : {dataSource-0} closing ...

4.Aop

1. 简介
	 AOP(Aspect-Oriented Programming面向切面编程)是Spring框架的一个核心功能 它允许开发者在不修改业务逻辑代码的情况下 通过定义切面(Aspect)和通知(Advice)来增强代码的功能 
	 Spring AOP 主要用于日志记录 权限检查 事务管理等跨越多个请求的处理
	 Spring AOP 的核心概念包括
		切面(Aspect):切面是通知和切点的结合 它定义了何时何地以及如何应用通知
		通知(Advice):通知是切面的一个具体实现 它定义了在切点处需要执行的额外逻辑 
			Spring 支持以下类型的通知:
                前置通知(Before):在切点之前执行
                后置通知(After):在切点之后执行 无论方法是否成功
                返回通知(After Returning):在方法成功返回后执行
                异常通知(After Throwing):在方法抛出异常后执行
                环绕通知(Around):包围切点 可以在方法执行前后执行自定义逻辑
		切点(Pointcut):切点是应用程序中的一个或一组特定位置 如方法的执行或异常的抛出 切点表达式用于匹配这些位置
         连接点(Joinpoint):连接点是应用程序执行过程中的一个特定点 如方法调用或字段访问 Spring AOP 仅支持方法执行的连接点
         目标对象(Target Object):被代理的对象
         代理(Proxy):代理对象是AOP框架创建的对象 它包含目标对象的引用 并在调用目标对象的方法时应用切面
         织入(Weaving):织入是将切面应用到目标对象并创建代理对象的过程 织入可以在编译时 类加载时或运行时进行

2. 使用场景
2.1 日志记录
2.2 权限检查
2.3 事务管理
2.4 性能监控
2.5 异常处理
2.6 数据校验等等...

3. 使用方法
	流程步骤
		定义切面:创建一个类 使用 @Aspect 注解标记它作为切面
		定义切点:使用 @Pointcut 注解定义切点表达式
		定义通知:在切面类中定义通知方法 并使用相应的注解(如 @Before、@After、@AfterReturning、@AfterThrowing、@Around)标记它们
		启用AOP:在配置类上使用 @EnableAspectJAutoProxy 注解启用AOP (原生spring需要在配置文件配置 springboot默认启用)
		
	实现方式
		jdk动态代理:在运行时使用 Java 的 Proxy 类和 InvocationHandler 接口生成代理对象 JDK 动态代理只能代理实现了接口的类 因为它依赖于接口的实现
		CGLIB代理: 使用 CGLIB 库(Code Generation Library)在运行时动态生成被代理类的子类来创建代理对象 CGLIB 代理不要求被代理的类实现任何接口 因此它可以代理没有实现接口的类
		
	相关注解解释
	    @Aspect:将一个 java 类定义为切面类
	    @Pointcut:定义一个切入点 可以是一个规则表达式 比如下例中某个 package 下的所有函数 也可以是一个注解等
        @Before:在切入点开始处切入内容
        @After:在切入点结尾处切入内容 无论是否有异常 都会执行 类似于finally
        @AfterReturning:在切入点 return 内容之后处理逻辑 只有执行成功会执行 异常不会
        @Around:在切入点前后切入内容 并自己控制何时执行切入点自身的内容 原则上可以替代@Before和@After
        @AfterThrowing:用来处理当切入内容部分抛出异常之后的处理逻辑
        @Order(100):AOP 切面执行顺序 @Before 数值越小越先执行 @After 和 @AfterReturning 数值越大越先执行
        
    切点表达式
    	execution(<方法的修饰符><方法的返回类型><包.类.方法名(参数)><异常>)
    		修饰符(可省略): public private protected static 或者 * 可使用&&指定多个 
    		返回值(不可省略): void String *
             包|类|方法名: 方法名不可省略 可以是详细的包 类名 方法名 或者使用*通配符替代
             	*:匹配任意字符 匹配一个(包 类 方法 方法参数)
             	..: 匹配任意字符 匹配多个
             	+: 类型匹配 匹配指定类名
             参数: ()无参 (int)一个参数 (..)任意参数 
             	
    
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-aop</artifactId>
    <version>2.5.6</version>
</dependency>
package com.ntt.web.aop;

import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;


@Aspect  // 定义切面
@Component
@Slf4j
public class TestAspect
{

    // 定义切点
    @Pointcut("execution(* com.ntt.web.controller.TestController.*(..))")
    public void targetCut(){}

    // 实现通知
    @Before("targetCut()")
    public void before()
    {
        log.info("before");
    }

    @After("targetCut()")
    public void after()
    {
        log.info("after");
    }
	
    //@AfterReturning(value = "targetCut()", returning = "res")
    //public void afterReturn(JoinPoint jp, Object res)
    @AfterReturning("targetCut()")
    public void afterReturn()
    {
        log.info("afterReturn");
    }
	
    //@AfterThrowing(value = "targetCut()", throwing = "err")
    //public void afterThrowing(JoinPoint jp, Throwable err)
    @AfterThrowing("targetCut()")
    public void afterThrowing()
    {
        log.info("afterThrowing");
    }

    @Around("targetCut()")
    public Object around(ProceedingJoinPoint pjp)
    {
        Object oj = null;
        log.info("around-begin");
        try{
            // 目标业务处理
           oj = pjp.proceed();
        }catch (Throwable e){
            e.printStackTrace();
        }
        log.info("around-end");
        return oj;
    }

}
2024-10-11 17:23:11.646  INFO 37312 --- [nio-9999-exec-2] com.ntt.web.aop.TestAspect               : around-begin
2024-10-11 17:23:11.646  INFO 37312 --- [nio-9999-exec-2] com.ntt.web.aop.TestAspect               : before
2024-10-11 17:23:11.656  INFO 37312 --- [nio-9999-exec-2] com.ntt.web.controller.TestController    : 调用地址:/aop
2024-10-11 17:23:11.657  INFO 37312 --- [nio-9999-exec-2] com.ntt.web.aop.TestAspect               : afterThrowing
2024-10-11 17:23:11.657  INFO 37312 --- [nio-9999-exec-2] com.ntt.web.aop.TestAspect               : after
2024-10-11 17:23:11.659  INFO 37312 --- [nio-9999-exec-2] com.ntt.web.aop.TestAspect               : around-end


2024-10-11 17:24:46.781  INFO 37272 --- [nio-9999-exec-1] com.ntt.web.aop.TestAspect               : around-begin
2024-10-11 17:24:46.781  INFO 37272 --- [nio-9999-exec-1] com.ntt.web.aop.TestAspect               : before
2024-10-11 17:24:46.791  INFO 37272 --- [nio-9999-exec-1] com.ntt.web.controller.TestController    : 调用地址:/aop
2024-10-11 17:24:46.792  INFO 37272 --- [nio-9999-exec-1] com.ntt.web.aop.TestAspect               : afterReturn
2024-10-11 17:24:46.792  INFO 37272 --- [nio-9999-exec-1] com.ntt.web.aop.TestAspect               : after
2024-10-11 17:24:46.792  INFO 37272 --- [nio-9999-exec-1] com.ntt.web.aop.TestAspect               : around-end

5. 参考文档

[1] https://blog.csdn.net/qq_43842093/article/details/135578271

[2] https://segmentfault.com/a/1190000021823564#item-4

[3] https://blog.csdn.net/houpeibin2012/article/details/104449730

[4] https://www.baeldung.com/spring-aop

标签:INFO,web,---,拦截器,10,Spring,2024,监听器,com
From: https://www.cnblogs.com/fsh19991001/p/18458953

相关文章

  • Springboot使用EasyExcel 的填充模板导出,导出为多Sheet工作簿
    概述Springboot使用EasyExcel的填充模板导出,导出为多Sheet工作簿详细代码Excel数据填充/***使用EasyExcel写入Excel*@paramexcelModelFilePath 模板文件地址*@paramsheetNameAndDataMap Sheet名称与Sheet数据Map集合,key为Sheet名称,value为Sheet数据集合*@ret......
  • springboot如何做token的拦截校验
    1、新建一个拦截类@ComponentpublicclassLoginInterceptorimplementsHandlerInterceptor{@AutowiredprivateJwtUtiljwtUtil;@Value("${oaTokenKeyword}")privateStringoaTokenKeyword;@OverridepublicbooleanpreHandle(Http......
  • 【API文档】spring的Assert类
    org.springframework.util.Assert提供的方法列表:方法信息方法功能或适用场景参数详细解释booleanisAssignable(Class<?>superType,Class<?>subType)断言`subType`是`superType`的子类或实现类。superType:父类或接口类型。subType:子类或实现类类型。b......
  • java毕业设计-基于Springboot的多商家商城系统【代码+论文+PPT】
    全文内容包括:1、采用技术;2、系统功能;3、系统截图;4、部分代码;5、配套内容。索取方式见文末微信号,欢迎关注收藏!一、采用技术语言:Java1.8框架:Springboot数据库:MySQL5.7、8.0开发工具:IntelliJIDEA旗舰版其他:Maven3.8以上二、系统功能管理员管理:负责系统后台的整体运维,包......
  • Spring Boot应用开发
    SpringBoot是一种基于Spring框架的轻量级开发框架,它简化了Spring应用的开发过程,提供了自动化的配置方式以及丰富的生态和插件,非常适合用于快速构建和部署生产级别的Spring应用。以下是对SpringBoot应用开发的详细介绍:一、SpringBoot的核心思想及特性核心思想:SpringBoo......
  • 基于Springboot网上在线购物商城【附源码+文档】
    ......
  • 一、Spring Boot集成Spring Security之自动装配
    一、SpringBoot集成SpringSecurity专栏一、SpringBoot集成SpringSecurity之自动装配二、实现功能及软件版本说明使用SpringBoot集成SpringSecurity实现Servlet项目的安全个性化配置SpringBoot版本:2.7.18SpringSecurity版本:5.7.11三、创建SpringBoot项目创建Sp......
  • 如何在springboot中,全局配置produces="text/plain;charset=UTF-8"
    为什么要使用produces="text/plain;charset=UTF-8"?当不用这个配置时,接口返回的数据,是有斜杠的 配置后,就正常了 以前我的配置方式,是在每个接口上,都添加上produces="text/plain;charset=UTF-8"。但是这样显示不太好,每个接口都加的话,会比较耗费时间如何做到全局配置使用W......
  • 基于java+springboot的社区心理健康服务平台系统小程序
    基于java+springboot的社区心理健康服务平台系统,旨在为社区居民提供全面的心理健康支持。后端运用springboot构建稳定可靠的服务,负责处理用户信息管理、心理咨询师资源整合、心理测评工具管理以及预约咨询安排等核心业务,与数据库有效交互以存储用户心理健康档案、咨询......
  • 基于java+springboot的社区汽车共享平台系统
    基于java+springboot的社区汽车共享平台系统,致力于为社区居民提供便捷的汽车共享服务。后端采用springboot构建,高效处理车辆信息管理、用户认证与授权、预订流程控制及费用结算等业务,与数据库紧密交互确保车辆状态、用户信息及预订记录准确存储与快速检索。前端利用相......