Java过滤器能够对目标资源的请求和响应进行截取,过滤器过滤的对象是客户端访问的web资源,也可以理解为一种预处理手段,对资源进行拦截后,将其中我们认为的杂质(用户自己定义的)过滤,符合条件的放行,不符合的则拦截下来。当然,过滤器既可以拦截request,也可以拦截返回的response,一张图解释:
一、什么是Java过滤器
过滤器的本质就是一个实现了 Filter 接口的 Java 类
public class FilterDemo implements Filter {
public void destroy() {
System.out.println("--过滤器消失");
}
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain)
throws ServletException, IOException {
//放行代码
chain.doFilter(req, resp);
}
public void init(FilterConfig config) throws ServletException {
System.out.println("--过滤器初始化");
}
}
重写相关代码里面重点在doFilter中实现相关操作方法
二、过滤器的配置
(1)web.xml里面修改相关配置
<filter>
<filter-name>filterDemo</filter-name>
<filter-class>package com.web.filter.FilterDemo</filter-class>
</filter>
<filter-mapping>
<filter-name>filterDemo</filter-name>
<!-- 拦截路径 -->
<url-pattern>/*</url-pattern>
</filter-mapping>
filter说明:
<filter-name></filter-name>
:指定filter名字
<filter-class></filter-class>
:指定filter全类名(带包名)
filter-mapping说明:
<filter-name></filter-name>
:这里的标签是为了与上面filter中的名字对应,从而指向到对应的文件中
<url-pattern></url-pattern>
:设置filter所拦截的路径 , 这里决定了什么样的资源会被过滤器拦截处理
格式 | 解释 |
---|---|
/index.jsp | 只有访问index.jsp这个资源的时候才会执行过滤器 |
/index/* | 访问index下所有资源你的时候,执行过滤器 |
*.jsp | 所有jsp格式的资源被访问的时候,执行过滤器 |
/* | 任意资源被访问,均执行过滤器 |
过滤器内设置的是比较通用的一些设置,所以一般来说使用 /*
这种格式,不过也可以根据需求情况选择
拦截方式配置:dispatcher
拦截方式配置也就是资源被访问的形式,有这么几个属性
REQUEST:默认值,浏览器直接请求资源
FORWARD:转发访问资源 : RequestDispatcher.forward();
INCLUDE:包含访问资源 : RequestDispatcher.include();
ERROR:错误跳转资源 : 被声明式异常处理机制调用的时候
补充:声明式异常处理即:在web.xml中通过配置来确定不同的异常类型将如何被处理,最后跳转到哪个页面,也就是我们常常看到的一些404错误页面
<error-page>
<!--异常的类-->
<exception-type>xxx</exception-type>
<!--异常发生时跳转的页面-->
<location>xxx</location>
</error-page>
(2)使用注解配置
与servlet相似的配置 ,我们可以指定它的名字和拦截路径
@WebFilter("filterName="FilterDemo1",urlPatters="/*")
但是直接在类上声明注解,显然那我们是不需要指定其名字的,而通过查看源码又可以知道,urlPatters又可以被value指定,而value又可以省略,所以我们可以简写为
@WebFilter("/*")
若想在filter注解中配置dispatcher,我们需要设置dispatcherTypes属性
@WebFilter(value = "/*",dispatcherTypes ={DispatcherType.FORWARD,DispatcherType.FORWARD} )
前面都是基本概念,下面将以做过的项目中真实的用户登录案例的拦截器作为例子为大家讲解一下
首先第一个例子是用户登录的拦截器,先看web.xml中的配置:
<!-- 集成门户的过滤器,获取权限 -->
<filter>
<filter-name>gainFilter</filter-name>
<filter-class>com.demo.authen.filter.gainFilter</filter-class>
<!--初始化参数 相当于key和value可以在过filter中取初始化值-->
<init-param>
<description>描述:是否集成menhu</description>
<param-name>isIntegrated</param-name>
<param-value>true</param-value>
</init-param>
<init-param>
<param-name>extension</param-name>
<param-value>/**/**.js,/**/**.jpg,/**/**.css,/**/**.jpeg,/**/**.json,/**/**.gif,/**/**.png,/**/**.ico,/**/**.mp4</param-value>
</init-param>
</filter>
<!--匹配拦截的内容 /*则对所有的内容都进行拦截-->
<filter-mapping>
<filter-name>gainFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
我们指定com.demo.authen.filter.gainFilter这个类为我们的拦截器方法,设定一个初始化参数isIntegrated的值为true,当前端请求web服务的时候,会先经过我们的过滤器进行判断筛选,下面看看拦截器里面究竟是什么样的:
/**
* 获取权限过滤器。<br/>
* 用户第一次进入系统,那么会判断用户是否已经初始化了权限,<br/>
* 如果没有那么会调用门户的服务,获取菜单和功能的权限。
*
*
*/
public class GainFilter implements Filter {
/** 是否和门户集成 */
public static boolean isIntegrated;
/**
* 初始化过滤器
*/
@Override
public void init(FilterConfig config) throws ServletException {
//获取web.xml里面配置的初始化值
String cfg = config.getInitParameter("isIntegrated");
if ("true".equals(cfg)) {
isIntegrated = true;
}
}
/**
* 过滤主体内容
*/
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
HttpServletRequest httpRequest = (HttpServletRequest) request;
HttpSession session = httpRequest.getSession();
if (isIntegrated) {// 如果门户集成
String account = (String) session.getAttribute(ACCOUNT);
userService = (UserService) SpringContextUtil.getBean("userService");
String reqUri = httpRequest.getRequestURI();
} else {
// 不和门户集成,进行测试用
String account = "admin";
long cityCode = 330000;
User user = new User();
user.setAccount(account);
session.setAttribute("account", user);
session.setAttribute("cityCode", user.getCityCode());
}
//通过当前过滤器,进入下一个过滤器或者进入程序
chain.doFilter(request, response);
}
/**
*过滤器消失
**/
@Override
public void destroy() {
}
}
上面是截自真实项目的部分片段,我们的 GainFilter 会去实现Filter 这个接口,并且会重写三个方法,init、doFilter、destroy。inity一般都是一些初始化参数,比如上面的去获取isIntegrated在web.xml中配置的值。doFilter是我们过滤器的主体,我们可以在这里执行一系列的操作。
这里我们再举一个实例,就是我们设置拦截器允许跨域,这个例子会比较完整,还是先看web.xml的配置:
<!--跨域问题过滤器 -->
<filter>
<filter-name>CORSFILTER</filter-name>
<filter-class>com.demo.authen.filter.CorsFilterConfig</filter-class>
</filter>
<filter-mapping>
<filter-name>CORSFILTER</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
下面再看看拦截器的代码:
package com.demo.authen.filter;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletResponse;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import java.io.IOException;
@Configuration
@Order(value=0)
@WebFilter(filterName = "CorsFilterConfig", urlPatterns = "/*")
public class CorsFilterConfig implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("===============CorsFilterConfig=================");
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse,
FilterChain filterChain) throws IOException, ServletException {
HttpServletResponse res = (HttpServletResponse) servletResponse;
res.setHeader("Access-Control-Allow-Origin", "*");
res.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE, PUT");
res.setHeader("Access-Control-Max-Age", "1728000");
res.setHeader("Access-Control-Allow-Headers",
"Authentication, Authorization, content-type, Accept, x-requested-with, Cache-Control");
filterChain.doFilter(servletRequest, res);
}
@Override
public void destroy() {}
}
在后台配置这个将允许跨域请求,方便前后端分离项目