Servlet过滤器web.xml文件配置

企业级JavaⅠ 专栏收录该内容
3 篇文章 0 订阅

这星期学了关于servlet过滤器的一些知识,现在把我之前没弄懂的地方给写下来,方便自己看回去也方便大家(高手请绕路)

首先先说下:Servlet过滤器,它是一种特殊的Servlet,可以用来对请求进行过滤。多个过滤器可以形成过滤链( FilterChain )。
当请求发送到servlet之前,可以用过滤器截获和处理请求,另外servlet结束工作之后,在响应发回给客户之前,可以用过滤器处理响应。

接下来,我们要用Java类来做过滤器, 注意是用Java类,不是servlet
当一个Java类 实现了 javax.servlet.Filter 接口,成为了过滤器,可以访问ServletContext;

容器管理过滤器的生命周期: init()→doFile()→destory()

首先:init()

   当容器实例化一个过滤器时,在init()方法中完成调用过滤器之前的所有初始化任务。

然后:真正的工作在doFilter()中完成

   容器对当前请求应用过滤器时,就会调用doFilter()方法完成过滤功能。该方法有三个参数:    doFilter(ServletRequest,ServletResponse,FilterChain)

最后:destroy()

   容器删除一个过滤器实例时,调用该方法回收清理工作


好了,理论就不多说,想看详细的理论知识可以到这个博客看 http://blog.163.com/lubihua_soft/blog/static/1302513702009118111244587/

接下来,开始实践操作

①建立项目,创建filter和servlet

首先,建立一个工程,分别创建下列文件,如下图:



第一个包com.myFilter里面分别创建3个filter.java文件,并在doFile中输出各自语句加以区分即可

Filter1的代码如下(另外2个相同道理创建):

package com.myFilter;

import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;

public class Filter1 implements Filter {
	public void destroy() {
	}

	public void init(FilterConfig config) throws ServletException {
	}

	public void doFilter(ServletRequest request, ServletResponse response,
			FilterChain chain) throws IOException, ServletException {
		try {
			System.out.println("filter1 go");//测试请求过滤
			chain.doFilter(request, response);
			System.out.println("filter1 return");//测试响应过滤
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}

第二个包com.myServlet这个包里面只有一个servlet文件:ServletTest.java

代码:

package com.myServlet;

import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class ServletTest extends HttpServlet {

	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		response.setContentType("text/html");
		PrintWriter out = response.getWriter();
		out.println("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">");
		out.println("<HTML>");
		out.println("  <HEAD><TITLE>A Servlet</TITLE></HEAD>");
		out.println("  <BODY>");
		out.println("<h1>hello</h1>");
		out.println("  </BODY>");
		out.println("</HTML>");
		out.flush();
		out.close();
	}
	public void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		doGet(request, response);
	}
}


需要用到的servlet文件和filter文件已经建好了,接下来就是在web.xml文件下配置

②配置web.xml文件

首先,打开本工程中/WebRoot/WEB-INF下的web.xml文件

 一般先配置filter的相关属性,再配置servlet

代码如下(相关注释以标明):

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
	http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
	<display-name></display-name>
	<welcome-file-list>
		<welcome-file>index.jsp</welcome-file>
	</welcome-file-list>

	<filter><!-- 声明过滤器实现类和 初始化参数 -->
		<filter-name>Filter1</filter-name><!-- 过滤器名 -->
		<filter-class>com.myFilter.Filter1</filter-class><!--过滤器类,包括包名 -->
		<!—下面这个init-param是设置初始化参数,本次测试没有用到,可以不写 -->
		<init-param>
            <param-name>a</param-name><!-- 初始化参数名 -->
            <param-value>5</param-value><!-- 初始化参数值 -->
        	</init-param>
	</filter>

	<filter>
		<filter-name>Filter2</filter-name>
		<filter-class>com.myFilter.Filter2</filter-class>
	</filter>

