springboot 2.1 实践教程(十一)-注册过滤器

什么是过滤器?

Filter也称之为过滤器,它是Servlet技术中最实用的技术,Web开发人员通过Filter技术,对web服务器管理的所有web资源:例如Jsp, Servlet, 静态图片文件或静态 html 文件等进行拦截,从而实现一些特殊的功能。例如实现URL级别的权限访问控制、过滤敏感词汇、压缩响应信息等一些高级功能。

它主要用于对用户请求进行预处理,也可以对HttpServletResponse进行后处理。使用Filter的完整流程:Filter对用户请求进行预处理,接着将请求交给Servlet进行处理并生成响应,最后Filter再对服务器响应进行后处理。

Filter链

在一个web应用中,可以开发编写多个Filter,这些Filter组合起来称之为一个Filter链。

web服务器根据Filter在web.xml文件中的注册顺序,决定先调用哪个Filter,当第一个Filter的doFilter方法被调用时,web服务器会创建一个代表Filter链的FilterChain对象传递给该方法。在doFilter方法中,开发人员如果调用了FilterChain对象的doFilter方法,则web服务器会检查FilterChain对象中是否还有filter,如果有,则调用第2个filter,如果没有,则调用目标资源。

 

 

 

(以上图片来自网络)

在没有使用Spring Boot时如果我们要配置一个filter过滤器,需要在web.xml里配置<filter>,然而Spring Boot没有web.xml,那么我们如何配置filter过滤器呢?

 

Spring Boot注册过滤的方式有三种:

方式1:启动类中注册Filter

a)创建Controller

package org.learn.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;

@Controller
public class TestFilterController {

    @GetMapping("/testfilter")
    public String TestF(){

        System.out.println("执行了TestFilterController的TestF方法");
    return "testFilter";
    }
}

 

b)创建过滤器类TestFilter

package org.learn.filter;


import javax.servlet.*;
import java.io.IOException;

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

    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        System.out.println("执行Controller前的TestFilter处理");
        filterChain.doFilter(servletRequest,servletResponse);
        System.out.println("执行Controller后的TestFilter处理");
    }

    @Override
    public void destroy() {

    }
}

c)在入口类中注册Filter过滤器

package org.learn;

import org.learn.filter.TestFilter;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;

@SpringBootApplication
public class SpringBootLearnApplication {

    //入口类注册Filter
    @Bean //将方法中返回的对象注入到IOC容器中
    public FilterRegistrationBean filterRegiste(){
        FilterRegistrationBean reFilter = new FilterRegistrationBean();
        reFilter.setFilter(new TestFilter()); //创建并注册TestFilter
        reFilter.addUrlPatterns("/*"); //拦截的路径(对所有请求拦截)
        reFilter.setName("TestFilter"); //拦截器的名称
        reFilter.setOrder(1); //拦截器的执行顺序。数字越小越先执行
        return  reFilter;

    }

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

}

d)执行启动类并发起请求

请求 http://localhost:8080/testfilter,从控制台输出我们可以看到

 

表明我们的Filter注册成功,改请求先是被Filter拦截,进行处理后在Controller执行,执行完成后,再执行 filterChain.doFilter(servletRequest,servletResponse)后的内容。

方式2:创建FilterConfig类注入为IOC容器内

a)创建FilterConfig类,将TestFilter注册至IOC

package org.learn.config;

import org.learn.filter.TestFilter;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class FilterConfig {

    @Bean //将方法中返回的对象注入到IOC容器中
    public FilterRegistrationBean filterRegiste(){
        FilterRegistrationBean reFilter = new FilterRegistrationBean();
        reFilter.setFilter(new TestFilter()); //创建并注册TestFilter
        reFilter.addUrlPatterns("/*"); //拦截的路径(对所有请求拦截)
        reFilter.setName("TestFilter"); //拦截器的名称
        reFilter.setOrder(1); //拦截器的执行顺序。数字越小越先执行
        return  reFilter;

    }
}

b)将启动类SpringBootApplication中注册Filter过滤器相关代码删除

package org.learn;

