拦截器与过滤器(一)介绍与使用方法

一、拦截器:

1、介绍

依赖于web框架,如在SpringMVC中就是依赖于SpringMVC框架。在实现上,基于Java的反射机制,属于面向切面编程(AOP)的一种运用。

2、使用场景:

由于拦截器是基于web框架的调用,因此可以使用Spring的依赖注入(DI)进行一些业务操作,同时一个拦截器实例在一个controller生命周期之内可以多次调用。但是缺点是只能对controller请求进行拦截,对其他的一些比如直接访问静态资源的请求则没办法进行拦截处理。

3、springboot使用拦截器:

自定义拦截器类实现HandlerInterceptor接口,再把这个拦截器类加载到全文配置中。如拦截器记录访问日志:

(1)自定义拦截器类:



import com.alibaba.fastjson.JSON;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.HashMap;
import java.util.Map;
@Component
public class ActionHandle implements HandlerInterceptor {

    @Autowired
    private UserActionLogService userActionLogService;

    @Override
    public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception {
        try {
            String userId = SpringContextUtil.getCurrentUserId();
            String requestUrl = httpServletRequest.getRequestURI();
            Map<String, String[]> originRequestMap = httpServletRequest.getParameterMap();
            Map<String,String> requestMap = new HashMap<String,String>();
            for (String key : originRequestMap.keySet()) {
                String[] values = originRequestMap.get(key);
                requestMap.put(key,values[0]);
            }
            String requestParam = JSON.toJSONString(requestMap);
            String requestIp = httpServletRequest.getRemoteAddr();
            UserActionLog userActionLog = new UserActionLog(userId, requestUrl, requestParam, requestIp, "tableAdmin");
            userActionLogService.insert(userActionLog);
        } catch (Exception e) {
        }
        return true;

    }

    @Override
    public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {

    }

    @Override
    public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {

    }
}

(2)、加载(编程式加载) :

package com.demo.config;


import com.demo.interceptor.MyInterceptor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringBootConfiguration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;

@SpringBootConfiguration
public class MySpringMVCConfig extends WebMvcConfigurerAdapter {

    @Autowired
    private ActionHandle myInterceptor;

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(myInterceptor).addPathPatterns("/**");
    }


}

 也可以使用xml式加载。 

4、demo:

现有页面

     

export function updateReport(report, emails, views) {
  const id = report.id
  const reportName = report.reportName
  const safeLevel = report.safeLevel
  const reportUrl = report.reportUrl
  const remark = report.remark
  const reportType = report.reportType
  return request({
 
    url: '/report/updateReport',
    method: 'post',
    data: {
      id,
      reportName,
      reportUrl,
      safeLevel,
      remark,
      reportType,
      emails,
      views
    }
  })
 
 
export function deleteReport(reportId) {
  return request({
    url: '/report/deleteReport',
    method: 'post',
    data: {
      reportId
    }
  })
}

列表有查看、编辑、删除功能,前端判断该条数据的creator与当前登录用户是不是同一个人,如果是则展示编辑和删除按钮。为防止恶意攻击,可以在后端再加个拦截器,双重控制。

 
@Component
public class ReportHandler implements HandlerInterceptor{
	
	@Autowired
	private ReportService reportService;
 
	@Override
	public void afterCompletion(HttpServletRequest arg0,
			HttpServletResponse arg1, Object arg2, Exception arg3)
			throws Exception {
		// TODO Auto-generated method stub
		
	}
 
	@Override
	public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1,
			Object arg2, ModelAndView arg3) throws Exception {
		// TODO Auto-generated method stub
		
	}
 
	@Override
	public boolean preHandle(HttpServletRequest req, HttpServletResponse arg1,
			Object arg2) throws Exception {
		
		try{
			String requestURI = req.getRequestURI();
            //是删除或者编辑请求
			if(requestURI.indexOf("updateReport")!=-1 || requestURI.indexOf("deleteReport")!=-1){
				String reportId = null;
              //删除的参数为reportId
				if(req.getParameter("reportId") != null){
					reportId = req.getParameter("reportId");
				}
             //编辑的参数为id
				if(req.getParameter("id") != null){
					reportId = req.getParameter("id");
				}
				Report report = reportService.getById(reportId);
				User user = new SessionUtil().getCurrentUser();
				if(!report.getCreator().equals(user.getId())){
					return false;
				}
			}
			return true;
		}catch (Exception e) {
			return true;
		}
		
	}
 
}

二、过滤器:

1、介绍

它依赖于servlet容器。在实现上,基于函数回调,它可以对几乎所有请求进行过滤,但是缺点是一个过滤器实例只能在容器初始化时调用一次

