道阻且长,行则将至,走慢一点没关系,不停下就好了.|

Ac_c0mpany丶

园龄:3年7个月粉丝:6关注:3

2022-11-30 16:49阅读: 600评论: 0推荐: 0

Spring Boot中使用Filter过滤器

Filter过滤器

一、引入

在和管理员有关的Controller中,接口都需要判断当前用户是否为管理员,如果是管理员,则可以操作目录;如果不是管理员,则不能操作;这一连串的身份验证代码都是固定的,并且在每一个接口中都需要编写,显然代码没有得到重复利用。为了解决这一问题,可以使用Servlet规范中的Filter过滤器来解决这个问题。

二、Filter介绍

  • Filter是过滤器(是一个Java程序)
  • Filter可以在Servlet这个目标程序执行之前添加代码。也可以在目标Servlet执行之后添加代码。之前之后都可以添加过滤规则。
  • 一般情况下,都是在过滤器当中编写公共代码。

三、Filter实现(原始实现方式)

  • 第一步:编写一个Java类实现一个接口:jarkata.servlet.Filter。并且实现这个接口当中所有的方法。

    • init方法:在Filter对象第一次被创建之后调用,并且只调用一次。
    • doFilter方法:只要用户发送一次请求,则执行一次。发送N次请求,则执行N次。在这个方法中编写过滤规则。
    • destroy方法:在Filter对象被释放/销毁之前调用,并且只调用一次。
  • 第二步:注册Filter

    • 在web.xml文件中对Filter进行配置。这个配置和Servlet很像。

      • <filter>
            <filter-name>filter2</filter-name>
            <filter-class>com.bjpowernode.javaweb.servlet.Filter2</filter-class>
        </filter>
        <filter-mapping>
            <filter-name>filter2</filter-name>
            <url-pattern>*.do</url-pattern>
        </filter-mapping>
        
    • 或者使用注解进行注册:@WebFilter({"*.do"})

      • // 访问这个/abc路径就会执行这个过滤器
        @WebFilter("/abc")
        public class AdminFilter implements Filter {
            @Override
            public void init(FilterConfig filterConfig) throws ServletException {
        
            }
        
            @Override
            public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
                
            }
        
            @Override
            public void destroy() {
        
            }
        }
        

四、Filter相关知识点

  • 注意:

    • Servlet对象默认情况下,在服务器启动的时候是不会新建对象的。
    • Filter对象默认情况下,在服务器启动的时候会新建对象。
    • Servlet是单例的。Filter也是单例的。(单实例)
  • 目标Servlet是否执行,取决于两个条件:

    • 第一:在过滤器当中是否编写了:chain.doFilter(request, response); 代码。(放行)
    • 第二:用户发送的请求路径是否和Servlet的请求路径一致。
  • chain.doFilter(request, response); 这行代码的作用:

    • 执行下一个过滤器,如果下面没有过滤器了,执行最终的Servlet
  • 注意:Filter的优先级,天生的就比Servlet优先级高。

    • /a.do 对应一个Filter,也对应一个Servlet。那么一定是先执行Filter,然后再执行Servlet。
  • 关于Filter的配置路径:

    • /a.do、/b.do、/dept/save。这些配置方式都是精确匹配
    • /* 匹配所有路径
    • *.do 后缀匹配。不要以 / 开始
    • /dept/* 前缀匹配
  • 在web.xml文件中进行配置的时候,Filter的执行顺序是什么?

    • 依靠filter-mapping标签的配置位置,越靠上优先级越高。
  • 过滤器的调用顺序,遵循数据结构。

  • 使用@WebFilter的时候,Filter的执行顺序是怎样的呢?

    • 执行顺序是:比较Filter这个类名。
    • 比如:FilterA和FilterB,则先执行FilterA。
    • 比如:Filter1和Filter2,则先执行Filter1。
  • Filter的生命周期?

    • 和Servlet对象生命周期一致。
    • 区别:Filter默认情况下,在服务器启动阶段就实例化。Servlet不会。
  • Filter过滤器这里有一个设计模式:

    • 责任链设计模式
    • 过滤器最大的优点:
      • 在程序编译阶段不会确定调用顺序。因为Filter的调用顺序是配置到web.xml文件中的,只要修改web.xml配置文件中filter-mapping的顺序就可以调整Filter的执行顺序。显然Filter的执行顺序是在程序运行阶段动态组合的。那么这种设计模式被称为责任链设计模式。
    • 责任链设计模式最大的核心思想:
      • 在程序运行阶段,动态的组合程序的调用顺序。

五、Spring Boot项目中使用Filter过滤器

过滤器是AOP(面向切面编程)思想的具体实现。可以过滤浏览器发出的请求,并且决定放行请求还是中断请求。

机制简述
在浏览器对服务器发起请求或者服务器对浏览器响应,都会经过过滤器。

基于过滤器的机制,我们可以在过滤器中对请求和响应做一些处理,可以在过滤器中决定是否放行,例如:校验请求中有没有敏感字符串,校验有没有Session,实现URL级别的权限控制、压缩响应信息、编码格式等。

5.1 Spring Boot使用过滤器的两种方式

  1. 使用spring boot提供的FilterRegistrationBean注册Filter
  2. 使用原生servlet注解@WebServlet,并在启动类上面增加注解@ServletComponentScan注册Filter

两种方法的本质都是一样的,都是去FilterRegistrationBean注册Filter

总结:定义Filter + 注册Filter

5.2 方法一:使用SpringBoot配置类实现

  • 定义一个Filter类
  1. 定义一个Filter类实现Filter接口
  2. 重写三个方法:init、doFilter、destory

AdminFilter.java



package com.kyk.imoocmall.filter;

import com.kyk.imoocmall.common.Constant;
import com.kyk.imoocmall.pojo.User;

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

/**
 * 管理员校验过滤器
 * @FileName imooc-mall
 * @Author keyongkang
 * @Create 2022-11-30-9:14
 */