	<filter>
		<filter-name>Filter3</filter-name>
		<filter-class>com.myFilter.Filter3</filter-class>
	</filter>

<filter-mapping><!-- 将过滤器映射到servlet或者URL中,即把过滤器和web资源关联起来 -->
        <filter-name>Filter1</filter-name><!-- 上面声明过的过滤器名 -->
        <servlet-name> /*</servlet-name><!-- 指定过滤器映射的URL,/*是指全部URL -->
    </filter-mapping>
    <filter-mapping>
        <filter-name> Filter2</filter-name>
        <url-pattern>/*</url-pattern>
</filter-mapping>
<filter-mapping>
		<filter-name>Filter3</filter-name>
		<servlet-name>ServletTest</servlet-name><!-- 指定过滤器映射的servlet -->
	</filter-mapping>

	<servlet>
		<servlet-name>ServletTest</servlet-name>
		<servlet-class>com.myServlet.ServletTest</servlet-class>
	</servlet>

	<servlet-mapping>
		<servlet-name>ServletTest</servlet-name>
		<url-pattern>/servlet/ServletTest</url-pattern>
	</servlet-mapping>

</web-app>


③部署与测试

配置完成后,我们就可以把这个web 项目部署到服务器了(weblogic或者tomcat都行)

如果到此都没出现错误的话,那恭喜你,项目基本上可以运行了

在浏览器输入网址(我这里是用tomcat,所以端口是8080,如果是weblogic的话改成7001即可):http://localhost:8080/FilterTest/servlet/ServletTest

然后页面会显示下图:


如果上面这步没出现错误并显示成功的话,我们返回myeclipse,在控制台我们会看见


ok,做到这里,我们的工作基本完成了。下面要做的就是解决我们的“为什么”!


那么为什么会出现这个结果呢?

我们来看下请求过滤与响应过滤的顺序:


由上图,我们可以很容易知道,当客户在浏览器访问一个页面的时候,客户的请求会先经过servlet过滤器的处理,最后才到达servlet。


看完这里,我们的问题可以再细化一下,变成两个:

①为什么会3个filter的信息都输出来呢?

②这个输出的顺序能否改变?


第一个问题:

为什么会3个filter的信息都输出来呢?

这里我们可以打开配置好的web.xml文件看看


仔细看下红框位置,我们可以看到,在filter1和filter2的关联URL路径是“/*”,“/*”表示本工程里面的所有URL,就是说,访问任何一个本工程的网页都必须经过filter1和filter2的处理(即每次访问都要调用filter1和filter2的doFilter()方法)。

而filter3关联的却是一个servlet,因为我们上面访问的页面正好是filter3关联的servlet,所以,filter3的信息也会被输出。

PS:因为filter3关联的是一个指定servlet,所以说,我们只要不访问这个servlet(比如:http://localhost:8080/FilterTest/),就可以看到控制台的结果会少了filter3的输出信息。


第二个问题:

输出的顺序能否改变?

先看下比较官方的解释根据servlet2.3规范filter执行是按照web.xml配置的filter-mapping先后顺序进行执行

也就是说因为我们上面配置的web.xml文件中,过滤器的关联顺序是filter1、filter2、filter3,所以输出的结果是1、2、3、3、2、1

那么,要想改变顺序的话,我们直接把<filter-mapping>的顺序调一下就可以解决问题了。

但是,事情往往不会那么顺利的,当我们把filter3的<filter-mapping>调到第一的时候,控制台输出的结果却不是第一个输出filter3的信息,而且无聊你怎么改,都是没作用。最后查了一下资料,是因为过滤器在关联servlet或URL的时候,是遵循这样的规则的:先找到与URL模式匹配的所有过滤器,最后再找与servlet-name匹配的过滤器。

就是说,因为filter1、filter2关联的是URL,而filter3关联的是servlet,所以无论<filter-mapping>的位置怎么改都好,容器都会先找到URL关联的filter,最后再去找servlet关联的filter!

 

好了,今天的servlet过滤器初步学习就到此先!





  • 5
    点赞
  • 0
    评论
  • 11
    收藏
  • 打赏
    打赏
  • 扫一扫,分享海报

©️2022 CSDN 皮肤主题:大白 设计师:CSDN官方博客 返回首页

打赏作者

WeiBin_Lin

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值