您的位置:首页 > 其它

Filter(过滤器)、Listener(监听器)

2018-03-09 23:37 281 查看
一: 过滤器: 可以把”不和谐”的东西给过滤掉

01.过滤器概述

生活中的过滤器:带有过滤功能的净水器,滤纸,香烟的过滤嘴,测试,丈母娘.

程序中的过滤器:在JAVA中最小的程序单元是类,程序中的过滤器就是一个特殊的类

Servelt/Filter是Web的一个组件.


Web中过滤器的作用(简单理解为:过滤器处在客户端和服务端资源之间):

过滤器可以对所有的请求或者响应做拦截操作.

1:以常规的方式调用资源(Servelt/JSP);

2:利用修改过的请求信息调用资源;

3:调用资源之后,但在响应到客户端之前,对响应做出修改;

4:阻止当前资源调用,代之转带其他资源.


02.过滤器的应用

过滤器在开发中的应用:

1):可以对请求中的字符做编码.

2):登录验证过滤器.

3):敏感字(非法文字)过滤.

4):做MVC框架中的前端控制器(处理所有请求共同操作,再分发)


在开发中两个常用的思想:

1):DRY原则: Don't Repeat Yourself.

开发中拒绝代码重复,(重复会带来巨大的维护成本)

2):责任分离原则:各自做各自最擅长的事情.


03:开发和使用Filter

Servlet开发:

1:自定义一个类(XxxServlet),实现于javax.servlet.Servlet接口.

2:实现Servelt接口中的方法(init(初始化方法),service(处理请求))

3:告诉Tomcat来帮我们管理该Servlet程序(1:使用web.xml做配置,2:WebServlet("/资源名")).

<servlet>
<servlet-name>Servlet的别名</servlet-name>
<servlet-class>自定义Servelt的全限定名</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>Servlet的别名</servlet-name>
<url-pattern>/资源名</url-pattern>
</servlet-mapping>

注意:此时的url-pattern的文本内容是外界访问Servelt的资源名称.


Filter开发:

1:自定义一个类(XxxFilter),实现于javax.servlet.Filter接口.

2:实现Filter接口中的方法(init(初始化方法),doFilter(处理请求))

3:告诉Tomcat来帮我们管理该Filter程序(1:使用web.xml做配置,2:WebFilter("/资源名")).

<filter>
<filter-name>Filter的别名</filter-name>
<filter-class>自定义Filter的全限定名</filter-class>
</filter>
<filter-mapping>
<filter-name>Filter的别名</filter-name>
<url-pattern>/资源名</url-pattern>
</filter-mapping>

注意:此时的url-pattern的文本内容是Filter对哪一些资源做过滤操作.