public class AdminFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        request.setCharacterEncoding("utf-8");
        servletResponse.setContentType("text/html;charset=utf-8");
        servletResponse.setCharacterEncoding("utf-8");

        HttpSession session = request.getSession();

        // 对当前用户进行校验
        User currentUser = (User)session.getAttribute(Constant.IMOOC_MALL_USER);

        if (currentUser == null) {
            // 用户未登录
            //return R.error(ImoocMallExceptionEnum.USER_NOT_LOGIN);
            PrintWriter out = new HttpServletResponseWrapper((HttpServletResponse) servletResponse).getWriter();
            out.write("{\n" +
                    "    \"status\": 10007,\n" +
                    "    \"msg\": 用户未登录,\n" +
                    "    \"data\": null\n" +
                    "}");
            out.flush();
            out.close();
            return;
        }

        if (currentUser.getRole() != 2) {
            // 非管理员操作
            PrintWriter out = new HttpServletResponseWrapper((HttpServletResponse) servletResponse).getWriter();
            out.write("{\n" +
                    "    \"status\": 10009,\n" +
                    "    \"msg\": \"当前用户不是管理员,无操作权限\",\n" +
                    "    \"data\": null\n" +
                    "}");
            out.flush();
            out.close();
        }
        filterChain.doFilter(servletRequest, servletResponse);
    }

    @Override
    public void destroy() {

    }
}

该过滤器是用来校验管理员登录的。

  • 注册Filter

AdminFilterConfig.java

package com.kyk.imoocmall.config;

import com.kyk.imoocmall.filter.AdminFilter;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * Admin过滤器的配置
 * @FileName imooc-mall
 * @Author keyongkang
 * @Create 2022-11-30-9:30
 */

@Configuration //定义此类为配置类,必须添加!
public class AdminFilterConfig {
    @Bean
    public AdminFilter adminFilter() {
        return new AdminFilter();
    }

    // 使用spring boot提供的FilterRegistrationBean注册Filter
    @Bean(name = "adminFilterConf")
    public FilterRegistrationBean adminFilterConfig() {
        FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();
        filterRegistrationBean.setFilter(adminFilter());
        filterRegistrationBean.addUrlPatterns("/admin/category/*");
        filterRegistrationBean.addUrlPatterns("/admin/product/*");
        filterRegistrationBean.addUrlPatterns("/admin/order/*");
        filterRegistrationBean.setName("adminFilterConf");
        return filterRegistrationBean;
    }
}

