过滤器中的chain.doFilter(request,response)

先来说说过滤器filter的作用,它就相当于公路上的一个关卡,对要通过的拦截下来进行相关操作或放行。

dofilter作用【request -> filter1 -> filter2 ->filter3 -> .... -> request resource。】

先写一个简单的没有filter的登录例子,当用户名和密码都是admin时,能跳转到success页面,否则到fail页面。

1、eclipse建立一个web project ,结果目录如下

其中,jsp很简单。在login.jsp为一个form表单

1   <form action="<%=request.getContextPath() %>/servlet/LoginServlet" method="post">
2   用户名:<input type="text" name="username">
3   密码:<input type="password" name="password">
4  <input type="submit" value="提交">
5 </form>

xml中为

 1   <servlet>
 2     <description>This is the description of my J2EE component</description>
 3     <display-name>This is the display name of my J2EE component</display-name>
 4     <servlet-name>LoginServlet</servlet-name>
 5     <servlet-class>com.imooc.serlvet.LoginServlet</servlet-class>
 6   </servlet>
 7
 8   <servlet-mapping>
 9     <servlet-name>LoginServlet</servlet-name>
10     <url-pattern>/servlet/LoginServlet</url-pattern>
11   </servlet-mapping>    

LoginServlet.java中主要是

 1     public void destroy() {
 2         super.destroy(); // Just puts "destroy" string in log
 3         // Put your code here
 4     }
 5 public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
 6         String username = request.getParameter("username");
 7         String password = request.getParameter("password");
 8
 9         System.out.println(username);
10
11         if("admin".equals(username) && "admin".equals(password)){
12             //校验通过
13             HttpSession session = request.getSession();
14             session.setAttribute("username", username);
15             response.sendRedirect(request.getContextPath()+"/sucess.jsp");
16         }else{
17             //校验失败
18             response.sendRedirect(request.getContextPath()+"/fail.jsp");
19         }
20
21     }
22 public void init() throws ServletException {
23         // Put your code here
24     }

运行后进入:...8080/LoginFilter/login.jsp

当用户名和密码都输入admin,按下submit,就会进入action对应的servlet,然后重定向到success.jsp页面;用户名密码不对就到fail.jsp。

仔细想想会想到,可以直接在地址输入8080/LoginFilter/success.jsp不就进入了成功的页面了吗,还有类似页面。这样时不安全的,所以要加入拦截器

2、在此项目加入拦截器filter,也就是对其url进行拦截,不让其用url随便访问,结构中多了个类文件

在xml中添加

 1  <filter>
 2        <filter-name>LoginFilter</filter-name>
 3        <filter-class>com.imooc.filter.LoginFilter</filter-class>
 4  </filter>
 5  <filter-mapping>
 6        <filter-name>LoginFilter</filter-name>
 7        <url-pattern>/success.jsp</url-pattern>
 8  </filter-mapping>

这样,url输入...8080/LoginFilter/success.jsp就会进行拦截,进入LoginFilter.java

里面主要为:

 1 @Override
 2     public void destroy() {
 3     }
 4     @Override
 5     public void doFilter(ServletRequest arg0, ServletResponse arg1, FilterChain arg2) throws IOException, ServletException {
 6         HttpServletRequest request = (HttpServletRequest) arg0;
 7         HttpServletResponse response = (HttpServletResponse) arg1;
 8         HttpSession session = request.getSession();
 9 //因为登录后保存了username,所以可以先检查username判断是否登录
10 if(session.getAttribute("username")!=null){
11             arg2.doFilter(arg0, arg1);//已登录,则放行,
12         }else{
13             response.sendRedirect("login.jsp");//未登录,重定向到登录页面
14         }
15     }

【 出现了 arg.doFailter(arg0,arg1),他表示好像放行、通过这样,继续往下到LoginServlet.java中,如果没有写 arg.doFailter(arg0,arg1)。那就是,把他拦截下来后,什么都不做,也不让它通过,那就会卡在那里不能往下了。】

【在这里只是request -> filter1 -> request resource。】

