一 过滤器
每个servlet都有自己需要处理的资源,这么多的资源我们有时候我们希望统一的进行管理,比如对响应的图片进行加水印处理,对提交和响应的数据的编码进行统一,或者是对提交的数据进行过滤。
解决的办法就是使用过滤器,他的目的是对服务器和浏览器之间交互的资源进行管理和保护servlet安全(一定程度上)。他的角色就像是服务器与浏览器之间的桥梁。它是由服务器调用执行的。
1.1 使用过滤器
1. 实现Filter接口
2. 覆写接口方法
public class MyFilter implements Filter {
//启动即执行,进行资源初始化
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("MyFilterinit!!");
}
//请求发送执行,进行资源管理
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println("MyFilteredoFilterExit!!");
//放行,这里如果不放行,请求就不会被servlet处理
filterChain.doFilter(servletRequest, servletResponse);
System.out.println("MyFilterdoFilterReturn!!");
}
//服务器关闭执行,对资源进行关闭
@Override
public void destroy() {
System.out.println("MyFilterdestroy!!");
}
}
3. 在web.xml中配置过滤器
<filter>
<filter-name>myFilter</filter-name>
<filter-class>com.chester.web.servlet.MyFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>myFilter</filter-name>
<!--/*代表对所有项目根目录的请求都过滤-->
<url-pattern>/*</url-pattern>
</filter-mapping>
这里的 <url-pattern>
有很灵活的写法,根据项目需求来写即可,这里再给出几个例子
<!--拦截所有以.do结尾的请求,一般进行的是模块拦截-->
<url-pattern>*.do</url-pattern>
<!--拦截指定url请求,针对某个servlet的请求进行拦截,保护servlet-->
<url-pattern>/ts</url-pattern>
在执行一个过滤器之后,如果还有符合要求的过滤器,则再执行符合要求的过滤器,执行完doFilter方法中filterChain.doFilter()方法后,继续执行doFilter中接下来的代码。
1.2 案例
下面我们来看看几个具体的使用场景,我们只关注关键代码部分。代码设置了接收和发送的编码格式,以及实现对session的管理,如果session失效,则要求用户重新登陆。
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
//编码格式设置
servletRequest.setCharacterEncoding("utf-8");
servletResponse.setContentType("text/html;charset=utf-8");
//session管理,
HttpSession hs = ((HttpServletRequest)servletRequest).getSession();
if(hs.getAttribute("user") == null){
((HttpServletResponse)servletResponse).sendRedirect("/JavaWebTest/login.jsp");
}else{
//放行
filterChain.doFilter(servletRequest, servletResponse);
}
}
二 监听器
上面我们使用了过滤器对资源进行统一的管理,但是有的时候,我们需要知道数据流转的具体过程,比如作用域对象是什么时候创建和销毁的,作用域对象中的数据是什么时候存取,改变和删除的。以此来进行一些处理,比如如果统计网站的在线人数,我们就需要知道session是什么时候销毁和创建的。创建在线人数+1,销毁则-1。通过监听器就可以完成这样的功能。
2.1 使用监听器
监听器可以监听request、session、application的创建销毁和内容的改变,下面
2.1.1 监听request对象
创建ServletRequestListener的实现类
public class MyListener implements ServletRequestListener, ServletRequestAttributeListener{
//监听作用域创建于销毁 继承 ServletRequestListener
//作用域销毁时调用
public void requestDestroyed(ServletRequestEvent sre) {
sre.getServletRequest();
System.out.println("MyListenerDestroyed");
}
//作用域创建时调用
public void requestInitialized(ServletRequestEvent sre) {
System.out.println("MyListenerInitialized");
}
//监听作用域数据修改 继承 ServletRequestAttributeListener
//数据增加时调用
public void attributeAdded(ServletRequestAttributeEvent srae) {
System.out.println("request 中增加了-" + srae.getName() + ":" +srae.getValue());
}
//数据删除时调用
public void attributeRemoved(ServletRequestAttributeEvent srae) {
System.out.println("request 中删除了-" + srae.getName() + ":" +srae.getValue());
}
//数据修改时调用
public void attributeReplaced(ServletRequestAttributeEvent srae) {
System.out.println("request 中改变了-" + srae.getName() + ":" +srae.getValue());
}
}
在web.xml中配置监听器
<!--配置监听器-->
<listener>
<listener-class>com.chester.web.servlet.MyListener</listener-class>
</listener>
2.1.2 监听session对象
和request一样,继承HttpSessionListener,HttpSessionAttributeListener
2.1.3 监听application对象
一样,继承ServletContextListener, ServletContextAttributeListener
2.2 监听器使用案例
该案例在application对象中使用count这个键维护网站的登陆人数,你可以在适当的地方进行取用。
public class MyListener implements HttpSessionListener, ServletContextListener{
//当一个session建立的时候,说明有用户进行了登陆count++
public void sessionCreated(HttpSessionEvent se) {
ServletContext sc = se.getSession().getServletContext();
int count = (int)sc.getAttribute("count");
sc.setAttribute("count", ++count);
}
//当一个session销毁的时候,说明有用户进行了退出count--
public void sessionDestroyed(HttpSessionEvent se) {
ServletContext sc = se.getSession().getServletContext();
int count = (int)sc.getAttribute("count");
sc.setAttribute("count", --count);
}
//application对象建立时,初始化count为0
public void contextInitialized(ServletContextEvent sce) {
//获取application
ServletContext sc = sce.getServletContext();
sc.setAttribute("count", 0);
}
}