先写一个Post接口用来请求,给过滤器测试用
@RestController
@RequestMapping(value = "api/tool")
public class ToolModuleController {
/**
* @param
* @return
* @创建日期:2020年3月5日
* @功能说明:生成UUID
*/
@ApiOperation(value = "生成UUID(数字+字母)", notes = "生成UUID(数字+字母)")
@PostMapping(value = "generateUuid")
public String generateUuid() {
try {
String id = UUIDGeneratorUtil.buildMallOrderSn();
return id;
} catch (Exception e) {
log.error(e.getMessage(), e);
return "失败";
}
}
}
方式一:通过注解扫描的方式完成Filter组件的注册
过滤器的使用很简单,建一个类,实现Filter
(引入的是javax.servlet
),那么这个类就是过滤器了,加上@WebFilter
配置过滤规则,@Order
用于多个过滤器时定义执行顺序,值越小越先执行,最后要在启动类加上@ServletComponentScan
,不加过滤器不生效。
1、过滤器init
方法是初始化的,程序(tomcat)启动的时候执行,doFilter
方法里面就可以写过滤的逻辑了,destroy
方法是程序(tomcat)关闭的时候执行的。
1.1、web服务器在调用doFilter
方法时,会传递一个filterChain
对象进来,filterChain
对象是filter接口中最重要的一个对 象,它也提供了一个doFilter
方法,开发人员可以根据需求决定是否调用此方法,调用该方法,则web
服务器就会调用web
资源的service
方 法,即web
资源就会被访问,否则web
资源不会被访问。有多个过滤器,会接着掉下一个过滤器
2、@WebFilter讲解:
2.1、urlPatterns
注解过滤写法:
①完全匹配:以“/”开头,以字母(非“”)结束
如:/test/list
②目录匹配:以“/”开头且以“/”结尾
如: /test/*
③扩展名匹配:以“*.”开头,以扩展名结束
如:*.do
,*.jsp
2.2、filterName
里面的值是当前类名
新建第一个过滤器:FilterDemo1
类
package wwfww.warehouse.aaaTest.filter;
import org.springframework.core.annotation.Order;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;
/**
* @Order(int) 注解,配合 @WebFilter 注解使用,用于多个过滤器时定义执行顺序,值越小越先执行
*/
@Order(1)
@WebFilter(filterName = "FilterDemo1",urlPatterns = {"/api/tool/*","*.jsp"})
public class FilterDemo1 implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("这边可以是初始化,可以干一些初始化的工作,比如初始化读取文件");
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
System.out.println("进入过滤器");
if(request.getParameter("num").equals("1")){
//假设这边是用来验证登录密码的
request.setCharacterEncoding("密码错误");
}else{
/**
* doFilter()的作用是将请求转发给过滤器链上下一个对象。这里的“下”指的是哪里 ?
*指的是下一个filter,如果没有filter那就是你请求的资源。
*/
chain.doFilter(request,response);
}
System.out.println("退出过滤器");
}
@Override
public void destroy() {
}
}
新建第二个过滤器:FilterDemo2
package wwfww.warehouse.aaaTest.filter;
import org.springframework.core.annotation.Order;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;
/**
* @Order(int) 注解,配合 @WebFilter 注解使用,用于多个过滤器时定义执行顺序,值越小越先执行
*/
@Order(2)
@WebFilter(filterName = "FilterDemo2",urlPatterns = {"/api/tool/*"})
public class FilterDemo2 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.println("轮到我执行了");
/**
* doFilter()的作用是将请求转发给过滤器链上下一个对象。这里的“下”指的是哪里 ?
*指的是下一个filter,如果没有filter那就是你请求的资源。不加这句你的请求就到不了你的接口
*/
chain.doFilter(request,response);
}
@Override
public void destroy() {
}
}
启动类:
@SpringBootApplication
@ServletComponentScan
@MapperScan(basePackages = {"wwfww.warehouse.mapper"})//不加这句mapper依赖注入不进来
public class WarehouseApplication {
public static void main(String[] args) {
SpringApplication.run(WarehouseApplication.class, args);
}
}
控制台输出:
2021-03-06 12:13:58.533 INFO 11976 --- [ main] o.s.web.context.ContextLoader : Root WebApplicationContext: initialization completed in 1601 ms
这边可以是初始化,可以干一些初始化的工作,比如初始化读取文件
Loading class `com.mysql.jdbc.Driver'. This is deprecated. The new driver class is `com.mysql.cj.jdbc.Driver'. The driver is automatically registered via the SPI and manual loading of the driver class is generally unnecessary.
2021-03-06 12:13:58.681 INFO 11976 --- [ main] com.zaxxer.hikari.HikariDataSource : warehouse - Starting...
2021-03-06 12:13:58.681 WARN 11976 --- [ main] com.zaxxer.hikari.util.DriverDataSource : Registered driver with driverClassName=com.mysql.jdbc.Driver was not found, trying direct instantiation.
2021-03-06 12:13:58.884 INFO 11976 --- [ main] com.zaxxer.hikari.HikariDataSource : warehouse - Start completed.
2021-03-06 12:13:58.937 INFO 11976 --- [ main] o.hibernate.jpa.internal.util.LogHelper : HHH000204: Processing PersistenceUnitInfo [name: default]
2021-03-06 12:13:59.001 INFO 11976 --- [ main] org.hibernate.Version : HHH000412: Hibernate ORM core version 5.4.12.Final
2021-03-06 12:13:59.140 INFO 11976 --- [ main] o.hibernate.annotations.common.Version : HCANN000001: Hibernate Commons Annotations {5.1.0.Final}
2021-03-06 12:13:59.257 INFO 11976 --- [ main] org.hibernate.dialect.Dialect : HHH000400: Using dialect: org.hibernate.dialect.MySQL8Dialect
2021-03-06 12:13:59.460 INFO 11976 --- [ main] o.h.e.t.j.p.i.JtaPlatformInitiator : HHH000490: Using JtaPlatform implementation: [org.hibernate.engine.transaction.jta.platform.internal.NoJtaPlatform]
2021-03-06 12:13:59.475 INFO 11976 --- [ main] j.LocalContainerEntityManagerFactoryBean : Initialized JPA EntityManagerFactory for persistence unit 'default'
2021-03-06 12:14:00.132 WARN 11976 --- [ main] JpaBaseConfiguration$JpaWebConfiguration : spring.jpa.open-in-view is enabled by default. Therefore, database queries may be performed during view rendering. Explicitly configure spring.jpa.open-in-view to disable this warning
2021-03-06 12:14:00.249 INFO 11976 --- [ main] pertySourcedRequestMappingHandlerMapping : Mapped URL path [/v2/api-docs] onto method [springfox.documentation.swagger2.web.Swagger2Controller#getDocumentation(String, HttpServletRequest)]
2021-03-06 12:14:00.356 INFO 11976 --- [ main] o.s.s.concurrent.ThreadPoolTaskExecutor : Initializing ExecutorService 'applicationTaskExecutor'
2021-03-06 12:14:00.409 INFO 11976 --- [ main] o.s.b.a.w.s.WelcomePageHandlerMapping : Adding welcome page template: index
2021-03-06 12:14:00.559 INFO 11976 --- [ main] d.s.w.p.DocumentationPluginsBootstrapper : Context refreshed
2021-03-06 12:14:00.580 INFO 11976 --- [ main] d.s.w.p.DocumentationPluginsBootstrapper : Found 1 custom documentation plugin(s)
2021-03-06 12:14:00.612 INFO 11976 --- [ main] s.d.s.w.s.ApiListingReferenceScanner : Scanning for api listing references
2021-03-06 12:14:00.729 INFO 11976 --- [ main] .d.s.w.r.o.CachingOperationNameGenerator : Generating unique operation named: sendEmailUsingPOST_1
2021-03-06 12:14:00.804 INFO 11976 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 8888 (http) with context path ''
2021-03-06 12:14:00.804 INFO 11976 --- [ main] wwfww.warehouse.WarehouseApplication : Started WarehouseApplication in 4.425 seconds (JVM running for 6.183)
2021-03-06 12:14:05.063 INFO 11976 --- [nio-8888-exec-1] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring DispatcherServlet 'dispatcherServlet'
2021-03-06 12:14:05.063 INFO 11976 --- [nio-8888-exec-1] o.s.web.servlet.DispatcherServlet : Initializing Servlet 'dispatcherServlet'
2021-03-06 12:14:05.072 INFO 11976 --- [nio-8888-exec-1] o.s.web.servlet.DispatcherServlet : Completed initialization in 9 ms
进入过滤器
轮到我执行了
退出过滤器
方式二、在启动类注册Filter
方式二是新建一个类实现Filter,然后在启动类那边将这个类注册,可以通过@Order()
来实现过滤器顺序
新建FilterDemo3,并且实现Filter
package wwfww.warehouse.aaaTest.filter;
import javax.servlet.*;
import java.io.IOException;
public class FilterDemo3 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.println("进入过滤器");
/**
* doFilter()的作用是将请求转发给过滤器链上下一个对象。这里的“下”指的是哪里 ?
*指的是下一个filter,如果没有filter那就是你请求的资源。
*/
chain.doFilter(request,response);
System.out.println("退出过滤器");
}
@Override
public void destroy() {
}
}
新建FilterDemo4类,并且实现Filter
package wwfww.warehouse.aaaTest.filter;
import javax.servlet.*;
import java.io.IOException;
public class FilterDemo4 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.println("方式二轮到我了");
chain.doFilter(request,response);
}
@Override
public void destroy() {
}
}
启动类注册Filter组件
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
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;
import tk.mybatis.spring.annotation.MapperScan;
import wwfww.warehouse.aaaTest.filter.FilterDemo3;
@SpringBootApplication
@MapperScan(basePackages = {"wwfww.warehouse.mapper"})//不加这句mapper依赖注入不进来
public class WarehouseApplication {
public static void main(String[] args) {
SpringApplication.run(WarehouseApplication.class, args);
}
/**
* 注册Filter
* @return
*/
@Bean
@Order(1)
public FilterRegistrationBean getFilterRegistrationBean(){
FilterRegistrationBean ben = new FilterRegistrationBean(new FilterDemo3());
ben.addUrlPatterns(new String[]{"/api/tool/*","*.jsp"});
return ben;
}
/**
* 注册Filter
* @return
*/
@Bean
@Order(2)
public FilterRegistrationBean getFilterRegistrationBean2(){
FilterRegistrationBean ben = new FilterRegistrationBean(new FilterDemo4());
ben.addUrlPatterns(new String[]{"/api/tool/*","*.jsp"});
return ben;
}
}
控制台输出:
进入过滤器
方式二轮到我了
退出过滤器
过滤器应用场景
1)过滤敏感词汇(防止sql注入)
2)设置字符编码
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
//转换
HttpServletRequest request1 = (HttpServletRequest)request;
HttpServletResponse response1 = (HttpServletResponse)response;
//设置编码
request1.setCharacterEncoding("UTF-8");
response1.setCharacterEncoding("UTF-8");
/*
* 使用doFilter方法调用链中的下一个过滤器或目标资源(servlet或JSP页面)。
* chain.doFilter处理过滤器的其余部分(如果有的话),最终处理请求的servlet或JSP页面。
*/
chain.doFilter(request,response);
}
3)URL级别的权限访问控制
4)压缩响应信息