解决springboot中配置过滤器以及可能出现的问题

在springboot添加过滤器有两种方式:

1、通过创建FilterRegistrationBean的方式(建议使用此种方式,统一管理,且通过注解的方式若不是本地调试,如果在filter中需要增加cookie可能会存在写不进前端情况)

2、通过注解@WebFilter的方式

通过创建FilterRegistrationBean的方式创建多个filter以及设置执行顺序:

1、创建两个实现Filter接口的类TestFilter1 、TestFilter2

package com.aoxun.core.filter;
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;

public class TestFilter1 implements Filter {

 @Override
 public void init(FilterConfig filterConfig) throws ServletException {}

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

 @Override
 public void destroy() {}

}
package com.aoxun.core.filter;
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;

public class TestFilter2 implements Filter {

 @Override
 public void init(FilterConfig filterConfig) throws ServletException {}

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

 @Override
 public void destroy() {}

}

2、创建配置类

有多个filter就创建多个FilterRegistrationBean ,若需注明filter的执行顺序,可通过registration.setOrder(FilterRegistrationBean.LOWEST_PRECEDENCE - 1)配置,值越大,执行顺序越靠后

package com.aoxun.config.web;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import com.aoxun.core.filter.TestFilter1;
import com.aoxun.core.filter.TestFilter2;

/**
 * filter配置
 * @author zcj
 *
 */
@Configuration
public class FilterConfig2 {

 @Bean
 public FilterRegistrationBean companyUrlFilterRegister() {
 FilterRegistrationBean registration = new FilterRegistrationBean();
 //注入过滤器
 registration.setFilter(new TestFilter1());
 //拦截规则
 registration.addUrlPatterns("/*");
 //过滤器名称
 registration.setName("testFilter1");
 //过滤器顺序
 registration.setOrder(FilterRegistrationBean.LOWEST_PRECEDENCE);
 return registration;
 }

 @Bean
 public FilterRegistrationBean outLinkSecurityFilterRegister() {
 FilterRegistrationBean registration = new FilterRegistrationBean();
 //注入过滤器
 registration.setFilter(new TestFilter2());
 //拦截规则
 registration.addUrlPatterns("/*");
 //过滤器名称
 registration.setName("testFilter2");
 //过滤器顺序
 registration.setOrder(FilterRegistrationBean.LOWEST_PRECEDENCE - 1);
 return registration;
 }

}

通过注解@WebFilter的方式

1、在启动类上增加@ServletComponentScan注解,自动扫描带有过滤器注解的包

2、在类上使用@WebFilter  

package com.aoxun.core.filter;
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter;

import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.core.annotation.Order;

@WebFilter(filterName="testFilter1",urlPatterns= {"/*"})
public class TestFilter1 implements Filter {

 @Override
 public void init(FilterConfig filterConfig) throws ServletException {
 // TODO Auto-generated method stub

 }

 @Override
 public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
  throws IOException, ServletException {

 chain.doFilter(request, response);

 }

 @Override
 public void destroy() {
 // TODO Auto-generated method stub

 }

}

注:经测试,@Order并不能实现过滤器排序功能,在springboot中注解的方式增加过滤器可通过修改过滤器文件名称的方式排序,如上的过滤器TestFilter1在TestFilter2前。

补充知识:SpringBoot2.1.x,集成Filter过滤器的三种方式,包含OncePerRequestFilter方式

一)Filter过滤器简介

主要作用:Filter使用户可以改变一个request和修改一个response,它能够在一个request到达servlet之前预处理request,也可以在response离开servlet时处理response。例如收集数据和包装数据,并进行处理。

1、Filter是依赖Servlet容器的,如Tomcat。

2、Filter对所有的请求起作用,并是在sevlet之前处理。可以理解成过滤器中包含拦截器,当一个请求过来,先进行过滤器处理,再看程序是否受理该请求。过滤器执行完后,程序中的拦截器再进行处理。

3、Filter只能处理HttpServletRequest和HttpServletResponse,底层是基于回调函数。

二)SpringBoot集成Filter过滤器

