之前我们学习spring的时候已经写过监听器与字符编码过滤器的自定义了,综合思想是不使用框架封装好的监听器,自己实现接口重写方法达到我们想要的效果,但是这样功能就太少了,接下来我们体验一下这个过程,对我来说使我对过滤器与监听器的生命周期和工作时间有了更深刻的理解。
一、自定义Filter字符编码过滤器
- 创建java类实现Filter接口(javax.servlet.Filter)
- 重写三个方法
- 在web.xml文件配置filter
- 测试功能检测生命周期(结果和监听器测试一起发出来)
创建Java类实现Filter接口以及重写方法
import javax.servlet.*;
import java.io.IOException;
/*过滤器的生命周期:我们看到在测试中,Tomcat工件部署之前就进行了过滤器的初始化,说明过滤器的初始化与Tomcat的部署过程中,
* 而过滤器的销毁在本地web服务器销毁之后。*/
public class filters implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("测试过滤器能否读取设置的过滤器编码参数"+filterConfig.getInitParameter("encoding"));
System.out.println(filterConfig.getFilterName()+"过滤器被初始化!");
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
servletResponse.setCharacterEncoding("UTF-8");
System.out.println("已经过滤服务名:"+servletRequest.getServerName());
filterChain.doFilter(servletRequest,servletResponse);
}
@Override
public void destroy() {
System.out.println("过滤器被销毁!");
}
}
注意这个filterChain参数的方法,通过反射看一看它的源码:
public interface FilterChain {
void doFilter(ServletRequest var1, ServletResponse var2) throws IOException, ServletException;
}
再看看servletRequest的源码:
public interface ServletRequest {
Object getAttribute(String var1);
Enumeration<String> getAttributeNames();
String getCharacterEncoding();
void setCharacterEncoding(String var1) throws UnsupportedEncodingException;);
String getParameter(String var1);
Enumeration<String> getParameterNames();
String[] getParameterValues(String var1);
Map<String, String[]> getParameterMap();
String getServerName();
int getServerPort();
String getRemoteAddr();
String getRemoteHost();
void setAttribute(String var1, Object var2);
void removeAttribute(String var1);
RequestDispatcher getRequestDispatcher(String var1);
}
可以发现通过英文我们能发现它的一些方法,我只保留了目前用过的方法,还有一些其他的方法。
在web.xml文件配置
<!--注册字符过滤器-->
<filter>
<filter-name>filter1</filter-name>
<filter-class>filters</filter-class>
<!--设置字符过滤器的放行字符类型参数-->
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>filter1</filter-name>
<!--拦截路径设置,这个路径下面的包文件会被字符过滤器过滤-->
<url-pattern>/*</url-pattern>
</filter-mapping>
注意我的java类里写到的 System.out.println("测试过滤器能否读取设置的过滤器编码参数"+filterConfig.getInitParameter("encoding"));语句,测试的就是我在web.xml文件配置的参数过滤器能否正确的读到。
二、自定义Listener监听器
- 创建java类实现servletContextListener与HttpSessionListener接口
- 重写方法
- 在web.xml文件配置
- 测试监听器的方法与实现session个数的统计
创建Java类实现接口并重写方法
public class listeners implements ServletContextListener, HttpSessionListener {
/*定义会话人数参数p*/
private int p = 0;
@Override
public void contextInitialized(ServletContextEvent sce) {
System.out.println("初始化监听器");
ServletContext servletContext = sce.getServletContext();
/*读取全局参数can并输出测试servletContext监听器的作用是否起到*/
String context = servletContext.getInitParameter("can");
System.out.println(context);
}
@Override
public void contextDestroyed(ServletContextEvent sce) {
System.out.println("销毁监听器!");
}
@Override
public void sessionCreated(HttpSessionEvent se) {
p++;
/*将这个p存到当前的会话上下文里,由页面接收并输出会话人数!*/
se.getSession().setAttribute("person",p);
/*控制台测试!*/
System.out.println("当前会话人数为"+p);
}
@Override
public void sessionDestroyed(HttpSessionEvent se) {
System.out.println("销毁会话!");
}
}
注意关于servletContextEvent参数的的源码:
public class ServletContextEvent extends EventObject {
private static final long serialVersionUID = -7501701636134222423L;
public ServletContextEvent(ServletContext source) {
super(source);
}
public ServletContext getServletContext() {
return (ServletContext)super.getSource();
}
}
它有一个方法返回的是当前监听器所处的servletContext,我们知道监听器所处的域就是servletContext,那么可以在它的方法里返回的话,就能够加载servletContext的一些资源与参数以及调用它的方法实现一些功能,这里的源码我也删掉了一部分:
public interface ServletContext {
String getContextPath();
ServletContext getContext(String var1);
Set<String> getResourcePaths(String var1);
URL getResource(String var1) throws MalformedURLException;
InputStream getResourceAsStream(String var1);
RequestDispatcher getRequestDispatcher(String var1);
RequestDispatcher getNamedDispatcher(String var1);
String getRealPath(String var1);
String getServerInfo();
String getInitParameter(String var1);
Enumeration<String> getInitParameterNames();
boolean setInitParameter(String var1, String var2);
Object getAttribute(String var1);
void setAttribute(String var1, Object var2);
void removeAttribute(String var1);
String getServletContextName();
SessionCookieConfig getSessionCookieConfig();
void addListener(String var1);
void addListener(Class<? extends EventListener> var1);
String getRequestCharacterEncoding();
}
在web.xml文件配置
<!-- 设置全局参数can=ssss给监听器识别测试输出 -->
<context-param>
<param-name>can</param-name>
<param-value>sssss</param-value>
</context-param>
<!--配置监听器-->
<listener>
<listener-class>listeners</listener-class>
</listener>
两个测试一起进行的控制台信息:
我们不难发现它们的生命周期的区域关系:服务器-监听器-过滤器的初始化-正常工作-过滤器的销毁-监听器-服务器。
其实我在实验的过程中想过用字符过滤器实现拦截不好的字符以及测试监听器读取全局参数成功实现页面跳转强行改变先显示主页的规则,结果因为不使用框架有些方法用不上,但是用了框架有些功能就是框架自己自动化的了,深度分析框架源码是我目前的基本任务,虚拟机的类加载子系统正在学习,进度慢下来的话我感觉自己到了夏天也浮躁了,大家看我更新的速度也知道我没劲头了,下周争取干起来!!!