作业内容:
filter:退出系统后不能访问main.jsp页面,要跳转到login.jsp
listener:完成在线用户统计
第一个作业有有一点需要注意,因为有一个判断必须要做,否则会无限循环,浏览器不会输出。当然我这个判断写的并不是很恰当,如果有写的更好的请联系我,不胜感激。
最后我会把我的源码添加上去,然后有需要的童鞋可以去看一下。
一、filter作业
1. 我是基于model2进行的修改,但分层后来就没有按照MVC格式来分,所以有点乱,勿怪勿怪
2. 首先我们需要在web.xml中添加filter:
fitler中filter-class表示filter的路径,url-pattern表示匹配模式,/*表示所有的请求都要通过filter
3. 我们在filter-class指定的路径中添加filter,注意要继承Filter:
注意:继承自Filter接口的话,需要重写三个方法,init(),doFilter()以及destory()方法,本次作业旨在了解filter的工作原理,所以初始化和销毁无需自己写
以下是doFilter()代码段的注释:
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
//获取传来的request和response
HttpServletRequest httpRequest = (HttpServletRequest)request;
HttpServletResponse httpResponse = (HttpServletResponse)response;
//获取到页面session
HttpSession session = httpRequest.getSession();
//获取到所有请求的执行url
String path = httpRequest.getRequestURI();
//获取到session中的用户名(如果有)
String username = (String)session.getAttribute("username");
//注意,这就是我说的很重要的判断:
//当我们传来的请求为Login.jsp,即表示是登录页面,或者登录请求为LoginTestServlet
//这边在解释前,需要说一下filter的工作过程,当我们启动tomcat后,输入登录页面的url,此时就要经过一次filter,之后,点击登录按钮后,filter仍然要先于servlet再经过一次filter
//所以这边需要加两个判断,如果不加LoginTestServlet这个判断的话,那么我们点击登录按钮后的执行内容应该是LoginTestServlet,然而这边无法让通过,那么就会一直停留在Login.jsp
if((path.indexOf("/Login.jsp") > -1) || (path.indexOf("/LoginTestServlet") > -1)) {
//如果是登录请求,我们当然要放行,让其进行登录
chain.doFilter(httpRequest, httpResponse);
}else{
//如果不是登录请求的话,那我们就要判断刚才获取的session中有没有username这个值,也就是之前有没有登录
//如果username不为空,那么也通过,比如我们在登录之后,在新标签页面中输入main页面的url
//此时浏览器的session还没有过期,也就是说session中有username,那么当然要能跳到main页面
if(username != null){
chain.doFilter(httpRequest, httpResponse);
}else{
//这边就很有意思,表示既不是登录请求,在session中又没有username,那么就要实现作业的要求:退出系统后不能访问main.jsp页面,要跳转到login.jsp
httpResponse.sendRedirect(httpRequest.getContextPath() + "/Login.jsp");
}
}
4. 需要在servlet中添加以下内容:
这个表示当我登录后,要手动在session中添加内容,否则前面的判断中,session中永远获取不到username
此时,第一个作业就已经完成。
二、listener作业
1. 仍然是基于model2实现,同时要注意:listener -> filter -> servlet,也就是说listener执行顺序优于filter,filter优于servlet
2. 首先在web.xml中添加有关listener内容:
这边只要写了listener-class即可
2. 在listener-class路径下添加一个listener,注意要继承三个接口:ServletContextListener, HttpSessionAttributeListener, HttpSessionListener
我们需要实现里面的三个方法,详细的注释如下:
@Override
public void contextInitialized(ServletContextEvent arg0) {
//该方法表示要对context进行初始化,即对application内容进行初始化
//初始化一个application对象
//Application 对象用于存储和访问来自任意页面的变量,类似 Session 对象。不同之处在于所有的用户分享一个 Application 对象,而 session 对象和用户的关系是一一对应的。
//Application 对象掌握的信息会被应用程序中的很多页面使用(比如数据库连接信息)。这就意味我们可以从任意页面访问这些信息。
//也意味着你可以在在一个页面上改变这些信息,随后这些改变会自动地反映到所有的页面中
this.application = arg0.getServletContext();
//application设置一个名字叫online,内容为LinkedList的属性
this.application.setAttribute("online", new LinkedList<String>());
}
@Override
public void attributeAdded(HttpSessionBindingEvent arg0) {
//该方法表示对application这个对象进行赋值
//从初始化的application对象中获取到刚才设置的名字叫online的内容
List<String> online = (List<String>) this.application.getAttribute("online");
//这边表示当我们从前台获取到username这个属性时,online就要在其列表中塞入Login.jsp那边在username控件中输入的内容
if("username".equals(arg0.getName())){
online.add((String)arg0.getValue());
}
//当我们在完成设值之后,我们要再把application重新设置一下
this.application.setAttribute("online", online);
}
@Override
public void sessionDestroyed(HttpSessionEvent arg0) {
//该方法表示将session手动销毁,用于将当前登录用户退出时把当前在线人数减一。
//从application中获取到online内容
List<String> online = (List<String>) this.application.getAttribute("online");
//将当前登录的用户名获取到
String username = (String)arg0.getSession().getAttribute("username");
//当点击退出按钮后,要把当前登录的用户名从online这个列表中移除,表示该用户已经不在线
online.remove(username);
//当我们在完成设值之后,我们要再把application重新设置一下
this.application.setAttribute("online", online);
}
在main.jsp页面中写以下内容进行统计:
点击退出按钮后,我偷懒跳转到Logout.jsp页面,该页面就是以下内容,其实就是销毁当前用户的session,然后进行跳转:
此时,该作业就全部完成!
ps:貌似这个博客无法添加附件,那我就放在百度网盘上面,有需要的下载就好:http://pan.baidu.com/s/1kVSSac3,密码:odbg