第一步:先创建一个maven项目,引入springboot的jar

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
 <modelVersion>4.0.0</modelVersion>
 <groupId>com.oysept</groupId>
 <artifactId>springboot_filter</artifactId>
 <version>0.0.1-SNAPSHOT</version>
 <packaging>jar</packaging>

 <parent>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-parent</artifactId>
  <version>2.1.4.RELEASE</version>
  <relativePath/>
 </parent>

 <dependencies>
  <dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-web</artifactId>
  </dependency>
 </dependencies>

 <build>
  <plugins>
   <plugin>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-maven-plugin</artifactId>
    <configuration>
     <mainClass>com.oysept.FilterApplication</mainClass>
    </configuration>
   </plugin>
   <plugin>
    <groupId>org.apache.tomcat.maven</groupId>
    <artifactId>tomcat7-maven-plugin</artifactId>
   </plugin>
  </plugins>
 </build>
</project>

添加一个application.yml配置文件,指定一个端口

server:

port: 8080

创建一个Demo测试接口

package com.oysept.controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

/**
 * Demo Controller
 * @author ouyangjun
 */
@RestController
public class DemoController {

 // 带参GET请求: http://localhost:8080/demo/get/param?param=111222333444
 @RequestMapping(value = "/demo/get/param", method = RequestMethod.GET)
 public String getParam(@RequestParam(value = "param") String param) {
  System.out.println("=====>进入DemoController /demo/get/param");
  return "/demo/get/param," + param;
 }
}

第二步:使用@WebFilter注解方式,实现Filter过滤器

当使用@WebFilter、@WebServlet、@WebListener等注解时, 需要在springboot启动类中启用@ServletComponentScan注解指定扫描包。

package com.oysept.filter;
import java.io.IOException;
import java.util.Enumeration;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.core.env.Environment;
import org.springframework.web.filter.OncePerRequestFilter;

/**
 * 过滤器, 过滤所有地址
 * 方式一: 使用@WebFilter、@WebServlet、@WebListener等注解时, 需要在springboot启动类中启用@ServletComponentScan注解指定扫描包
 * 方式二: 结合@WebFilter和@Component注解一起使用, 但可能会同时注入两个bean, 可能会报错, 可在application.yml配置中启用同名Bean覆盖: spring.main.allow-bean-definition-overriding=true
 * @author ouyangjun
 */
@WebFilter(value = "/*", filterName = "oauthFilter")
public class OAuthFilter extends OncePerRequestFilter {

 @Override
 protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
   throws ServletException, IOException {
  System.out.println("====>进入OAuthFilter doFilterInternal过滤器====");
  System.out.println("请求地址: " + request.getRequestURL());

  System.out.println("GET请求参数: ");
  Enumeration<String> parameters = request.getParameterNames();
  String parameterName = "";
  while (parameters.hasMoreElements()) {
   parameterName = parameters.nextElement();
   System.out.println("参数名称: " + parameterName + ", 值: " + request.getParameter(parameterName));
 }

  // 工具类
  //FilterConfig filterConfig = super.getFilterConfig();
  //ServletContext servletContext = super.getServletContext();
  //Environment environment = super.getEnvironment();

  System.out.println("====>结束OAuthFilter doFilterInternal过滤器====");
  filterChain.doFilter(request, response);
 }
}

第三步:使用@Component注解方式,实现Filter过滤器

package com.oysept.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.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Component;

/**
 * 过滤器通过@Component注解注册
 * @author ouyangjun
 */
@Component
public class PathFilter implements Filter {

 @Override
 public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)
   throws IOException, ServletException {
  // 转换
  HttpServletRequest request = (HttpServletRequest) servletRequest;
  HttpServletResponse response = (HttpServletResponse) servletResponse;
  System.out.println("====>进入PathFilter doFilter过滤器====");

  System.out.println("====>结束PathFilter doFilter过滤器====");
  filterChain.doFilter(request, response);
 }
}

第四步:通过@Bean注解方式,实现Filter过滤器

@Configuration注解:相当于spring中的<beans>标签

@Bean注解:相当于spring中<bean>标签

package com.oysept.config;
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.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

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

/**
 * @Configuration注解: 相当于spring中的<beans>标签
 * @Bean注解: 相当于spring中<bean>标签
 * @author ouyangjun
 */
@Configuration
public class MyFilterConfig {