总结:自定义一个Filter,然后自定义AdminFilterConfig类,使用spring boot提供的FilterRegistrationBean注册Filter

5.3 方法二:使用原生servlet注解@WebFilter + @ServletComponentScan

  • 定义一个Filter类

在filter类上使用@WebFilter注解

package com.kyk.imoocmall.filter;


import com.kyk.imoocmall.common.Constant;
import com.kyk.imoocmall.pojo.User;

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

/**
 * 管理员校验过滤器
 * @FileName imooc-mall
 * @Author keyongkang
 * @Create 2022-11-30-9:14
 */

@WebFilter(urlPatterns = "/admin/category/*") // 注意
@Component
public class AdminFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        request.setCharacterEncoding("utf-8");
        servletResponse.setContentType("text/html;charset=utf-8");
        servletResponse.setCharacterEncoding("utf-8");

        HttpSession session = request.getSession();

        // 对当前用户进行校验
        User currentUser = (User)session.getAttribute(Constant.IMOOC_MALL_USER);

        if (currentUser == null) {
            // 用户未登录
            //return R.error(ImoocMallExceptionEnum.USER_NOT_LOGIN);
            PrintWriter out = new HttpServletResponseWrapper((HttpServletResponse) servletResponse).getWriter();
            out.write("{\n" +
                    "    \"status\": 10007,\n" +
                    "    \"msg\": 用户未登录,\n" +
                    "    \"data\": null\n" +
                    "}");
            out.flush();
            out.close();
            return;
        }

        if (currentUser.getRole() != 2) {
            // 非管理员操作
            //return R.error(ImoocMallExceptionEnum.NOT_ADMIN);
            PrintWriter out = new HttpServletResponseWrapper((HttpServletResponse) servletResponse).getWriter();
            out.write("{\n" +
                    "    \"status\": 10009,\n" +
                    "    \"msg\": \"当前用户不是管理员,无操作权限\",\n" +
                    "    \"data\": null\n" +
                    "}");
            out.flush();
            out.close();
        }
        filterChain.doFilter(servletRequest, servletResponse);
    }

    @Override
    public void destroy() {

    }
}
  • 在启动类上面增加注解@ServletComponentScan开启Servlet支持
package com.kyk.imoocmall;

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.ServletComponentScan;
import springfox.documentation.oas.annotations.EnableOpenApi;

@EnableOpenApi
@SpringBootApplication
@MapperScan("com.kyk.imoocmall.mapper")
@ServletComponentScan("com.kyk.imoocmall.filter")  //扫描指定指定的filter包
public class ImoocMallApplication {

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

}

注意:这里直接用@WebFilter就可以进行配置,同样,可以设置url匹配模式,过滤器名称等。这里需要注意一点的是@WebFilter这个注解是Servlet3.0的规范,并不是Spring boot提供的。除了这个注解以外,我们需在启动类中加注解:@ServletComponetScan,指定扫描的包。

本文作者:Ac_c0mpany丶

本文链接:https://www.cnblogs.com/keyongkang/p/16939006.html

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   Ac_c0mpany丶  阅读(600)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起
  1. 1 You Are My Sunshine REOL
You Are My Sunshine - REOL
00:00 / 00:00
An audio error has occurred.

作曲 : Traditional

You are my sunshine

My only sunshine.

You make me happy

When skies are gray.

You'll never know, dear,

How much I love you.

Please don't take my sunshine away

The other night, dear,

When I lay sleeping

I dreamed I held you in my arms.

When I awoke, dear,

I was mistaken

So I hung my head and cried.

You are my sunshine,

My only sunshine.

You make me happy

When skies are gray.

You'll never know, dear,

How much I love you.

Please don't take my sunshine away.

You are my sunshine,

My only sunshine

You make me happy

When skies are gray.

You'll never know, dear

How much I love you

Please don't take my sunshine away

Please don't take my sunshine away.

Please don't take my sunshine away.