2、使用场景

使用过滤器的目的,是用来做一些过滤操作,获取我们想要获取的数据,比如:在Javaweb中,对传入的request、response提前过滤掉一些信息,或者提前设置一些参数,然后再传入servlet或者Controller进行业务逻辑操作。通常用的场景是:

(1)在过滤器中修改字符编码(CharacterEncodingFilter)

(2)在过滤器中修改HttpServletRequest的一些参数(XSSFilter(自定义过滤器)),如:过滤低俗文字、危险字符等。

3、springboot使用过滤器:

自定义过滤器类实现Javax.serlvet.Filter接口(对应servlet-api.jar),加上Component注解可以被扫描到即可,不需要其他的配置了。demo:

package com.demo.filter;

import org.springframework.stereotype.Component;

import javax.servlet.*;
import java.io.IOException;
@Component
public class MyFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        System.out.print("filter");
        chain.doFilter(request,response);
    }

    @Override
    public void destroy() {

    }
}

三、比较:

1、关系结构:

容器是Tomcat,拦截器,过滤器,他们的关系结构:

在这里插入图片描述在这里插入图片描述

①:拦截器是基于java的反射机制,而过滤器基于函数回调。
②:过滤器依赖于servlet容器,拦截器不依赖于servlet容器。
③:拦截器只能对action请求起作用,而过滤器几乎对所有的请求都起作用。
④:拦截器可以访问action上下文,值栈里的对象,而过滤器不能。
⑤:在action的生命周期中,拦截器可以多次被调用,而过滤器只能在容器初始化时被调用一次。
⑥:拦截器可以获取IOC容器中的各个bean,而过滤器就不行,(在拦截器里注入一个service,可以调用业务逻辑)。
⑦:过滤器是在请求进入容器后,但进入servlert前进行预处理的。响应请求也是,在servlet处理结束后,返回给客户端前触发。而拦截器提供了三个方法支持(1)preHandle:预处理回调方法,实现处理器的预处理(如登录检查),第三个参数为响应的处理器(如我们上一章的Controller实现); 返回值:true表示继续流程(如调用下一个拦截器或处理器);false表示流程中断(如登录检查失败),不会继续调用其他的拦截器或处理器,此时我们需要通过response来产生响应;postHandle:后处理回调方法,实现处理器的后处理(但在渲染视图之前),此时我们可以通过modelAndView(模型和视图对象)对模型数据进行处理或对视图进行处理,modelAndView也可能为null。
afterCompletion:整个请求处理完毕回调方法,即在视图渲染完毕时回调,如性能监控中我们可以在此记录结束时间并输出消耗时间,还可以进行一些资源清理,类似于try-catch-finally中的finally,但仅调用处理器执行链中preHandle返回true的拦截器的afterCompletion。

2、区别:

(1)使用范围不同:Filter是Servlet规范规定的,只能用于web程序中。而拦截器既可以用于web程序,也可以用于Application、swing程序中。
(2)规范不同:Filter是在servlet规范中定义的,是Servlet容器支持的,而拦截器是在spring容器内的,是spring框架支持的。
(3)使用的资源不同:同其他的代码块一样,拦截器也是一个spring的组件,归spring管理,配置在spring文件中,因此能使用spring里的任何资源,独享。例如service对象、数据源、事务管理等,通过IOC注入到拦截器即可;而Filter不能。
(4)深度不同:Filter只在Servlet前后起作用。而拦截器能深入到方法前后、异常抛出前后等。因此拦截器的使用灵活性更大。所以在Spring为基础的构架的程序中,优先使用拦截器。

(5)原理不同:

拦截器(Interceptor)是基于Java的反射机制;过滤器(Filter)是基于函数回调。

3、过滤器、拦截器、监听器使用场景:

(1)拦截器:

用于对象拦截,行为干预(可以改变拦截对象的属性和行为)。从灵活性上说拦截器功能更强大些,Filter能做的事情,都能做,而且可以在请求前,请求后执行,比较灵活。

参数校验(sql注入检验)、做xss攻击校验(两种方式,一种是流,一种是直接获取),做校验签名,做鉴权,请求计数(限流)等。

(2)过滤器:

,Filter主要是针对URL地址做一个编码的事情、过滤掉没用的参数、安全校验(比较泛的,比如登录不登录之类)。用于属性甄别,对象收集(不可改变过滤对象的属性和行为)

(3)监听器:用于对象监听,行为记录(不可改变监听对象的属性和行为)

4、执行顺序:

过滤前-拦截前-Action处理-拦截后-过滤后

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

w_t_y_y

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

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

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

打赏作者

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

抵扣说明:

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

余额充值