如:   /hello.jsp           :说明当前Filter只会对/hello.jsp做拦截/过滤.
/employee            :说明当前Filter只会对/enployee资源做过滤.
/system/*            :说明当前Filter只会对以/system/作为前缀的资源路径做拦截.


filterChain(过滤器链):多个过滤器按照一定的顺序,排列起来.

拦截器栈:
--------------------------------------------------------
程序中存在多个过滤器的时候,过滤器的先后执行顺序由谁来决定.

在WEB.xml中:配置的<fiter-mapping>的先后顺序来决定.

![过滤器的的先后执行顺序示意图](https://img-blog.csdn.net/20180310104230663?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvd2VpeGluXzQwMTYxNzA4/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70)


04.Filter的细节

过滤器的映射细节:

1):filter中的url-pattern的文本内容是Filter对哪一些资源做过滤操作.

如:     /hello.jsp           :说明当前Filter只会对/hello.jsp做拦截/过滤.
/employee            :说明当前Filter只会对/enployee资源做过滤.
/system/*            :说明当前Filter只会对以/system/作为前缀的资源路径做拦截.
/*                   :说明对所有的资源做过滤.
/*.do                :对所有以 .do 结尾的资源做拦截

2):Filter的dispatcher(表示对哪些动作作过滤).

<filter-mapping>
<filter-name>FilterDemo1</filter-name>
<url-pattern>/*</url-pattern>
<url-pattern>/x1</url-pattern>
<!-- 只对请求做拦截(默认) -->
<dispatcher>REQUEST</dispatcher>
<!-- 增加对请求转发做拦截 -->
<dispatcher>FORWARD</dispatcher>
<!-- 增加请求包含做拦截 -->
<dispatcher>INCLUDE</dispatcher>
<!-- 增加跳转到错误页面做拦截 -->
<dispatcher>ERROR</dispatcher>
</filter-mapping>

<error-pag
1006e
e>
<error-code>404</error-code>
<location>/404.jsp</location>
</error-page>


05.请求编码过滤器CharacterEncodingFilter

Servelt只管 1:获取 2:调用 3:跳转 就行,设置编码交给Filter就行, DRY原则 跟 责任分离原则!


//字符编码过滤器
public class CharacterEncodingFilter implements Filter{

private String encoding;

private Boolean forceEncoding = false;

public void init(FilterConfig config) throws ServletException {
this.encoding = config.getInitParameter("encoding");
forceEncoding = Boolean.valueOf(config.getInitParameter("force"));
}

public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
//类型
HttpServletRequest req = (HttpServletRequest) request;
HttpServletResponse resp = (HttpServletResponse) response;
//设置编码
//1:应用中没有编码,并且我自己设置了编码.
//2:应用中已经存在编码了但是依然要使用我自己设置的编码:强制使用
if(haslength(encoding) && (req.getCharacterEncoding() == null || forceEncoding)){
req.setCharacterEncoding(encoding);
}
chain.doFilter(req, resp);
}

public void destroy() {

}

private boolean haslength(String str){
return str!=null && !"".equals(str.trim());
}
}


XML配置文件

<filter>
<filter-name>CharacterEncodingFilter</filter-name>
<filter-class>com._520it._02_characterencoding.CharacterEncodingFilter</filter-class>
<!-- 设置编码 -->
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
<!-- 是否强制使用该编码  -->
<init-param>
<param-name>force</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>CharacterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>


06.登陆检查过滤器

![登录检查的流程图](http://img.blog.csdn.net/20180310170822918?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvd2VpeGluXzQwMTYxNzA4/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70)


检查登录过滤器

//登录检查过滤器
public class CheckLoginFilter implements Filter{

private String[] unCheckUris = {"/login.jsp","/login"};

public void init(FilterConfig filterConfig) throws ServletException {
}
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) request;
HttpServletResponse resp = (HttpServletResponse) response;
Object user = req.getSession().getAttribute("USER_IN_SESSION");
//当前正在过滤的资源
String requestURI = req.getRequestURI();
if(!Arrays.asList(unCheckUris).contains(requestURI)){
if(user == null){//没有登录
resp.sendRedirect("login.jsp");
return ;
}
}
chain.doFilter(req, resp);
}
public void destroy() {
}
}


从登录界面跳转到的Servlet中

@WebServlet("/login")
public class LoginServelt extends HttpServlet{

private static final long serialVersionUID = 1L;

protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String username = req.getParameter("username");
//把登录信息存储到session中
req.getSession().setAttribute("USER_IN_SESSION",username);
resp.sendRedirect("/welcome.jsp");
}
}


login.jsp登录界面

<form action="/login" method="post">
账号:<input type="text" name="username" required/><br/>
密码:<input type="text" name="password"/><br/>
<input type="submit" value="登录"/>
</form>


welcom.jsp

${sessionScope.USER_IN_SESSION}
<hr/>
<a href="function1.jsp">功能1</a><br/>
<a href="function2.jsp">功能2</a><br/>
<a href="function3.jsp">功能3</a><br/>


Filter的配置文件

<filter>
<filter-name>CheckLoginFilter</filter-name>
<filter-class>com._520it.checklogin.CheckLoginFilter</filter-class>
<init-param>
<param-name>unCheckUris</param-name>
<!-- 以后这样做 对需要检查的放到/system/中来 -->
<param-value>/system/*</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>CheckLoginFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>


07.敏感字过滤

利用装饰设计模式,给Request.getParameter赋予敏感字过滤功能

![流程示意图](http://img.blog.csdn.net/20180310212548133?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvd2VpeGluXzQwMTYxNzA4/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70)


给Filter中的request赋予过滤字符的功能

public class MessageRequestWapper extends HttpServletRequestWrapper{
public MessageRequestWapper(HttpServletRequest request) {
super(request);
}
//覆盖getParameter方法,使之支持敏感字过滤
public String getParameter(String name){
//如果参数名为title或content
if("title".equals(name) || "content".equals(name)){
//返回过滤之后的title和content
FilterUtil.filter(super.getParameter(name)); //FilterUtils就是过滤的代码,现在先知道就行
}
return super.getParameter(name);
}
}


过滤器(filter)使用

@WebFilter("/*")
public class MessageFilter implements Filter{
public void init(FilterConfig filterConfig) throws ServletException {
}
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
//把不具有处理敏感字的请求对象换成可以处理敏感字的请求对象.
HttpServletRequest req = (HttpServletRequest) request;
HttpServletRequest requestWapper = new MessageRequestWapper(req);
//放行
chain.doFilter(requestWapper, response);
}
public void destroy() {
}
}


二: Listener(监听器)

Web的另一大组件:Listener(监听器).

Web中的监听器,主要用于监听作用域对象的创建,监听作用域对象属性的添加/删除/替换:

1):监听作用域对象的创建和销毁.

ServletRequestListener:监听请求对象的创建和销毁.

HttpSessionListener:监听会话对象(session) 的创建和销毁

ServletContextListener:监听应用的创建和销毁.

2):监听作用域对象的属性的添加/删除/替换.

ServletRequestAttributeListener: 监听request作用域中属性的添加/删除/替换.

HttpSessionAttributeListener: 监听session作用域中属性的添加/删除/替换.

ServletContextAttributeListener: 监听application作用域中属性的添加/删除/替换.

Web中的监听器组件,没有初始化参数配置如果要解决监听器中的硬编码,只能使用全局的初始化参数.


//监听系统(应用)的启动和销毁
public class ContextLoaderListener implements ServletContextListener{

public void contextInitialized(ServletContextEvent sce) {
System.out.println("Web系统启动了.....");
}

public void contextDestroyed(ServletContextEvent sce) {
System.out.println("Web系统销毁了.....");
}
}


@WebListener
public class HttpSessionListenerDemo implements HttpSessionListener{

public void sessionCreated(HttpSessionEvent se) {
System.out.println("会话开始了");
}

public void sessionDestroyed(HttpSessionEvent se) {
System.out.println("会话结束了");
}
}


@WebListener
public class HttpSessionAttributeListenerDemo implements HttpSessionAttributeListener{

public void attributeAdded(HttpSessionBindingEvent se) {
System.out.println("属性添加"+se.getName()+","+se.getValue());
}
public void attributeRemoved(HttpSessionBindingEvent se) {
System.out.println("属性删除"+se.getName()+","+se.getValue());
}
public void attributeReplaced(HttpSessionBindingEvent se) {
System.out.println("属性替换"+se.getName()+","+se.getValue()+","+se.getSession().getAttribute(se.getName()));
}
}


预习,精通Struts2的hello开发:
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  Filter Listener