您的位置:首页 > 编程语言 > Java开发

JavaEE学习之过滤器 Filter

2017-04-28 16:29 399 查看

过滤器 Filter

概念 :

Filter也称之为过滤器,可以对web服务器管理的所有web资源:
例如Jsp, Servlet, 静态图片文件或静态 html 文件等进行拦截,
从而实现一些特殊的功能。例如实现URL级别的权限访问控制、过滤敏感词汇、压缩响应信息等一些高级功能。


作用 :

1:实现动态资源不缓存
2:静态资源缓存
3:中文乱码集中处理
4: 特殊字符过滤
5:自动登录实现


写法

第一步: 写一个类实现 Filter

public class MyFirstFilter implements Filter {

public void destroy() {
System.out.println("filter被销毁了");

}

public void doFilter(ServletRequest servletRequeset,
ServletResponse servletResponse, FilterChain filterChain)
throws IOException, ServletException {
System.out.println("开始过滤");
// 放行 如果不放行,就不能到达目标资源
filterChain.doFilter(servletRequeset, servletResponse);
System.out.println("放行了---");
}

public void init(FilterConfig arg0) throws ServletException {
System.out.println("filter初始化了");
}

}

第二步: 在web.xml中进行配置
<filter>
<filter-name>MyFirstFilter</filter-name>
<filter-class>com.example.filterdemo.MyFirstFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>MyFirstFilter</filter-name>
<url-pattern>/servlet/FirstServlet</url-pattern>
</filter-mapping>


生命周期

1.在应用被加载或容器启动时,过滤器就进行实例化,初始化
2.对比请求的资源及web.xml,以后每调拦截时,直接执行doFilter()
3.容器停止或应用卸载时,destory()执行销毁


配置详解

1.一个Filter 可以有多个 filter-mapping 可以拦截多个资源

