Web应用中Filter的定义和使用
web开发中,客户端发来请求时,可以对请求和回应信息进行过滤,或者说对Request和Response进行拦截。比如对数据编码,加解密,验证用户合法性,过滤垃圾数据等。
定义过滤器类
必须实现 java.servlet.Filter接口
实现三个方法:
1、init(FilterConfigfilterConfig) 初始化过滤器,在Servlet容器启动时(一般为tomcat启动时)创建Filter实例的时候就会调用该方法,所以如果修改了其中的内容,需要重启tomcat才行。多用于读取web.xml文件中Servlet过滤器的初始化参数。
2、doFilter(ServletRequest request,ServletResponseresponse,FilterChain chain) 进行过滤处理,所有过滤处理都在这个方法中实现
处理完毕,需要调用chain.doFilter(request,response)方法,把请求继续向后传递,可以是对下一个过滤器doFilter方法的调用,或者相应的web组件。所以Filter采用了职责链设计模式。
然后继续在这等着其他请求,类似于Servlet的service()。
3、destroy() 过滤器销毁 Servlet容器在销毁过滤器实例之前该方法得到调用,以释放占用的资源。
设置字符集
response
页面中文显示:
<%@ page language="java"contentType="text/html; charset=GB18030"
使用PrintWriter输出中文
response.setContentType("text/xml;charset=utf-8");
request
否则,每个Servlet或者JSP都需要设置request字符集,例如
// 设置request字符集(文件头设置response字符集)
request.setCharacterEncoding("GB18030");
原理图
CharsetEncodingFilter.java
public class CharsetEncodingFilter implements Filter {
//设置默认的字符集,避免忘了配置Filter文件设置字符集导致出现乱码
private String encoding = "UTF-8";
@Override
public void doFilter(ServletRequest request, ServletResponseresponse,
FilterChain chain) throws IOException, ServletException {
// 设置字符集
// request.setCharacterEncoding("GBK");
request.setCharacterEncoding(encoding);
// 继续执行
chain.doFilter(request, response);
}
@Override
public void init(FilterConfig filterConfig) throwsServletException {
//从配置文件中CharsetEncodingFilter的init-param中取值,如果没有的话就使用默认的
encoding = filterConfig.getInitParameter("encoding");
}
@Override
public void destroy() {
}
}
web.xml
<filter> <filter-name>CharsetEncodingFilter</filter-name> <filter-class>com.java.drp.util.filter.CharsetEncodingFilter</filter-class> <init-param> <param-name>encoding</param-name> <param-value>GBK</param-value> </init-param> </filter> <filter-mapping> <filter-name>CharsetEncodingFilter</filter-name> <url-pattern>*.jsp</url-pattern> </filter-mapping> <filter-mapping> <filter-name>CharsetEncodingFilter</filter-name> <url-pattern>/servlet/*</url-pattern> </filter-mapping>
防止url跳转,判断用户是否已登录
AuthFilter.java
public class AuthFilter implements Filter {
@Override
public void destroy() {
}
@Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest)request;
HttpServletResponse resp = (HttpServletResponse)response;
// /DRP6.3/login.jsp
String reqURI = req.getRequestURI();
// 截取字符串,得到/login.jsp
String subReqURI = reqURI.substring(reqURI.indexOf("/", 1), reqURI.length());
// 如果是登陆页或者验证码的servlet,继续执行;否则进行验证
if (!"/login.jsp".equals(subReqURI) && !"/servlet/util/AuthImageServlet".equals(subReqURI)) {
// 如果用户没有登录,则跳到登陆页
HttpSession session = req.getSession(false);
if (session == null || session.getAttribute("user_info") == null) {
resp.sendRedirect(req.getContextPath() + "/login.jsp");
return;
}
}
// 继续执行
chain.doFilter(request, response);
}
@Override
public void init(FilterConfig arg0) throws ServletException {
}
}
web.xml
<filter> <filter-name>AuthFilter</filter-name> <filter-class>com.java.drp.util.filter.AuthFilter</filter-class> </filter> <filter-mapping> <filter-name>AuthFilter</filter-name> <url-pattern>*.jsp</url-pattern> </filter-mapping> <filter-mapping> <filter-name>AuthFilter</filter-name> <url-pattern>/servlet/*</url-pattern> </filter-mapping>
//改善登陆页:当session过期,子页面跳出框架,变成登陆页
if(window.self != window.top){
//用当前窗口位置引用覆盖顶层窗口位置引用,使得没有父亲引用
window.top.location = window.self.location;
}
Web Cache
对于在一定时间内不变的图片或者js文件等,无需每次请求都重新加载,而是放在缓存中。
还可以使用第三方产品 OSCache
WebCacheFilter.java
publicclass WebCacheFilter implements Filter {
@Override
publicvoid destroy() {
}
@Override
publicvoid doFilter(ServletRequest req, ServletResponse resp,
FilterChainchain) throws IOException, ServletException {
HttpServletRequestrequest = (HttpServletRequest)req;
HttpServletResponseresponse = (HttpServletResponse)resp;
//设置Cache-control
response.setHeader("Cache-control","max-age=5000");
//继续执行
chain.doFilter(request,response);
}
@Override
publicvoid init(FilterConfig arg0) throws ServletException {
}
}
web.xml
<filter>
<filter-name>WebCacheFilter</filter-name>
<filter-class>com.java.drp.util.filter.WebCacheFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>WebCacheFilter</filter-name>
<url-pattern>*.gif</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>WebCacheFilter</filter-name>
<url-pattern>*.jpg</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>WebCacheFilter</filter-name>
<url-pattern>*.png</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>WebCacheFilter</filter-name>
<url-pattern>*.js</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>WebCacheFilter</filter-name>
<url-pattern>*.css</url-pattern>
</filter-mapping>
分析特点
- 只对post请求起作用,而页面默认是get请求,所以想通过filter需要显示声明method。
- 责任链,多个filter,后进先出
- 生命周期类似servlet,只实例化一次,然后等待。
- AOP(Aspect-Oriented Programming)面向切面编程,是一种横切性的技术
- 提供一种声明式服务,具有可插拔能力。