 @Bean
 public FilterRegistrationBean<MyFilter> testFilterRegistration() {
  FilterRegistrationBean<MyFilter> registration = new FilterRegistrationBean<>();
  registration.setFilter(new MyFilter());
  registration.addUrlPatterns("/*"); // 配置过滤路径
  registration.addInitParameter("paramName", "paramValue"); // 添加初始值
  registration.setName("myFilter"); // 设置filter名称
  registration.setOrder(1); // 请求中过滤器执行的先后顺序,值越小越先执行
  return registration;
 }

 // 实现一个过滤器
 public class MyFilter implements Filter {
  @Override
  public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)
    throws IOException, ServletException {
   // 转换
   HttpServletRequest request = (HttpServletRequest) servletRequest;
   HttpServletResponse response = (HttpServletResponse) servletResponse;
   System.out.println("====>进入MyFilter doFilter过滤器====");

   System.out.println("====>结束MyFilter doFilter过滤器====");
   filterChain.doFilter(request, response);
  }
 }
}

第五步:创建一个SpringBoot启动类,并通过@ServletComponentScan注解指定扫描的Filter实现类

package com.oysept;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.servlet.ServletComponentScan;

/**
 * @ServletComponentScan注解不指定扫描包时, 默认扫描当前包和子包
 * @author ouyangjun
 */
@SpringBootApplication
@ServletComponentScan(basePackages = "com.oysept.filter")
public class FilterApplication {

 public static void main(String[] args) {
  new SpringApplicationBuilder(FilterApplication.class).run(args);
 }
}

启动main方法,在浏览器输入地址:http://localhost:8080/demo/get/param?param=111222333444

在控制台查看打印日志:

项目结构图:

以上这篇解决springboot中配置过滤器以及可能出现的问题就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持我们。

(0)

