SpringBoot使用过滤器,拦截器(基于AOP),监听器(都是基于注解的)

在Springboot整合SSM的基础上进行

简单介绍

SSM就应该用过下面三个了,我这主要说一下它们的用途

  1. 过滤器:对web服务器管理所有的web资源,主要是对用户的一些请求进行一些预处理,并在服务器响应后再进行预处理,返回给用户,例如jsp,静态图片等,用途:1、实现URL级别的访问控制,2、过滤敏感词汇,3、某些信息用*隐藏。
  2. 拦截器:基本上都是AOP,当某个方法或字段被访问时进行拦截,在之前在之后 加入某些操作,用途:权限验证,判断用户是否登录,或者再做某一操作时要确定满足某一定的条件
  3. 监听器:用于监听servletContextHttpSessionservletRequest等域对象的创建销毁事件,可以在这些事件发生前和发生后进行处理。用途:1、用于统计在线人数和在线用户,2、系统启动时加载初始化信息,3、统计网站访问量,4、记录用户访问路径

这篇博客需要的目录结构

在这里插入图片描述
在进行下面内容看的时候如果目录结构搞不清可以回来看看,这个觉看着乱,那就看下面这个
在这里插入图片描述
画红圈的启动类和上面文件夹是平级的

1、过滤器

package com.ssm.filter;

import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter;


/**
 * @author 作者
 * @data 2019年8月2日 
 */
@WebFilter(filterName = "myFilter", urlPatterns = "/*") //一个是filter的名字,一个是url为什么时用此过滤器,其他的看源码
public class MyFilter implements Filter{
	@Override
	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
			throws IOException, ServletException {
		System.out.println("这是我的Filter");
		//放行
		chain.doFilter(request, response);
		
	}
	
} 
	//下面两个如果没有可以自己添加上,看源码,有这两个,只是不是必须的
    @Override
    public void destroy() {

    }

    @Override
    public void init(FilterConfig arg0) throws ServletException {

    }

Filter,必须要有名字,所有的过滤器执行顺序是根据Filter的名字字母顺序来执行的
注意:需要在springboot的运行类增加@ServletComponentScan注解,添加上Filter的路径
示例

@SpringBootApplication
@ServletComponentScan("com.ssm.filter")//这个是扫描包的路径
public class SpringBoot1Application {

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

}

如果不加@ServletComponentScan就算这个类和运行类平级或者子级不会被扫描
在这里插入图片描述

2、拦截器(基于AOP)

需要添加依赖

   <!-- AOP -->
      	<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-aop</artifactId>
        </dependency>
(1)基于切点表达式进行拦截

这做一个示例:对于controller 类里的所有方法进行拦截,拦截就让它进行日志管理吧,这篇博客只有AOP不需要在启动类上加@ServletComponentScan,其他两个都需要

AOP做日志管理的类

package com.ssm.aop;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
/**
 * @author 作者
 * @data 2019年8月2日 
 */
@Aspect   //这两个注解必须有
@Component 
public class MyAspect{
	private final static Logger log = LoggerFactory.getLogger(MyAspect.class);
	
	//定义切点位置:下面如果你在SSM中用AOP,在xml中配的就是下面
	@Pointcut("execution(* com.ssm.controller..*.*(..))")
	public void performance() {
	}
	
	/**
	 * 环绕通知记录时间
	 * 
	 * @param joinPoint
	 * @return
	 * @throws Throwable
	 */
	@Around("performance()")
	public Object doLog(ProceedingJoinPoint joinPoint) throws Throwable {
	
	    // 记录起始时间
	    long begin = System.currentTimeMillis();
	    Object result = "";
	    /** 执行目标方法 */
	    try {
	        result = joinPoint.proceed();
	    } catch (Exception e) {
	        log.error("日志记录发生错误, errorMessage: {}", e.getMessage());
	    } finally {
	        /** 记录操作时间 */
	        long took = (System.currentTimeMillis() - begin) / 1000;
	        log.info("controller执行时间为: {}秒", took);
	    }
	    System.out.println("66666666");
	    return result;
	}
	
