学习主题:过滤器filter和监听器listener
学习目标:
1 掌握 filter的作用
2 掌握filter的编写
3 掌握监听器的作用
4 掌握监听器的编写
过滤器filter是学习的重点,可以拦截浏览器发送过来的任意请求,不分请求类型。
例子: 1、过了某个时间段后禁止登录。
2、登录或者访问权限的校验
过滤器filter
目前我们访问Servlet,是可以直接进行访问的,没有进行任何防护。
可能会造成服务器资源的浪费,以及安全性不高。我们希望真的在请求被
servlet处理之前,进行一次请求的校验,符合要求再调用对应的Servlet
进行请求处理,可以使用过滤器去处理。
过滤器的使用:
1、创建一个普通java类并实现过滤器接口Filter
2、在web.xml中配置过滤器
<filter>
<filter-name>配置的过滤器名称</filter-name>
<filter-class>要配置的过滤器的全限定路径:包名.类名</filter-class>
</filter>
<filter-mapping>
<filter-name>配置的过滤器名称</filter-name>
<url-pattern>过滤器拦截请求地址的范围</url-pattern>
</filter-mapping>
示例:
<filter>
<filter-name>myFilter</filter-name>
<filter-class>com.bjsxt.filter.MyFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>myFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
也可以使用注解@webfilter( )
技能点一:过滤器之doFilter方法
作用: 服务器在接收到浏览器发过来的请求后,先解析请求信息,创建对象request和response
然后根据请求URL地址判断如果符合过滤器的过滤范围,则会调用过滤器中的doFilter来
进行请求拦截,并将request和response对象作为实参传递给doFilter方法。我们可以在doFilter方法中声明过滤器拦截代码。
参数:
ServletRequest:接收此次拦截的请求的request实参
ServletResponse:接收此次拦截的请求的response实参
FilterChain:可以进行请求放行
chain.doFilter(request, response);
技能点二:过滤器之init和destory方法
init方法:服务器启动时调用
destory方法:服务器关闭时调用
证明:过滤器的生命周期为从服务器开启到服务器关闭
技能点三:过滤器之拦截范围配置
拦截所有:/*
拦截部分Servlet的请求:*.do
拦截指定Servlet的请求:和要拦截的指定的Servlet的url-pattern配置完全一致即可,例如:/my
注意:过滤器之间会出现多重拦截,如果是按照拦截拦截范围的大小在web.xml中自大而小进行的配置则会先执行大范围的拦截器,再执行小范围的拦截器。
过滤器案例
Filter案例之统一编码格式:
在doFilter中使用
设置请求编码格式 request.setCharacterEncoding("utf-8");
设置响应编码格式 response.setContentType("text/html;charset=utf-8");
Filter案例之session管理:
在过滤器中获取session对象,然后查看session中的数据是否还在。如果数据没了,则因为session失效则重定向到登录页面。如果数据还在,session没有失效,则放行。
同时会产生一些问题:
问题1:
在过滤器中使用session校验后发现登录页面的访问成了死循环,因为登录页面的请求也就是login.jsp的请求也会被过滤器拦截,而此时session中没有相关数据的,造成又重定向到登录页面......
解决1:
对login.jsp和登录请求进行放行
问题2:
过滤器会拦截所有的请求,包括静态资源(css文件js文件image图片)请求也会拦截。造成页面中的样式和动态效果等出不来
解决2:
对静态资源放行(css/js/image)
Filter案例之权限管理
需求:
不同的用户在对同一功能使用时,有的用户可以直接使用,有的用户会被提示权限不足。
思路:
1、在数据库中创建一个URL权限表,该表存储了该系统需要被管理的URL。
2、在数据库中创建用户权限中间表,用来进行权限分配
3、在数据库中将权限给用户分配好
4、在用户登录成功后查询该用户具备的URL权限,存储到该用户的session中
5、在过滤器中对当前发起请求的用户的请求地址进行校验,校验该用户是否具备该请求地址的权限,如果具备则放行执行,如果不具备则提示权限不足。
数据库设计:
URL权限表:t_url
编号: urlid
url地址 :location
描述:remark
用户权限中间表:t_user_url
uid
urlid
SQL语句的设计:查询当前登录用户的url信息
子查询:
select * from t_url where urlid in (select urlid from t_user_url where uid=8)
联合查询:
select * from t_url tu,t_user_url tul where tu.urlid=tul.urlid and tul.uid=8
具体代码:
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
//设置请求编码格式
request.setCharacterEncoding("utf-8");
//设置响应编码格式
response.setContentType("text/html;charset=utf-8");
//强转request对象
HttpServletRequest req=((HttpServletRequest)request);
//强转response对象
HttpServletResponse resp=((HttpServletResponse)response);
//获取此次请求uri
String uri=req.getRequestURI();
//获取此次请求的method
String method=req.getParameter("method");
System.out.println("当前请求的uri为:"+uri);
//放行登录页面 放行登录请求 放行静态资源
if("/project2/login.jsp".equals(uri) || ("/project2/data".equals(uri)&& "userLogin".equals(method)) || uri.startsWith("/project2/css/") || uri.startsWith("/project2/js/")|| uri.startsWith("/project2/images/")){
//放行
chain.doFilter(request, response);
}else{
//session管理(session统一校验)
//获取Session对象
HttpSession session = req.getSession();
Object obj=session.getAttribute("user");
//判断
if(obj!=null){
//获取权限信息
List<Url> lu=(List<Url>) session.getAttribute("lu");
//权限校验
for(Url url:lu){
if(url.getLocation().equals(method) || url.getLocation().equals(uri)){
//放行
chain.doFilter(request, response);
return;
}
}
//响应
resp.getWriter().write("power");
return;
}else{
//重定向到登录页面
resp.sendRedirect("/project2/login.jsp");
}
}
}
监听器listener的学习
1. 监听器的使用之监听request对象
监听request的创建和销毁:ServletRequestListener
监听request作用域数据的变更:ServletRequestAttributeListener
2. 监听器之监听session和application对象
监听session的创建和销毁:HttpSessionListener
监听session对象的增加,删除和修改:HttpSessionAttributeListener
监听application对象的创建和销毁:ServletContextListener。
监听application对象的数据的变更:ServletContextAttributeListener
统计当前在线人数的思路:
统计当前系统的session的个数,一个session意味一个在线的用户。
在session被创建的时候使用计数器+1,session被销毁的时候计数器-1,
将计数器存储在ServletContext对象。
统计当前在线人数
public class MyListener implements HttpSessionListener,ServletContextListener{
//监听Application对象
@Override
public void contextInitialized(ServletContextEvent sce) {
int count=0;
//获取Application对象
ServletContext sc = sce.getServletContext();
sc.setAttribute("count",count);
}
@Override
public void contextDestroyed(ServletContextEvent sce) {
// TODO Auto-generated method stub
}
//监听Sesion对象
@Override
public void sessionCreated(HttpSessionEvent se) {
//获取Application对象中的计数器
ServletContext sc = se.getSession().getServletContext();
int count=(int) sc.getAttribute("count");
//计数器自增
++count;
//然后再将计数器存储到application中
sc.setAttribute("count", count);
}
@Override
public void sessionDestroyed(HttpSessionEvent se) {
//获取Application对象中的计数器
ServletContext sc = se.getSession().getServletContext();
int count=(int) sc.getAttribute("count");
//计数器自减
--count;
//然后再将计数器存储到application中
sc.setAttribute("count", count);
}
}