相关推荐

  • SpringBoot应用整合ELK实现日志收集的示例代码

    ELK即Elasticsearch.Logstash.Kibana,组合起来可以搭建线上日志系统,本文主要讲解使用ELK来收集SpringBoot应用产生的日志. ELK中各个服务的作用 Elasticsearch:用于存储收集到的日志信息: Logstash:用于收集日志,SpringBoot应用整合了Logstash以后会把日志发送给Logstash,Logstash再把日志转发给Elasticsearch: Kibana:通过Web端的可视化界面来查看日志. 使用Docker Compos

  • springboot基于过滤器实现接口请求耗时统计操作

    Spring Boot中实现一个过滤器相当简单,实现javax.servlet.Filter接口即可. 下面以实现一个记录接口访问日志及请求耗时的过滤器为例: 1.定义ApiAccessFilter类,并实现Filter接口 @Slf4j @WebFilter(filterName = "ApiAccessFilter", urlPatterns = "/*") public class ApiAccessFilter implements Filter { @Ov

  • SpringBoot设置接口超时时间的方法

    SpringBoot设置接口访问超时时间有两种方式 一.在配置文件application.properties中加了spring.mvc.async.request-timeout=20000,意思是设置超时时间为20000ms即20s, 二.还有一种就是在config配置类中加入: public class WebMvcConfig extends WebMvcConfigurerAdapter { @Override public void configureAsyncSupport(fin

  • 详解SpringBoot中异步请求和异步调用(看完这一篇就够了)

    一.SpringBoot中异步请求的使用 1.异步请求与同步请求 特点: 可以先释放容器分配给请求的线程与相关资源,减轻系统负担,释放了容器所分配线程的请求,其响应将被延后,可以在耗时处理完成(例如长时间的运算)时再对客户端进行响应.一句话:增加了服务器对客户端请求的吞吐量(实际生产上我们用的比较少,如果并发请求量很大的情况下,我们会通过nginx把请求负载到集群服务的各个节点上来分摊请求压力,当然还可以通过消息队列来做请求的缓冲). 2.异步请求的实现 方式一:Servlet方式实现异步请求

  • 解决springboot中配置过滤器以及可能出现的问题

    在springboot添加过滤器有两种方式: 1.通过创建FilterRegistrationBean的方式(建议使用此种方式,统一管理,且通过注解的方式若不是本地调试,如果在filter中需要增加cookie可能会存在写不进前端情况) 2.通过注解@WebFilter的方式 通过创建FilterRegistrationBean的方式创建多个filter以及设置执行顺序: 1.创建两个实现Filter接口的类TestFilter1 .TestFilter2 package com.aoxun.c

  • SpringBoot中shiro过滤器的重写与配置详解

    目录 问题 解决方案 实现代码 1.重写shiro 登录 过滤器 2.重写role权限 过滤器 3.配置过滤器 问题 遇到问题:在前后端分离跨域访问的项目中shiro进行权限拦截失效 (即使有正确权限的访问也会被拦截) 时造成302重定向错误等问题报错:Response for preflight is invalid (redirect) 1.302原因:使用ajax访问后端项目时无法识别重定向操作 2.shiro拦截失效原因:跨域访问时有一种带预检访问的跨域,即访问时先发出一条methods

  • SpringBoot中配置Web静态资源路径的方法

    介绍: 本文章主要针对web项目中的两个问题进行详细解析介绍:1- 页面跳转404,即controller转发无法跳转页面问题:2- 静态资源文件路径问题. 项目工具: Intelij Idea, JDK1.8, SpringBoot 2.1.3 正文: 准备工作:通过Idea创建一个SpringBoot-web项目,此过程不做赘述,创建完成后项目结构如下图: 1- 创建一个controller代码如下: package com.example.webpractice.controller; i

  • 解决SpringBoot中@Email报错问题

    JSR303校验相关 现象:在springboot中使用@Email注解进行数据校验时,报没有该注解的错误. 解决方法: 在pom.xml中加该配置 <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-validation</artifactId> </dependency> 测试成功 ==测试成功== ![i

  • 解决springboot yml配置 logging.level 报错问题

    如下所示: logging: config: classpath:spring-logback.xml pattern: console: "%d - %msg%n" level: info 直接写 level: info 会报错: org.springframework.boot.context.properties.bind.BindException: Failed to bind properties under 'logging.level' to java.util.Map

  • 解决SpringBoot中使用@Async注解失效的问题

    错误示例,同一个类中使用异步方法: package com.xqnode.learning.controller; import com.fasterxml.jackson.core.JsonProcessingException; import org.springframework.scheduling.annotation.Async; import org.springframework.web.bind.annotation.GetMapping; import org.springf

  • 解决springboot文件配置端口不起作用(默认8080)

    springboot文件配置端口不起作用 1.可能是格式不对,yml要求 :后面有个空格,然后才写数据. 2.可能maven环境没导入好,新手没注意这个,看看项目右边有没有maven的图标,没有就说明没导好maven环境,再看看右下角有没有提示你import maven project ,点击导入即可! yml修改端口无效(SpringBoot中) 在yml文件中,修改端口: 启动后,若发现没反应,则修改为: 解决 以上为个人经验,希望能给大家一个参考,也希望大家多多支持我们.

  • 解决springboot 无法配置多个静态路径的问题

    目录 springboot 无法配置多个静态路径 需要在启动类里加一段代码如下: springboot静态路径配置遇到的坑 按照网上一些博客的说法 解决方法 springboot 无法配置多个静态路径 默认static路径是可以访问的, 对接天猫精灵需要额外的放开一个目录aligenie,供天猫精灵端访问,且路径名称无法更改. 这就导致了一个问题,默认识别的静态路径META-INF/resources / resources / static / public 都是spring boot 认为静

  • 解决springboot中@DynamicUpdate注解无效的问题

    springboot 中 @DynamicUpdate 注解无效解决方案 遇到的问题 项目中使用 jpa,以前没用过,所以踩坑在所难免. 在使用过程中,要更新一条记录的某个字段,更新成功以后,发现整条记录只剩下我更新的那个字段,其他的全部为空了. 瞬间明白,这种更新是全覆盖,针对每个字段 update,实体类没赋值的字段,也直接将空值 set 过去了. 寻求解决方案 正在庆幸这么容易就解决,突然发现并没有这么简单. 群众的力量是无穷大的,我立刻就明白这个注解为什么无效,原来是搞错了它的用途. 一

  • 解决SpringBoot中的Scheduled单线程执行问题

    目录 问题描述 原因分析: 解决方案: 补充: 问题描述 在一次SpringBoot中使用Scheduled定时任务时,发现某一个任务出现执行占用大量资源,会导致其他任务也执行失败.类似于以下模拟场景,test1定时任务模拟有五秒钟执行时间,这时会同步影响到test2任务的执行,导致test2任务也变成五秒执行一次. @Scheduled(fixedRate = 1000) public void test1() throws InterruptedException { log.info(Th

随机推荐