过滤器Filter笔记

过滤器Filter笔记

PS:使用@Slf4j注解

此注解就是为了能够少写两行代码,不用每次都在类的最前边写上:
private static final Logger logger = LoggerFactory.getLogger(this.XXX.class);
我们只需要在类前面添加注解@Slf4j,即可使用log日志的功能了

首先必须要有该插件

在这里插入图片描述

并且加入该依赖

<dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-log4j12</artifactId>
        <version>1.7.25</version>
    </dependency>
    
    <dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <version>1.18.22</version>
</dependency>

使用:

在这里插入图片描述

在这里插入图片描述

1.当你使用过滤器时必须得配置过滤什么

第一次使用filter时:

在这里插入图片描述

方法里面什么都没有,并且前端网页不显示了

这是因为被过滤器默认过滤掉了所有的接口

2.过滤器的方法

  • init(): 此方法在只在过滤器创建的时候执行一次,用于初始化过滤器的属性
  • doFilter(): 该方法会对请求进行拦截,用户需要在该方法中自定义对请求内容以及响应内容进行过滤的,调用该方法的入参 FilterChain对象的 doFilter 方法对请求放行执行后面的逻辑,若未调用 doFilter 方法则本次请求结束,并向客户端返回响应失败
  • destroy(): 此方法用于销毁过滤器,过滤器被创建以后只要项目一直运行,过滤器就会一直存在,在项目停止时,会调用该方法销毁过滤器,也可以用于过滤器销毁前,完成某些资源的回收。

3.过滤器大致运行原理

在这里插入图片描述

4.过滤器常用的地方

    1. Authentication Filters,即用户访问权限过滤
    1. Logging and Auditing Filters, 日志过滤,可以记录特殊用户的特殊请求的记录等
    1. Image conversion Filters,图像转换过滤器
    1. Data compression Filters ,数据转换
    1. Encryption Filters ,安全加密
    1. Tokenizing Filters ,词法分析
    1. Filters that trigger resource access events ,资源访问事件触发过滤器
    1. XSL/T filters
    1. Mime-type chain Filter ,文件类型链过滤器

5.过滤器的过滤

成功过滤 /filter

问题: 但使用==servletRequest.getParameter==取出数据的时候int数据会变成字符串

 @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) servletRequest;

        log.info("请求地址:"+request.getRequestURI());
        HttpServletResponseWrapper wrapper = new HttpServletResponseWrapper((HttpServletResponse) servletResponse);
         log.info("对请求进行过滤");
        // 请求url中包含/filter,继续执行,否则直接放行
        if (request.getRequestURI().contains("/filter")){
            // 交给下一个过滤器或servlet处理
            log.info("过滤了filter");
            if ( servletRequest.getParameter("size") == "2"){
                log.info("page size :{}",servletRequest.getParameter("size")+"拦截size为2的请求");
            }else {
                log.info("page size :{}",servletRequest.getParameter("size"));
                filterChain.doFilter(servletRequest,servletResponse);
            }
        }else {
            filterChain.doFilter(servletRequest,servletResponse);
            log.info("对返回进行过滤");
        }
    }

使用 : filterChain.doFilter(servletRequest,servletResponse); 放行请求

request.getRequestURI() 获取请求的URL(即Controller中的url)

解决: int size=Integer.parseInt(request.getParameter(“size”));//强转成整型

6.过滤器重定向到其他方法

servletRequest.getRequestDispatcher("/selectall").forward(servletRequest,servletResponse);

7.完整过滤器代码(2024.3.5)

PS:若是用注解配置则需要在启动类加入@ServletComponentScan(“com.example.demofilter.filter”)

@Slf4j
@Component
@WebFilter(filterName = "MyFilter",
        /**
         * 通配符(*)表示对所有的web资源进行拦截
        */
        urlPatterns = "/*"
)
public class LogFilter implements Filter {
/**
 * 过滤器初始化
 * explain:在容器中创建当前过滤器的时候自动调用
 *
 * @param filterConfig
**/
 @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        log.info("==================初始化过滤器=============");
        Filter.super.init(filterConfig);
    }
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        log.info("------------- LogFilter 开始 -------------");
        log.info("请求地址: {} {}", request.getRequestURL().toString(), request.getMethod());
        log.info("远程地址: {}", request.getRemoteAddr());
//        HttpServletResponseWrapper wrapper = new HttpServletResponseWrapper((HttpServletResponse) servletResponse);
        HttpServletResponse resp = (HttpServletResponse) servletResponse;
         log.info("对请求进行过滤");
      //记录当前时间
        long startTime = System.currentTimeMillis();
        // 请求url中包含/filter,继续执行,否则直接放行
        if (request.getRequestURI().contains("/filter")){
            // 交给下一个过滤器或servlet处理
            log.info("过滤了filter");
            int size=Integer.parseInt(request.getParameter("size"));//强转成整型
            if ( size == 2){
                log.info("page size :{}",servletRequest.getParameter("size")+"拦截size为2的请求");
                //拦截后重定向到其他方法
              //  servletRequest.getRequestDispatcher("/selectall").forward(servletRequest,servletResponse);
                log.info("------------- LogFilter 结束 耗时:{} ms -------------", System.currentTimeMillis() - startTime);
            }else {
                log.info("page size :{}",servletRequest.getParameter("size"));
                filterChain.doFilter(servletRequest,servletResponse);
                log.info("------------- LogFilter 结束 耗时:{} ms -------------", System.currentTimeMillis() - startTime);
            }

        }else {
            filterChain.doFilter(servletRequest,servletResponse);
            log.info("对返回进行过滤");
            log.info("------------- LogFilter 结束 耗时:{} ms -------------", System.currentTimeMillis() - startTime);

        }
    }

    @Override
    public void destroy() {
        log.info("===================销毁过滤器==============");
        Filter.super.destroy();
    }
}