2.可以使用通配符 /* 或者 *.扩展名进行配置

3.filter-mapping靠前的先拦截

4.filter默认只拦截拦截浏览器发送的请求,对转发不进行拦截

<dispatcher>FORWARD</dispatcher>
<dispatcher>REQUEST</dispatcher>


5.errorPage 可以根据错误类型或者错误码配置对应的错误界面

<error-page>
<error-code>404</error-code>
<location>/404error.jsp</location>
</error-page>
<error-page>
<error-code>500</error-code>
<location>/500error.jsp</location>
</error-page>


过滤器链

过滤器1------->过滤器2---------->目标资源------->过滤器2------->过滤器1


FilterConfig接口

对于过滤器,可以配置一些初始化的参数,这些参数可以直接放置到filter中,在初始化的时候,可以将参数读取出来

<filter>
<filter-name>MyFirstFilter</filter-name>
<filter-class>com.example.filterdemo.MyFirstFilter</filter-class>
<init-param>
<param-name>encode</param-name>
<param-value>utf-8</param-value>
</init-param>
</filter>
String getInitParameter(String name):


案例一:乱码问题解决

对于乱码问题,每个Servlet界面都需要进行处理,太耗时费力了,可以统一在过滤器中进行解决

对Post请求方式进行乱码统一处理

对于post方式,解决乱码非常简单,只需要在过滤器中设置两行代码即可

public void doFilter(ServletRequest req, ServletResponse resp,
FilterChain chain) throws IOException, ServletException {
req.setCharacterEncoding("UTF-8");
resp.setContentType("text/html;charset=UTF-8");
chain.doFilter(req, resp);
}


统一修改Get和Post乱码

对于get方式,由于浏览器编码采用的是ISO-8859-1,需要对每个参数进行编解码

在这里使用一种装饰者模式,修改getParameter方法

public void doFilter(ServletRequest req, ServletResponse resp,
FilterChain chain) throws IOException, ServletException {
HttpServletRequest httpServletRequest = (HttpServletRequest) req;
resp.setContentType("text/html;charset=UTF-8");
chain.doFilter(new MyServletRequest(httpServletRequest), resp);
}

class MyServletRequest extends HttpServletRequestWrapper {

private HttpServletRequest request;

public MyServletRequest(HttpServletRequest request) {
super(request);
this.request = request;

}

@Override
public String getParameter(String name) {
String method = request.getMethod();
//判断请求方式--如果是get方式请求,先对参数使用ISO-8859-1解码成字节,再使用UTF-8进行编码
if ("get".equalsIgnoreCase(method)) {
try {
String value = request.getParameter(name);
return new String(value.getBytes("ISO-8859-1"), "UTF-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
} else if ("post".equalsIgnoreCase(method)) {
try {
request.setCharacterEncoding("utf-8");
} catch (UnsupportedEncodingException e) {
}
}
return super.getParameter(name);
}

}


案例二:设置动态web资源全部不缓存

对于动态Web资源,要求实时更新,可以在过滤器中统一将其配置为不缓存,只需要设置响应中的三个响应头即可

public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException {

HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) resp;
//三个头
response.setHeader("Expires", "-1");
response.setHeader("Cache-Control", "no-cache");
response.setHeader("Pragma", "no-cache");

chain.doFilter(request, response);
}


案例三:设置静态Web资源全部缓存

对于静态Web资源,为了加载时间,可以在过滤器中统一将其配置为缓存,只需要设置缓存的响应头,指定过期时间就好

response.setDateHeader("Expires",System.currentTimeMillis()+60*60*1000);//单位:毫秒


案例四:自动登录

自动登录的场景分析:当用户在登录表单中勾选了自动登录按钮的时候,意味着用户下次再进入到程序的某个需要用户名的界面时,可以直接将用户名取出,而不需要再次进行登录



步骤分析:
1.使用集合模拟数据库
private static List<User> users = new ArrayList<User>();
static {
users.add(new User("zhangsan", "123"));
users.add(new User("lisi", "123"));
users.add(new User("wangwu", "123"));
}

public static User findUser(String username, String password) {
for (User u : users) {
if (username.equals(u.getUsername())
&& password.equals(u.getPassword())) {
return u;
}
}
return null;
}

public static User findUser(String username) {
for (User u : users) {
if (username.equals(u.getUsername())) {
return u;
}
}
return null;
}


LoginServlet

// 1--- 获取请求参数
String username = req.getParameter("username");
String password = req.getParameter("password");
// 2--- 进行用户验证
User user = UserDB.findUser(username, password);
if (user == null) {
// 2.1 提醒
resp.getWriter().write("please login first");
resp.setHeader("Refresh", "2;url=/Day17_AutoLogin/login.jsp");
} else {
// 2.2 登录成功 --存储到session中,因为登录成功要访问其他界面
req.getSession().setAttribute("user", user);
// 3-判断是否勾选了记住用户名
String rememberName = req.getParameter("rememberName");
String autoLogin = req.getParameter("autoLogin");
if ("on".equals(rememberName)) {
Cookie cookie = new Cookie("savename", user.getUsername());
cookie.setMaxAge(60 * 60 * 24);
cookie.setPath(req.getContextPath() + "/");
resp.addCookie(cookie);
}

// 3--- 判断是否勾选自动登录
// 4-- 如果勾选,往客户端设置cookie,存储用户名和密码
if ("on".equals(autoLogin)) {
Cookie cookie = new Cookie("autoLogin", user.getUsername()
+ "_" + user.getPassword());
cookie.setMaxAge(60 * 60 * 24);
cookie.setPath(req.getContextPath() + "/");
System.out.println("勾选了自动登录,路径为" + cookie.getPath());
resp.addCookie(cookie);
}
resp.sendRedirect(req.getContextPath() + "/index.jsp");


AutoLoginFilter

public void doFilter(ServletRequest req, ServletResponse resp,
FilterChain chain) throws IOException, ServletException {
// 1---强转
HttpServletRequest requeset = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) resp;
String resource = requeset.getRequestURI();// 得到资源名
boolean isLogin = resource.endsWith("login.jsp");// 判断是否想进行登录操作
System.out.println(resource + "----");
if (!isLogin) {
// 2--判断session域中有无user
User user = (User) requeset.getSession().getAttribute("user");
// 3--如果user不为空,说明已经登录了,直接放行,不做操作

System.out.println(user);
if (user == null) {
System.out.println("用户为空");
// 4 user 为空,判断之前是否有勾选自动登录
Cookie[] cookies = requeset.getCookies();
if (cookies == null || cookies.length == 0) {
// 说明根本没有cookie--
System.out.println("没有cookie");
} else {
System.out.println("遍历cookie");
for (Cookie cookie : cookies) {
String name = cookie.getName();
System.out.println(name + "------");
if ("autoLogin".equals(name)) {
// 找到了autologin的cookie zhangsan_123
String value = cookie.getValue();
System.out.println(value + "00000");
String[] split = value.split("_");
String username = split[0];
String password = split[1];
// 去查询一下这个用户名和密码的人是否存在
User user2 = UserDB.findUser(username, password);
if (user2 != null) {
System.out.println("cookie中用户不为空");
// 封装成user,放到session域中
requeset.getSession().setAttribute("user",
user2);
}
break;
}
}

}
}
}

chain.doFilter(requeset, response);

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  java ee filter