过滤器
- 一:过滤器概述
- 1.什么是过滤器
- 二:过滤器详细
- 1.过滤器的四种拦截方式
- 三:过滤器的应用场景
- 1.案例一:分IP统计访问次数
- 2.案例二:粗粒度权限管理
- 3.案例三:全站编码问题
- 4.案例四:页面静态化(图书管理小项目)
一:过滤器概述
1.什么是过滤器
过滤器是JavaWeb三大组件之一,它与Servlet很相似!不过它是用来拦截请求的,而不是用来处理请求的。
当用户请求某个Servlet时,会先执行部署在这个请求上的Filter,如果Filter“放行”,那么会继续执行用户请求的Servlet;如果Filter不放行,那么就不会执行用户请求的Servlet
- Filter是单例的
实现方式:
- 写一个类实现Filter接口来实现
- 在web.xml中进行配置
<filter>
<filter-name>AFilter</filter-name>
<filter-class>net.xyz.filter.AFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>AFilter</filter-name>
<url-pattern>/AFilter</url-pattern>
</filter-mapping>
三个生命周期方法:
public class AFilter implements Filter {
public AFilter() {
// TODO Auto-generated constructor stub
}
public void destroy() {
System.out.println("过滤器死亡了");
}
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
// TODO Auto-generated method stub
// place your code here
// pass the request along the filter chain
System.out.println("拦截你");
}
public void init(FilterConfig fConfig) throws ServletException {
// TODO Auto-generated method stub
System.out.println("过滤器出生了");
}
}
FilterCongfig:
- 获取初始化参数 :getInitParameter()
- 获取过滤器名称:getFilterName()
- 获取appliction:getServletContext()
Filter Chain: - doFilter(ServletRequest,ServletResponse)
放行,相当于调用了目标servlet的service()方法!调用完之后会继续执行后面的代码
二:过滤器详细
多过滤器:
doFilter(ServletRequest,ServletResponse):
当有多个过滤器时,会执行下一个过滤器,如果没有,会执行目标servlet
执行顺序:
有多个Filter时,执行顺序按<filter-map>
的执行顺序执行
1.过滤器的四种拦截方式
在<filter-mapping>
中进行配置
<dispatcher>REQUEST</dispatcher> :拦请求。默认配置
<dispatcher>FORWARD</dispatcher> :拦转发
<dispatcher>INCLUDE</dispatcher>: 拦包含
<dispatcher>ERROR</dispatcher>:拦错误
三:过滤器的应用场景
1.案例一:分IP统计访问次数
统计工作需要在所有资源之前执行,那么就可以放到Filter中了。这个过程不做拦截操作,用Map来存储数据,用ip做key,用访问次数做value,因为是全局变量,数据存在ServletContext中
Listener用来创建资源:
package ipCount;
import java.util.LinkedHashMap;
import java.util.Map;
import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;
@WebListener
public class AListener implements ServletContextListener {
public AListener() {
// TODO Auto-generated constructor stub
}
public void contextDestroyed(ServletContextEvent sce) {
}
public void contextInitialized(ServletContextEvent sce) {
// TODO Auto-generated method stub
ServletContext application= sce.getServletContext();
Map<String,Integer>map=new LinkedHashMap<String,Integer>();
application.setAttribute("map", map);
}
}
Filter用来统计访问次数:
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
request.setCharacterEncoding("utf-8");
response.setContentType("text/html;charset=utf-8");
Map<String,Integer> map=(Map<String, Integer>) application.getAttribute("map");
String ip=request.getRemoteAddr();
if(map.containsKey(ip)) {
int num=map.get(ip);
System.out.println(ip);
System.out.println(1);
map.put(ip, num+1);
}else {
map.put(ip,1);
}
application.setAttribute("map", map);//更新map
chain.doFilter(request, response);//不要拦截请求
}
jsp用来显示数据:
<%@ page language="java" contentType="utf-8"
pageEncoding="utf-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Insert title here</title>
</head>
<body>
<h1 align="center">显示结果</h1>
<table align="center" width="60%" border="1">
<tr>
<th>IP</th>
<th>次数</th>
</tr>
<c:forEach items="${map }" var="entry" >
<tr>
<td>${entry. key } </td>
<td>${entry. value }</td>
</tr>
</c:forEach>
</table>
</body>
</html>
2.案例二:粗粒度权限管理
该应用分为三个角色,游客,会员,和管理员,每个人的角色默认是游客,而登录时使用用户名的话是会员,名字中包含xyz的则是管理员。现在使用filter控制user界面和admin界面的访问。
实现:
- 通过session存储用户名
- 在Filter中获取后判断是否允许通过还是拦截
Servlet:
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("utf-8");
response.setContentType("text/htmll;charset=utf-8");
String name=request.getParameter("username");
if(name.contains("xyz")) {//是管理员
request.getSession().setAttribute("admin", name);
}else {//就是普通会员
request.getSession().setAttribute("user", name);
}
request.getRequestDispatcher("/index.jsp").forward(request,response);
}
userFilter:
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
request.setCharacterEncoding("utf-8");
response.setContentType("text/html;charset=utf-8");
HttpServletRequest req=(HttpServletRequest) request;
String name;
name=(String) req.getSession().getAttribute("admin");
if(name!=null) {
chain.doFilter(request, response);//是管理员直接放行
return;
}
name=(String) req.getSession().getAttribute("user");
if(name!=null) {
chain.doFilter(request, response);//是普通会员直接放行
}else {
response.getWriter().write("你就是个普通游客,速走");
}
}
adminFilter:
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
request.setCharacterEncoding("utf-8");
response.setContentType("text/html;charset=utf-8");
HttpServletRequest req=(HttpServletRequest) request;
String name;
name=(String) req.getSession().getAttribute("admin");
if(name!=null) {
chain.doFilter(request, response);//是管理员直接放行
}else {
response.getWriter().write("反正你不是管理员");
req.getRequestDispatcher("/login.jsp").forward(request, response);
}
}
3.案例三:全站编码问题
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
request.setCharacterEncoding("utf-8");
response.setContentType("text/html;charset=utf-8");
chain.doFilter(request, response);
}
虽然教程上分别处理了GET和POST请求编码,但我试了一下不做处理GET编码也是正常的搞得我就不想写了,但还是写一下思路吧
- GET请求编码方式就是自定义一个request
继承HttpServletRequestWarrper
类实现装饰者模式,重写request
方法,在过滤器里传递自己定义的request
4.案例四:页面静态化(图书管理小项目)
- 第一步 :写一个小项目:图书管理
页面:
- 链接页面 :link.jsp
- > 查询所有
- >查看SE分类
- >查看EE分类
- > 查看框架分类
- 查询结果页面:show.jspServlet:
-BookServlet
findAll()–>查看所有图书
findByCategoary()–>按分类进行查询BookDao:
Linst<Book> findAll()
List findByCategoary(int categoary)domain:Book类
- 第二步: 什么是页面静态化!
首次访问去数据库获取数据,然后把数据保存到一个html页面中,二次访问,就不再去数据库获取了,而是直接显示html。
好处:直接加载html页面速度会快很多,但是只适合长时间数据保持不变的东西