配置类:

@Configuration
public class FilterConfig {
    @Bean
    public FilterRegistrationBean myFilterBean(){
         FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();
        //指明需要被注册的过滤器
         filterRegistrationBean.setFilter(new LogFilter());
        //添加过滤路径
        filterRegistrationBean.addUrlPatterns("/filter");
        return filterRegistrationBean;
    }
}

配置过滤器,使用FilterRegistrationBean中的方法:

1.setFilter
将建好的过滤器类对象传进去
指明需要被注册的过滤器,即是哪个过滤器的Bean

2.setOrder
设置过滤器执行次序
数字越小越先执行
为保证一定最先执行,可以使用Integer.MIN_VALUE

3.addUrlPatterns
配置过滤器规则

4.setName
设置过滤器名称

5.setUrlPatterns
配置多个过滤规则,参数List

7.HttpServletResponse.sendRedirect方法和RequestDispatcher.forward方法

下面是HttpServletResponse.sendRedirect方法实现的请求重定向与RequestDispatcher.forward方法实现的请求转发的总结比较:

(1)RequestDispatcher.forward方法只能将请求转发给同一个WEB应用中的组件;而 HttpServletResponse.sendRedirect 方法不仅可以重定向到当前应用程序中的其他资源,还可以重定向到同一个站点上的其他应用程序中的资源,甚至是使用绝对URL重定向到其他站点的资源。如果传递给HttpServletResponse.sendRedirect 方法的相对URL以“/”开头,它是相对于整个WEB站点的根目录 ;如果创建RequestDispatcher对象时指定的相对URL以“/”开头,它是相对于当前WEB应用程序的根目录 。
(2)调用HttpServletResponse.sendRedirect方法重定向的访问过程结束后,浏览器地址栏中显示的URL会发生改变,由初始的URL地址变成重定向的目标URL;而调用RequestDispatcher.forward 方法的请求转发过程结束后,浏览器地址栏保持初始的URL地址不变。

(3)HttpServletResponse.sendRedirect方法对浏览器的请求直接作出响应,响应的结果就是告诉浏览器去重新发出对另外一个URL的访问请求,这个过程好比有个绰号叫“浏览器”的人写信找张三借钱,张三回信说没有钱,让“浏览器”去找李四借,并将李四现在的通信地址告诉给了“浏览器 ”。于是,“浏览器”又按张三提供通信地址给李四写信借钱,李四收到信后就把钱汇给了“浏览器”。可见,“浏览器”一共发出了两封信和收到了两次回复,“ 浏览器”也知道他借到的钱出自李四之手。RequestDispatcher.forward方法在服务器端内部将请求转发给另外一个资源,浏览器只知道发出了请求并得到了响应结果,并不知道在服务器程序内部发生了转发行为。这个过程好比绰号叫“浏览器”的人写信找张三借钱,张三没有钱,于是张三找李四借了一些钱,甚至还可以加上自己的一些钱,然后再将这些钱汇给了“浏览器”。可见,“浏览器”只发出了一封信和收到了一次回复,他只知道从张三那里借到了钱,并不知道有一部分钱出自李四之手。

(4)RequestDispatcher.forward方法的调用者与被调用者之间共享相同的request对象和response对象,它们属于同一个访问请求和响应过程 ;而HttpServletResponse.sendRedirect方法调用者与被调用者使用各自的request对象和response对象,它们属于两个独立的访问请求和响应过程。对于同一个WEB应用程序的内部资源之间的跳转,特别是跳转之前要对请求进行一些前期预处理,并要使用HttpServletRequest.setAttribute方法传递预处理结果,那就应该使用 RequestDispatcher.forward方法。不同WEB应用程序之间的重定向,特别是要重定向到另外一个WEB站点上的资源的情况,都应该使用HttpServletResponse.sendRedirect方法。

(5)无论是RequestDispatcher.forward方法,还是HttpServletResponse.sendRedirect方法,在调用它们之前,都不能有内容已经被实际输出到了客户端。如果缓冲区中已经有了一些内容,这些内容将被从缓冲区中清除。

(6) 代码的执行:

无论是 request.getRequestDispatcher(path).forward(request, response)还是response.sendRedirect,程序都会在执行完该句的情况下继续向下执行,因此在必要的时候应该使用return终止该方法.

对于 request.getRequestDispatcher(path).forward(request, response),在执行完该方法的时候再进行对request的操作已经没有任何意义,如果在该方法之后再进行request.setAttribute(),该值将不会被放进当前请求的request中.

response.setRedirect:该方法执行之后,接下来的方法也会被执行.但是使用该方法的时候,会发送一个全新的request,将不再使用原先的request,因此不论在该方法执行之前,还是在该方法执行之后,对request操作,都是无效的.

8、中文乱码问题

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值