	/**
	 * 前置通知
	 * 
	 * @param joinPoint
	 * @throws Throwable
	 */
	@Before("performance()")
	public void doBefore(JoinPoint joinPoint) throws Throwable {
	    // 接收到请求,记录请求内容
	    log.info("doBefore");
	    System.out.println("1111111");
	}
	
	}

不光只有上面这两个,总共有@Before,@After,@AfterReturning,@AfterThrowing,@Around这五种
想知道他们的用法和想知道切点表达式怎么写,请参考Springboot(二十一)@Aspect 切面注解使用

启动类如果和上面的类平级或者和它父级平级,就不用在启动类上添加注解@ServletComponentScan它会自己扫描

结果
在这里插入图片描述

(2)基于注解(需要自己手写注解)

自己写的注解

package com.ssm.annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * @author 作者
 * @data 2019年8月2日 
 */
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation {
	String operateDescription();// 记录日志的操作类型,不写默认值就是一个必须填的注解
}

AOP用手写注解做日志管理的类

package com.ssm.aop;

import java.lang.reflect.Method;
import java.sql.SQLException;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import com.ssm.annotation.MyAnnotation;

/**
 * @author 作者
 * @data 2019年8月2日 
 */
@Aspect  
@Component 
public class MyAspect2 {
	 private final static Logger log = LoggerFactory.getLogger(MyAspect2.class);

	    /**
	     * 环绕通知处理
	     *
	     * @param pjp
	     * @return
	     * @throws Throwable
	     */
	    @Around("@annotation(com.ssm.annotation.MyAnnotation)")
	    public Object aroundAdvice(ProceedingJoinPoint pjp) throws Throwable {
	        // 1.方法执行前的处理,相当于前置通知
	        // 获取方法签名
	        MethodSignature methodSignature = (MethodSignature) pjp.getSignature();
	        // 获取方法
	        Method method = methodSignature.getMethod();
	        // 获取方法上面的注解
	        MyAnnotation myAnno = method.getAnnotation(MyAnnotation.class);
	        // 获取到类名
	        String targetName = pjp.getTarget().getClass().getName();
	        // 获取到方法名字
	        String methodName = method.getName();
	        // 获取操作描述的属性值
	        String operateDescription = myAnno.operateDescription();
	        Object result = null;
	        try {
	            // 让代理方法执行
	            result = pjp.proceed();
	            // 2.相当于后置通知(方法成功执行之后走这里)
	        } catch (SQLException e) {
	            // 3.相当于异常通知部分
	        } finally {
	            // 4.相当于最终通知
	            log.info("class->{},methodName->{},operateDescription->{}", targetName, methodName, operateDescription);
	        }
	        System.out.println("基于手写注解的AOP拦截功能实现");
	        return result;
	    }
}

在这里插入图片描述
还有很多用途,不光这些,剩下的需要自己去发掘
多谢Springboot的日志管理&Springboot整合Junit测试&Springboot中AOP的使用

3、监听器

监听器类

package com.ssm.listener;

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

/**
 * @author 作者
 * @data 2019年8月2日 
 */
@WebListener()
public class MyListener implements HttpSessionListener{

	 public static int online = 0;

	    @Override
	    public void sessionCreated(HttpSessionEvent se) {
	        System.out.println("创建session,在线用户数:" + (++online));
	    }

	    @Override
	    public void sessionDestroyed(HttpSessionEvent se) {
	        System.out.println("销毁session,在线用户数:" + (--online));
	        online--;
	    }
}

controller类

@Controller
public class UserController {
		@Autowired
		private UserService userService;
		@RequestMapping("findAll")
		public String findAll(Model model, HttpServletRequest request) throws Exception {
			List<User> list = userService.getAllUser();
			model.addAttribute("list",list);			
			request.getSession().setAttribute("55", "55");
			return "index";
			
		}
}

启动类


@SpringBootApplication
@ServletComponentScan("com.ssm.listener") //需要扫描包
public class SpringBoot1Application {

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

}

结果:
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值