import org.learn.filter.TestFilter;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;

@SpringBootApplication
public class SpringBootLearnApplication {

/*    //入口类注册Filter
    @Bean //将方法中返回的对象注入到IOC容器中
    public FilterRegistrationBean filterRegiste(){
        FilterRegistrationBean reFilter = new FilterRegistrationBean();
        reFilter.setFilter(new TestFilter()); //创建并注册TestFilter
        reFilter.addUrlPatterns("/*"); //拦截的路径(对所有请求拦截)
        reFilter.setName("TestFilter"); //拦截器的名称
        reFilter.setOrder(1); //拦截器的执行顺序。数字越小越先执行
        return  reFilter;

    }*/

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

}

 

c)执行启动类并发起请求请求 http://localhost:8080/testfilter,从控制台输出我们可以看到,跟方式1得到的结果一致。

方式3:@WebFilter

a)在TestFilter类上增加@WebFilter,说明该类是一个Filter

@WebFilter(filterName ="TestFilter",urlPatterns = "/*")

package org.learn.filter;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;
    @WebFilter(filterName ="TestFilter",urlPatterns = "/*")
    public class TestFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        System.out.println("执行Controller前的TestFilter处理");
        filterChain.doFilter(servletRequest,servletResponse);
        System.out.println("执行Controller后的TestFilter处理");
    }

    @Override
    public void destroy() {

    }
}

b)删除FilterConfig类,或将其代码全部注释(方式2需要该类)

 

c)在项目启动类中增加注解@ServletComponentScan,通过该注解系统会去扫描Filter文件

package org.learn;

import org.learn.filter.TestFilter;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.boot.web.servlet.ServletComponentScan;
import org.springframework.context.annotation.Bean;

@SpringBootApplication
@ServletComponentScan
public class SpringBootLearnApplication {

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

}

d)执行项目启动类,并输入http://localhost:8080/testfilter,输出结果和方式1、方式2效果一致,表明注册过滤器成功

 

以上就是三种注册过滤器的方式,推荐方式2、方式3更易于管理。

 

 

 

 

对于Spring Boot应用程序,你可以通过创建一个自定义过滤器来为响应头添加X-Frame-Options标头,并设置为ALLOW-FROM。以下是一个示例: 首先,创建一个名为`XFrameOptionsFilter`的类,实现`javax.servlet.Filter`接口。 ```java import javax.servlet.*; import javax.servlet.http.HttpServletResponse; import java.io.IOException; public class XFrameOptionsFilter implements Filter { @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { HttpServletResponse httpResponse = (HttpServletResponse) response; httpResponse.setHeader("X-Frame-Options", "ALLOW-FROM http://example.com"); // 替换为你允许的来源URL chain.doFilter(request, response); } // 可以在 init() 和 destroy() 方法中添加逻辑,如果需要的话 @Override public void init(FilterConfig filterConfig) throws ServletException { // 初始化逻辑 } @Override public void destroy() { // 清理逻辑 } } ``` 然后,在Spring Boot应用程序的主类中注册这个过滤器。假设你的主类是`Application`,可以按照以下方式进行注册: ```java import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.web.servlet.FilterRegistrationBean; import org.springframework.context.annotation.Bean; @SpringBootApplication public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } @Bean public FilterRegistrationBean<XFrameOptionsFilter> xFrameOptionsFilterRegistrationBean() { FilterRegistrationBean<XFrameOptionsFilter> registrationBean = new FilterRegistrationBean<>(); registrationBean.setFilter(new XFrameOptionsFilter()); registrationBean.addUrlPatterns("/*"); // 指定过滤器的URL模式 registrationBean.setOrder(1); // 设置过滤器的顺序 return registrationBean; } } ``` 这样,每个请求都会被该过滤器拦截,并在响应头中添加X-Frame-Options标头。 请注意,上述示例中的`ALLOW-FROM http://example.com`应该替换为你允许的来源URL。如果你想允许多个来源,可以使用逗号分隔它们。 希望这可以帮助到你!如果还有其他问题,请随时提问。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值