过滤器定义:
Filter也称之为过滤器,它是Servlet技术中最实用的技术,Web开发人员通过Filter技术,对web服务器管理的所有web资源:例如Jsp, Servlet, 静态图片文件或静态 html 文件等进行拦截,从而实现一些特殊的功能。例如实现URL级别的权限访问控制、过滤敏感词汇、压缩响应信息等一些高级功能。
它主要用于对用户请求进行预处理,也可以对HttpServletResponse进行后处理。使用Filter的完整流程:Filter对用户请求进行预处理,接着将请求交给Servlet进行处理并生成响应,最后Filter再对服务器响应进行后处理。
Filter功能
在HttpServletRequest到达 Servlet 之前,拦截客户的HttpServletRequest 。根据需要检查HttpServletRequest,也可以修改HttpServletRequest 头和数据。
在HttpServletResponse到达客户端之前,拦截HttpServletResponse 。根据需要检查HttpServletResponse,也可以修改HttpServletResponse头和数据
过滤器的开发流程
1 配置web.xml
<filter>
<filter-name>characterFileter</filter-name>
<filter-class>com.rl.characterfilter.CharacterFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>characterFileter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter>
<filter-name>loginFilter</filter-name>
<filter-class>com.rl.loginfilter.LoginFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>loginFilter</filter-name>
<url-pattern>*.jsp</url-pattern>
</filter-mapping>
2 实现Filter接口
package com.rl.characterfilter;
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 javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.rl.utils.MyRequest;
public class CharacterFilter implements Filter {
/**
* Default constructor.
*/
public CharacterFilter() {
// TODO Auto-generated constructor stub
}
public void destroy() {
// TODO Auto-generated method stub
}
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
//转换请求
HttpServletRequest servletRequest=(HttpServletRequest) request;
HttpServletResponse servletResponse=(HttpServletResponse) response;
//处理响应乱码
servletResponse.setContentType("text/html;charset=utf-8");
//创建增强对象 要增强原来的request对象,必须先获取到原来的request对象
MyRequest myRequest=new MyRequest(servletRequest);
//放行的时候应该传入增强后的request对象 myRequest
chain.doFilter(myRequest, servletResponse);
}
public void init(FilterConfig fConfig) throws ServletException {
// TODO Auto-generated method stub
}
}
在上面的代码中创建MyRequest 类 去增强request 为其编码。(装饰者模式)
装饰模式定义:装饰模式指的是在不必改变原类文件和使用继承的情况下,动态地扩展一个对象的功能。
它是通过创建一个包装对象,也就是装饰来包裹真实的对象。
MyRequest 设计:(要增强原来的request 故继承HttpServletRequestWrapper 重写getParameterMap()方法 为了契合开发时使用getParameter()方法获取参数是为其编码 我对这个方法也做了重写)
package com.rl.utils;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Method;
import java.util.Map;
import java.util.Set;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
public class MyRequest extends HttpServletRequestWrapper{
/* 第一步:总结:继承HttpServletRequestWrapper,为了偷懒,
* 不用自己去实现所有HttpServletRequest的方法
* 第二步:使用构造函数将原来的request对象保存到当前自定义对象中
* 第三步:针对要修改的方法,进行增强
* 第四步:定义一个flag标记,防止编码重复执行
* */
// 定义了一个成员变量,用来保存构造函数传入的requset对象
private HttpServletRequest request = null;
// 定义一个标记,用来标注:当前requset中,请求参数,是否已经编码过了
private boolean flag = false;
public MyRequest(HttpServletRequest request) {
super(request);
this.request=request;
// TODO Auto-generated constructor stub
}
// 总需求:对request对象的获取数据的方法,进行增强(统一编码)
@Override
public java.util.Map<String, String[]> getParameterMap() {
//获得请求方法 post/ get
String method=request.getMethod();
if("post".equalsIgnoreCase(method)){
try {
request.setCharacterEncoding("utf-8");
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
java.util.Map<String, String[]> map=request.getParameterMap();
return map;
}/*如果是get方式*/
else if("get".equalsIgnoreCase(method)){
Map<String, String[]> map = this.request.getParameterMap();
/*如果已经编码了 直接返回map*/
if(flag){
return map;
}
else{
if(map==null){
return super.getParameterMap();//?
}else{
//获取参数名集合
Set<String> keys=map.keySet();
//遍历每一个参数 为其值编码
for(String key:keys){
//考虑到一个个名字有多个值(复选框,下拉列表框等) 故用一个数组来存放值
String [] values=map.get(key);
//对每一个值进行编码
for(int i=0;i<values.length;i++){
try {
values[i]=new String(values[i].getBytes("utf-8"), "utf-8");
System.out.println(values[i]+"values[i]");
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
//编码完成后 设置flag=true
flag=true;
}
}
else{
//位置请求方式,自定义对象处理不了,使用父类的方法处理
return super.getParameterMap();
}
return super.getParameterMap();
}
@Override
public String getParameter(String name) {
boolean flag=false;
String method=request.getMethod();
if(flag){
return super.getParameter(name);
}
else{
if("post".equalsIgnoreCase(method)){
try {
request.setCharacterEncoding("utf-8");
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}else if("get".equalsIgnoreCase(method)){
String param=request.getParameter(name);
try {
param=new String(param.getBytes("utf-8"), "utf-8");
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return param;
}else{
return super.getParameter(name);
}
}
// TODO Auto-generated method stub
return super.getParameter(name);
}
}
上面是对字符编码的过滤器的实现
接下来我对登录做了一个过滤器 如下:
package com.rl.loginfilter;
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.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
public class LoginFilter implements Filter {
public LoginFilter() {
// TODO Auto-generated constructor stub
}
public void destroy() {
// TODO Auto-generated method stub
}
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
// 获得在下面代码中要用的request,response,session对象
HttpServletRequest servletRequest = (HttpServletRequest) request;
HttpServletResponse servletResponse = (HttpServletResponse) response;
HttpSession session = servletRequest.getSession();
/*contextPath /Filter*/
String contextpath=request.getServletContext().getContextPath();
/* uri/Filter/login.jsp*/
String uri=servletRequest.getRequestURI();
/* url http://localhost:8080/Filter/login.jsp*/
StringBuffer url=servletRequest.getRequestURL();
//如果是登录页面放行
if(uri.indexOf("/login.jsp")>-1){
chain.doFilter(request, response);
}else{
/*取用户的session值*/
String user=(String) session.getAttribute("user");
if("".equals(user)||user==null){
servletResponse.sendRedirect("/Filter/login.jsp");
}
else{
chain.doFilter(request, response);
}
}
}
public void init(FilterConfig fConfig) throws ServletException {
// TODO Auto-generated method stub
}
}