这样的思路,就可以拦截一些不能随便访问的页面,但如果这类页面很多,可访问的页面相对少,则可以把拦截的地址改为/*,也就是

1    <filter-mapping>
2          <filter-name>LoginFilter</filter-name>
3          <url-pattern>/success.jsp</url-pattern>
4    </filter-mapping>
5 改成
6  <filter-mapping>
7          <filter-name>LoginFilter</filter-name>
8          <url-pattern>/*</url-pattern>
9    </filter-mapping>

再对本不用拦截的,比如login.jsp 在LoginFilter进行判断

 1      public void doFilter(ServletRequest arg0, ServletResponse arg1, FilterChain arg2) throws IOException, ServletException {
 2          HttpServletRequest request = (HttpServletRequest) arg0;
 3          HttpServletResponse response = (HttpServletResponse) arg1;
 4         HttpSession session = request.getSession();
 5 //如果是login.jsp,则不拦截,直接放行,不用进行其他操作
 6 if(request.getRequestURI().indexOf("login.jsp")!=-1 ){
 7                     arg2.doFilter(arg0, arg1);
 8                     return;
 9                 }
10
11 //因为登录后保存了username,所以可以先检查username判断是否登录
12  if(session.getAttribute("username")!=null){
13              arg2.doFilter(arg0, arg1);//已登录,则放行,
14          }else{
15              response.sendRedirect("login.jsp");//未登录,重定向到登录页面
16          }

仔细想想,其他问题也来了,因为拦截所有页面,所以按下submit时都过不去(action="<%=request.getContextPath() %>/servlet/LoginServlet" 也要拦截,过不去),则要添加一些不需拦截的url

1 //如果是下面3个url,则不拦截,直接放行,不用进行其他操作
2  if(request.getRequestURI().indexOf("login.jsp")!=-1
3   ||request.getRequestURI().indexOf("servlet/LoginServlet")!=-1
4   ||request.getRequestURI().indexOf("fail.jsp")!=-1
5 ){
6                    arg2.doFilter(arg0, arg1);
7                 return;
8                 }

但这样也有问题,当不需拦截的url多了,if语句也屡屡需要修改,很麻烦,则可以用 FilterConfig对象。先在xml添加配置,有新的不需要拦截的url,秩序在配置里添加即可。

 1     <filter>
 2         <filter-name>LoginFilter</filter-name>
 3         <filter-class>com.imooc.filter.LoginFilter</filter-class>
 4         <init-param>
 5             <param-name>noLoginPaths</param-name>
 6             <param-value>login.jsp;fail.jsp;LoginServlet</param-value> //在此添加不需拦截的url
 7         </init-param>
 8         <init-param>
 9             <param-name>charset</param-name> //防止中文乱码
10             <param-value>UTF-8</param-value>
11         </init-param>
12     </filter>
13     <filter-mapping>
14         <filter-name>LoginFilter</filter-name>
15         <url-pattern>/*</url-pattern>
16     </filter-mapping>

在dofilter中得到此对象 LoginFilter.java

 1 public class LoginFilter implements Filter {
 2     private FilterConfig config;  //这里定义一下
 3     @Override
 4     public void destroy() {
 5
 6     }
 7     @Override
 8     public void doFilter(ServletRequest arg0, ServletResponse arg1, FilterChain arg2) throws IOException, ServletException {
 9
10         HttpServletRequest request = (HttpServletRequest) arg0;
11         HttpServletResponse response = (HttpServletResponse) arg1;
12         HttpSession session = request.getSession();
13         String noLoginPaths = config.getInitParameter("noLoginPaths"); //已获取filterconfig对象,可以获取其中属性
14
15         String charset = config.getInitParameter("charset");
16         if(charset==null){
17             charset = "UTF-8";
18         }
19         request.setCharacterEncoding(charset);
20
21         if(noLoginPaths!=null){
22             String[] strArray = noLoginPaths.split(";");  //对属性的值分割。分别放行
23             for (int i = 0; i < strArray.length; i++) {
24                 if(strArray[i]==null || "".equals(strArray[i]))continue;
25         if(request.getRequestURI().indexOf(strArray[i])!=-1 ){
26                     arg2.doFilter(arg0, arg1);
27                     return;
28                 }
29             }
30         }
31         if(session.getAttribute("username")!=null){
32             arg2.doFilter(arg0, arg1);
33         }else{
34             response.sendRedirect("login.jsp");
35         }
36     }
37     @Override
38     public void init(FilterConfig arg0) throws ServletException {
39         config = arg0;  //在初始化时把次对象赋值
40     }
41
42 }//执行顺序:最先初始化init(),然后dofilter函数    最后destory()

这里,这个登录案例就完成了。

那【request -> filter1 -> filter2 ->filter3 -> .... -> request resource。】是什么呢

就是一个url-partten对应了多个filter,一个url,被拦截了好几次。

 1   <filter>
 2         <filter-name>FirstFilter</filter-name>
 3         <filter-class>com.imooc.filter.FirstFilter</filter-class>
 4  </filter>
 5     <filter>
 6         <filter-name>SecondFilter</filter-name>
 7         <filter-class>com.imooc.filter.SecondFilter</filter-class>
 8     </filter>
 9
10     <filter-mapping>
11         <filter-name>FirstFilter</filter-name>
12         <url-pattern>/index.jsp</url-pattern>
13     </filter-mapping>
14    <filter-mapping>
15         <filter-name>SecondFilter</filter-name>
16         <url-pattern>/index.jsp</url-pattern>
17     </filter-mapping>

这样就存在一个过滤器链,按xml中顺序执行。

index.jsp

1   <body>
2     This is my JSP page. <br>
3     <%
4     System.out.println("到了index.jsp");
5      %>
6   </body>

FirstFilter.java

 1 public class FirstFilter implements Filter {
 2
 3     @Override
 4     public void destroy() {
 5         System.out.println("destroy---FirstFilter");
 6     }
 7
 8     @Override
 9     public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
10         System.out.println("start----doFilter--FirstFilter");
11         chain.doFilter(request, response);
12         HttpServletRequest req =(HttpServletRequest) request;
13         HttpServletResponse response2 =(HttpServletResponse) response;

19         System.out.println("end------doFilter--FirstFilter");
20     }
21
22     @Override
23     public void init(FilterConfig filterConfig) throws ServletException {
24         System.out.println("init----FirstFilter");
25     }
26
27
28 }

SecondFilter.java

 1 public class SecondFilter implements Filter {
 2
 3     @Override
 4     public void destroy() {
 5         System.out.println("destroy-----SecondFilter");
 6     }
 7
 8     @Override
 9     public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
10         System.out.println("start---doFilter--SecondFilter");
11         chain.doFilter(request, response);
12         System.out.println("end---doFilter--SecondFilter");
13     }
14
15     @Override
16     public void init(FilterConfig filterConfig) throws ServletException {
17
18         System.out.println("init-----SecondFilter");
19     }
20
21 }

过滤器链具体的执行顺序:

在运行项目时,两个filter类都执行了init()初始化,控制台输出:

init-----FirstFilter
init-----SecondFilter

当访问index.jsp时,进入FirstFilter.java的dofilter函数,控制台会依次输出:

start---doFilter--FirstFilter
start---doFilter--SecondFilter
到了index.jsp
end---doFilter--FirstFilter
end---doFilter--SecondFilter

在dofilter函数中,先执行chain.doFilter(request, response);前的代码,然后下一个filter链的下一个filter,然后进入index.jsp。再继续依次执行chain.doFilter(request, response);后面的代码

Code1表示ilter(request, response);之前的代码Code2表示ilter(request, response);之后的代码。

文章为学习记录,若有错误,望指正。

时间: 2024-10-07 06:07:38

过滤器中的chain.doFilter(request,response)的相关文章

过滤器chain.doFilter(request,response)的含义

过滤器的生命周期一般都要经过下面三个阶段: 初始化: 当容器第一次加载该过滤器时,init() 方法将被调用.该类在这个方法中包含了一个指向 Filter Config 对象的引用.我们的过滤器实际上并不需要这样做,因为其中没有使用初始化信息,这里只是出于演示的目的. 过滤: 过滤器的大多数时间都消耗在这里.doFilter方法被容器调用, 同时传入分别指向这个请求/响应链中的 Servlet Request.Servlet Response 和 Filter Chain 对象的引用.然后过滤器

//可以不保存在session中, 并且前面我保存在request,这里session也可以获取 chain.doFilter(request, response); //只有登录名不为空时放行,防止直接登录 成功的页面

public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { HttpServletRequest httprequest = (HttpServletRequest)request; HttpServletResponse httpresponse = (HttpServletResponse)res

chain.doFilter(request,response)含义

过滤器的生命周期一般都要经过下面三个阶段: 初始化 当容器第一次加载该过滤器时,init() 方法将被调用.该类在这个方法中包含了一个指向 Filter Config 对象的引用.我们的过滤器实际上并不需要这样做,因为其中没有使用初始化信息,这里只是出于演示的目的. 过滤 过滤器的大多数时间都消耗在这里.doFilter方法被容器调用,同时传入分别指向这个请求/响应链中的 Servlet Request.Servlet Response 和 Filter Chain 对象的引用.然后过滤器就有机

对chain.doFilter(request,response)的理解

他的作用是将请求转发给过滤器链上下一个对象.这里的“下”指的是哪里 ? 指的是下一个filter,如果没有filter那就是你请求的资源. 一般filter都是一个链,web.xml 里面配置了几个就有几个.一个一个的连在一起 request -> filter1 -> filter2 ->filter3 -> .... -> request resource. 下面举一个例子: input.jsp 是用来提交输入的,当提交后,过滤器检测姓名和年龄,如果整常的话会提交给out

Java filter中的chain.doFilter详解

转载: 一.chain.doFilter作用 1.一般filter都是一个链,web.xml 里面配置了几个就有几个.一个一个的连在一起 request -> filter1 -> filter2 ->filter3 -> -. -> request resource. 2.chain.doFilter将请求转发给过滤器链下一个filter , 如果没有filter那就是你请求的资源 二.举例 input.jsp 是用来提交输入的 : 当提交后,过滤器检测姓名和年龄 . 如果

java 过滤器Filter中chain.doFilter()之前和之后代码的执行顺序

过滤器拦截到响应url的请求后会先执行doFilter()方法中chain.doFilter()之前的代码,然后执行下一个过滤器或者servelt.紧接着执行chain.doFilter()之后的代码. 一下为两个过滤器的执行顺序: 过滤器一: package com.rskd_yswb.lib.filter; import javax.servlet.*; import java.io.IOException; public class HttpRequestAndResponseFilter

关于项目在网页中运行部分jsp出现乱码(由request.getRequestDispatcher(&quot;XXX.jsp&quot;).forward(request, response)造成)的解决方法

在写jsp的时候发现部分的jsp在浏览器预览时出现乱码,为一堆问号,如图: 当时问了同学,只有部分jsp会出现乱码,因为重新建一个jsp在运行就没有错误,可以显示出来,所以发现是jsp头部的错误,当新建一个jsp把内容复制过去可以正确显示,但当把名字改成需要跳转的jsp时就会出现乱码,所以我才发现是由于调用这个名字的jsp出现了错误即:request.getRequestDispatcher("XXX.jsp").forward(request, response)造成了乱码,解决只需

javaweb中重定向和请求转发(response.sendRedirect()和request.getRequestDispatcher(rul).forward(request,response)))的区别

先来两张图,方便理解: 可以看出,重定向时,是服务器向游览器重新发送了一个response命令,让游览器再次向url2发送请求,以获取url2的资源 而请求转发时,类似于是服务器自己向自己发了一个跳转,然后将结果直接给游览器,这也是问什么游览器会不改变url地址.下面是具体总结他们的区别 一.response.sendRedirect(url)-服务器将新url发送给游览器,游览器再根据新url请求 Request.getRequestDispatcher(url).forward(reques

web过滤器中获取请求的参数(content-type:multipart/form-data)

1.前言: 1.1 在使用springMVC中,需要在过滤器中获取请求中的参数token,根据token判断请求是否合法: 1.2 通过requst.getParameter(key)方法获得参数值; 这种方法有缺陷:它只能获取  POST 提交方式中的Content-Type: application/x-www-form-urlencoded; HttpServletRequest request= (HttpServletRequest) req; String param = reque