【JavaWeb-12】Listener监听3个方面、Filter过滤器、全局编码过滤器案例
2016-09-25 20:52
751 查看
1、Listener主要监听3个方面,第一类是监听域对象,一共有3个域对象。
——第一个是ServletContext对象,3个步骤,首先是写一个继承自ServletContextListener的类,然后实现它的创建和销毁方法,最后在web.xml中注册这个类即可。
在xml中注册的语句如下:
第一个ServletContext其实就是application对象,所以我们程序启动就能在控制台看到创建的消息,关闭服务器的话就能看到销毁的消息。
——第二个是HttpSession域对象。继承自HttpSessionListener接口实现方法进行注册即可。我们在访问index.jsp的时候其实默认开启了session,所以我们直接访问的话,会有创建session的消息出来,我们在jsp中写如下代码,则会在创建消息出现之后出现销毁消息。
——第三个是ServletRequest域对象,继承自ServletRequestListener接口实现方法注册即可。我们直接访问index.jsp一样可以得到实验结果,因为访问静态文件和访问servlet类似都要经过servlet类处理,详细一点就是经过它里面的service处理,service处理结束的时候就相当于这个request被销毁了。所以我们可以得到下列消息。
2、第二类监听的是域对象属性的变化。也是上面那3个域对象,只是这一次继承的接口不一样了,其他用法都是类似的,我们只拿继承自HttpRequestAttributeListener为例。我们在index.jsp中写如下代码,然后访问这个页面。
结果如下,另外两个域对象的属性监听方法操作是一样的。
3、第三类是监听session绑定JavaBean。这里与以上两种有所区别。它需要实体类来继承自接口并实现方法,而不是随便创建一个类。其次,它不需要在xml中注册。
然后在index.jsp中写如下代码,即可得到测试消息:
4、Filter是重点。Filter其实和Servlet有点类似。我们之前说过Servlet的使用流程是,创建一个Servlet,然后在xml里面配置名字、类和路径(使用MyEclipse的话在图形化界面就配置好了),这样访问什么路径就去找什么Servlet。Filter也是类似的,本质上它是一个继承Filter接口的类,然后我们也需要在xml里面去配置名字、类和路径,这样访问什么路径的话就先到这个Filter类里面来进行处理,如果Filter类放行的话处理完它就会继续奔向Servlet。
——我们看到创建的继承自Filter接口的类如下,主要是用了其中的doFilter方法。
——这是我们在xml中的配置。
——小知识。我们在xml中的配置最好按照顺序来写,比如filter的配置写在servlet的上面,这个顺序的查看是点击
——如果把doFilter写成如下,我们可以测试执行顺序。是到资源里面去了之后又返回到filter里面了。
结果是:
——FilterChain只需要满足一个条件:对同一个资源进行过滤就行。至于哪一个filter先执行,是看xml里面哪一个filter-mapping写在上面。然后最后一个过滤器调用资源。
5、Filter生命周期。当服务器启动的时候就开始实例化,然后紧接着调动init方法初始化(只调用1次,这一点时间和Servlet不同,后者是第一次访问servlet的时候进行实例化和初始化,而前者是服务器启动就开始了),当访问资源的时候路径匹配到Filter的时候就调用doFilter方法,服务器关闭的时候调用destroy方法。
6、FilterConfig。在xml中配置,然后利用filterConfig获取这个参数值。
然后在filter里面获取,设置给request,再传递到servlet中,这样在servlet中就不需要配置编码了,因为这个request已经配置过了。
7、Filter配置,主要讲的是url-pattern的配置。我们之前说servlet的url-pattern时说过匹配原则,完全匹配的优先,然后又路径的其次,最后是通配符的。这里同样适用。
——但是这里多了一些配置,比如我们可以直接把url-pattern换成servletname,那就变成了对制定的servlet进行拦截过滤,而不是通过间接的路径进行匹配了,这叫精准打击么?
——还有一些情况,比如,我在一个servlet里面转发到了另一个servlet,这个时候,第二个servlet可能虽然满足了url-pattern里面的规则,但是并不会被过滤,为什么呢?因为我们的
8、利用Filter实现自动登录的案例。如果用户勾选了自动登录保存7天的话,我们把用户名密码保存在cookie中。然后我们可以在Filter里面进行拦截,拦截的时候先判断如果不是直接访问登录页面或者登录的servlet的话就查看是否有cookie,如果有cookie取得用户名密码,比较数据库后,放行。这里面其实是用了cookie、session的知识。
9、md5(message digest 5)加密。
10、利用Filter全局编码的案例。我们可能对每一个servlet都要设置request的编码,这种编码可以在Filter里面进行,然后把这个修改过的request放行。但是这种方式只能对post有效,如果是get方式提交的表单里面有中文的话,就会出现乱码。所以我们可以利用装饰器模式来对request进行修改。
——步骤是先定义一个类,和被包装类继承一样的类或者接口。然后在装饰类中持有一个被装饰类的引用,也就是把被包装类当做参数传递给我们新类的构造函数。最后把需要修改的函数重写,不需要的直接调用返回。
——但是这里面有个问题就是,request实现接口的话有很多方法,我们只需要重写一个,其他的我们都需要一个个的调用直接返回很累。所以我们可以让我们的这个类继承自一个适配器,因为适配器不强制实现所有的方法,所以我们可以只选那么我们需要重写的就行(主要是getParameter之类的方法)。
——之前的做法是获取到一个get表单里面的值,如果是中文的话,用以下处理即可。
——我们重写了request的getParameterMap方法,把里面的每个值都转码了,然后getParameter和getParameterValues都是调用的getParameterMap方法。
备注:如果仅仅是针对post请求的话,还是比较简单的,就直接在doFilter里面写一两句set的代码即可。但是要处理get请求的话,需要重写getParameter方法。
源代码:JavaEE Filter全局编码过滤器
——第一个是ServletContext对象,3个步骤,首先是写一个继承自ServletContextListener的类,然后实现它的创建和销毁方法,最后在web.xml中注册这个类即可。
在xml中注册的语句如下:
<listener> <listener-class>com.hello.listener.ServletContextListener</listener-class> </listener>
第一个ServletContext其实就是application对象,所以我们程序启动就能在控制台看到创建的消息,关闭服务器的话就能看到销毁的消息。
——第二个是HttpSession域对象。继承自HttpSessionListener接口实现方法进行注册即可。我们在访问index.jsp的时候其实默认开启了session,所以我们直接访问的话,会有创建session的消息出来,我们在jsp中写如下代码,则会在创建消息出现之后出现销毁消息。
<% session.invalidate(); %>
——第三个是ServletRequest域对象,继承自ServletRequestListener接口实现方法注册即可。我们直接访问index.jsp一样可以得到实验结果,因为访问静态文件和访问servlet类似都要经过servlet类处理,详细一点就是经过它里面的service处理,service处理结束的时候就相当于这个request被销毁了。所以我们可以得到下列消息。
ServletRequest被销毁了! HttpSession被创建了! HttpSession被销毁了! ServletRequest被创建了!
2、第二类监听的是域对象属性的变化。也是上面那3个域对象,只是这一次继承的接口不一样了,其他用法都是类似的,我们只拿继承自HttpRequestAttributeListener为例。我们在index.jsp中写如下代码,然后访问这个页面。
request.setAttribute("email", "andy@163.com"); request.setAttribute("email", "eric@163.com"); request.removeAttribute("email");
结果如下,另外两个域对象的属性监听方法操作是一样的。
ServletRequest新增了属性! ServletRequest修改了属性! ServletRequest移除了属性!
3、第三类是监听session绑定JavaBean。这里与以上两种有所区别。它需要实体类来继承自接口并实现方法,而不是随便创建一个类。其次,它不需要在xml中注册。
public class User implements HttpSessionBindingListener { private String name; private String pwd; …… public void valueBound(HttpSessionBindingEvent event) { System.out.println("User被绑定了!"); } public void valueUnbound(HttpSessionBindingEvent event) { System.out.println("User被解绑了!"); } }
然后在index.jsp中写如下代码,即可得到测试消息:
<% session.removeAttribute("u"); session.invalidate(); %>
4、Filter是重点。Filter其实和Servlet有点类似。我们之前说过Servlet的使用流程是,创建一个Servlet,然后在xml里面配置名字、类和路径(使用MyEclipse的话在图形化界面就配置好了),这样访问什么路径就去找什么Servlet。Filter也是类似的,本质上它是一个继承Filter接口的类,然后我们也需要在xml里面去配置名字、类和路径,这样访问什么路径的话就先到这个Filter类里面来进行处理,如果Filter类放行的话处理完它就会继续奔向Servlet。
——我们看到创建的继承自Filter接口的类如下,主要是用了其中的doFilter方法。
——这是我们在xml中的配置。
<filter> <filter-name>filterTest</filter-name> <filter-class>com.hello.filter.FilterTest</filter-class> </filter> <filter-mapping> <filter-name>filterTest</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
——小知识。我们在xml中的配置最好按照顺序来写,比如filter的配置写在servlet的上面,这个顺序的查看是点击
web-app然后按
F2,就出现下面这个样子,可以看到顺序。
——如果把doFilter写成如下,我们可以测试执行顺序。是到资源里面去了之后又返回到filter里面了。
public void doFilter(ServletRequest request, ServletResponse response,FilterChain chain) throws IOException, ServletException { System.out.println("doFilter开始了,然后放行!"); //放行,到servlet中去 chain.doFilter(request, response); System.out.println("访问servlet或资源后,又返回到doFilter了!"); }
结果是:
doFilter开始了,然后放行! 抵达Servlet了! 访问servlet或资源后,又返回到doFilter了!
——FilterChain只需要满足一个条件:对同一个资源进行过滤就行。至于哪一个filter先执行,是看xml里面哪一个filter-mapping写在上面。然后最后一个过滤器调用资源。
5、Filter生命周期。当服务器启动的时候就开始实例化,然后紧接着调动init方法初始化(只调用1次,这一点时间和Servlet不同,后者是第一次访问servlet的时候进行实例化和初始化,而前者是服务器启动就开始了),当访问资源的时候路径匹配到Filter的时候就调用doFilter方法,服务器关闭的时候调用destroy方法。
6、FilterConfig。在xml中配置,然后利用filterConfig获取这个参数值。
<filter> <filter-name>filterTest</filter-name> <filter-class>com.hello.filter.FilterTest</filter-class> <init-param> <param-name>encoding</param-name> <param-value>UTF-8</param-value> </init-param> </filter> <filter-mapping> <filter-name>filterTest</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
然后在filter里面获取,设置给request,再传递到servlet中,这样在servlet中就不需要配置编码了,因为这个request已经配置过了。
public class FilterTest implements Filter { private FilterConfig filterConfig; public void init(FilterConfig filterConfig) throws ServletException { this.filterConfig=filterConfig; } public void doFilter(ServletRequest request, ServletResponse response,FilterChain chain) throws IOException, ServletException { request.setCharacterEncoding(filterConfig.getInitParameter("encoding")); chain.doFilter(request, response); } }
7、Filter配置,主要讲的是url-pattern的配置。我们之前说servlet的url-pattern时说过匹配原则,完全匹配的优先,然后又路径的其次,最后是通配符的。这里同样适用。
——但是这里多了一些配置,比如我们可以直接把url-pattern换成servletname,那就变成了对制定的servlet进行拦截过滤,而不是通过间接的路径进行匹配了,这叫精准打击么?
<filter-mapping> <filter-name>filterTest</filter-name> <servlet-name>DoFilterServletTest</servlet-name> </filter-mapping>
——还有一些情况,比如,我在一个servlet里面转发到了另一个servlet,这个时候,第二个servlet可能虽然满足了url-pattern里面的规则,但是并不会被过滤,为什么呢?因为我们的
<filter-mapping>里有一个
dispatcher,它的默认值是REQUEST。意味着如果我们是以request的方式访问这个资源的话才会被filter拦截,而如果是从其他地方转发过来访问这个资源的话,尽管匹配上了,但是filter不拦截,需要我们把
dispatcher的值设置成FORWARD。但是,如果设置成FORWARD的话,REQUEST访问又不起作用了,所以我们可以设置多个。
<filter-mapping> <filter-name>filterTest</filter-name> <servlet-name>DoFilterServletTest</servlet-name> <dispatcher>REQUEST</dispatcher> <dispatcher>FORWARD</dispatcher> </filter-mapping>
8、利用Filter实现自动登录的案例。如果用户勾选了自动登录保存7天的话,我们把用户名密码保存在cookie中。然后我们可以在Filter里面进行拦截,拦截的时候先判断如果不是直接访问登录页面或者登录的servlet的话就查看是否有cookie,如果有cookie取得用户名密码,比较数据库后,放行。这里面其实是用了cookie、session的知识。
9、md5(message digest 5)加密。
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String raw_pwd="123456789"; try { MessageDigest md=MessageDigest.getInstance("md5"); BASE64Encoder b64c=new BASE64Encoder(); String new_pwd=b64c.encode(md.digest(raw_pwd.getBytes("UTF-8"))); System.out.println(new_pwd); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } }
10、利用Filter全局编码的案例。我们可能对每一个servlet都要设置request的编码,这种编码可以在Filter里面进行,然后把这个修改过的request放行。但是这种方式只能对post有效,如果是get方式提交的表单里面有中文的话,就会出现乱码。所以我们可以利用装饰器模式来对request进行修改。
——步骤是先定义一个类,和被包装类继承一样的类或者接口。然后在装饰类中持有一个被装饰类的引用,也就是把被包装类当做参数传递给我们新类的构造函数。最后把需要修改的函数重写,不需要的直接调用返回。
——但是这里面有个问题就是,request实现接口的话有很多方法,我们只需要重写一个,其他的我们都需要一个个的调用直接返回很累。所以我们可以让我们的这个类继承自一个适配器,因为适配器不强制实现所有的方法,所以我们可以只选那么我们需要重写的就行(主要是getParameter之类的方法)。
——之前的做法是获取到一个get表单里面的值,如果是中文的话,用以下处理即可。
String username=request.getParameter("username"); username=new String(username.getBytes("iso-8859-1"),"UTF-8"); System.out.println(username);
——我们重写了request的getParameterMap方法,把里面的每个值都转码了,然后getParameter和getParameterValues都是调用的getParameterMap方法。
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { HttpServletRequest req=(HttpServletRequest) request; MyRequest re=new MyRequest(req); chain.doFilter(re, response); }
class MyRequest extends HttpServletRequestWrapper{ HttpServletRequest request; public MyRequest(HttpServletRequest request){ super(request); this.request=request; } @Override public String getParameter(String name) { Map<String,String[]> map=getParameterMap(); return map.get(name)[0]; } @Override public Map getParameterMap() { Map<String,String[]> map=request.getParameterMap(); boolean flag=true; if(flag){ for(Map.Entry<String, String[]> m:map.entrySet()){ String[] values=m.getValue(); for(int i=0;i<values.length;i++){ try { values[i]=new String(values[i].getBytes("iso-8859-1"),"UTF-8"); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } } } flag=false; } return map; } @Override public String[] getParameterValues(String name) { Map<String,String[]> map=getParameterMap(); return map.get(name); } }
备注:如果仅仅是针对post请求的话,还是比较简单的,就直接在doFilter里面写一两句set的代码即可。但是要处理get请求的话,需要重写getParameter方法。
源代码:JavaEE Filter全局编码过滤器
相关文章推荐
- JavaWeb之过滤器实现统一编码案例
- JavaWeb-过滤器高级案例、URL过滤系统
- 12 自定义标签/JSTL标签库/web国际化/java web之设计模式和案例
- Tomcat与JavaWeb 5.3 HTTP会话的监听-HttpSessionListener等
- Java Web笔记 – Servlet中的Filter过滤器的介绍和使用 编写过滤器
- Java-Web过滤器应用案例
- java web项目js文件始终是乱码(剪切到记事本更改格式另存为也没用)关于编码过滤器的一种情况及解决方案
- 12.JavaWeb基础 过滤器
- JavaWeb之过滤器实现自动登录案例
- JavaWeb-过滤器Filter学习(二)设置全站编码与设置页面缓存
- JavaEE Web开发之Filter和Listener(过滤器和监听器)
- java web之编码过滤器
- java启动监听错误: org.springframework.web.context.ContextLoaderListener
- Java Web - 过滤器修改编码
- 【javaweb:Proxy&Filter】采用动态代理和过滤器解决request的全局乱码问题
- JavaWeb中使用Filter以及装饰者设计模式解决全局编码格式问题
- 【javaweb:Filter】通过过滤器和装饰设计模式解决request的全局乱码
- javaweb listener 对象的创建销毁-监听
- Java_Web学习笔记_过滤器应用案例(解决全站字符乱码)
- Java Web 中的监听(Listener)