一:filter:过滤器,拦截servlet的请求和响应。
1、
1 package jd.com.filter; 2 3 import javax.servlet.*; 4 import java.io.IOException; 5 6 public class MyFilter implements Filter { 7 @Override 8 public void destroy() { 9 10 } 11 12 @Override 13 public void init(FilterConfig filterConfig) { 14 15 } 16 17 @Override 18 public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) { 19 20 try { 21 System.out.println("请求到拦截器。"); 22 //放行请求和响应。 23 filterChain.doFilter(servletRequest,servletResponse); 24 System.out.println("响应到拦截器。"); 25 }catch (Exception ex){ 26 ex.printStackTrace(); 27 throw new RuntimeException(ex+"run ereror"); 28 } 29 30 } 31 }
需要继承抽象类Filter,需要重写init和destory方法以及doFilter()方法。如果想放行请求和响应需要调用类FilterChain的方法doFilter(servletRequest,serletRespone)。
servlet:
1 package jd.com.filter; 2 3 import javax.servlet.ServletException; 4 import javax.servlet.annotation.WebServlet; 5 import javax.servlet.http.HttpServlet; 6 import javax.servlet.http.HttpServletRequest; 7 import javax.servlet.http.HttpServletResponse; 8 import java.io.IOException; 9 10 @WebServlet(name = "ServletFilter") 11 public class ServletFilter extends HttpServlet { 12 protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 13 14 } 15 16 protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 17 System.out.println("请求到servlet。"); 18 } 19 }
2、注册serlet和Filter。
1 <?xml version="1.0" encoding="UTF-8"?> 2 <web-app xmlns="http://java.sun.com/xml/ns/javaee" 3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 4 xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 5 http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" 6 version="2.5"> 7 <servlet> 8 <servlet-name>ServletFilter</servlet-name> 9 <servlet-class>jd.com.filter.ServletFilter</servlet-class> 10 </servlet> 11 <servlet-mapping> 12 <servlet-name>ServletFilter</servlet-name> 13 <url-pattern>/test/</url-pattern> 14 </servlet-mapping> 15 <filter> 16 <filter-name>MyFilter</filter-name> 17 <filter-class>jd.com.filter.MyFilter</filter-class> 18 </filter> 19 <filter-mapping> 20 <filter-name>MyFilter</filter-name> 21 <url-pattern>/test/</url-pattern> 22 </filter-mapping> 23 24 </web-app>
想flter过滤那个url需要在url-pattern里写那个url!
图示:
2、FilterChain 过滤链
当我们的jsp或者servlet被多个过滤器使用的时候,整个请求和响应形成的链叫做过滤链。
通过过滤链FilterChain的doFilter方法,将一个请求从一个过滤器放行到下一个过滤器,直到最后一个过滤器被调用放行的时候,才到达最后的servlet或者jsp。
doFilter()放行方法。区别于咱们重写抽象方法Filter的doFiltter()方法,一个是服务器调用一个是FilterChain调用。
3、多个过滤器作用一个url的执行顺序(filter-mapping在web.xml的顺序决定):
url匹配规则:
1)完全匹配 : 必须以"/"开头 例如:"/a"
2)目录匹配: 必须以"/"开头,以"*"结束,例如:"/a/*"
3)后缀名匹配: 以“*”开头,以"jsp、do、action"结束的。例如:“”*.jsp *.do *.action“”
匹配规则:
以精确匹配>最长路径匹配>后缀名匹配>默认匹配
例1:比如servletA 的url-pattern为 /test,servletB的url-pattern为 /* ,这个时候,如果我访问的url为http://localhost/test ,这个时候容器就会先进行精确路径匹配,发现/test正好被servletA精确匹配,那么就去调用servletA,不会去管servletB。
例2:比如servletA的url-pattern为/test/*,而servletB的url-pattern为/test/a/*,此时访问http://localhost/test/a时,容器会选择路径最长的servlet来匹配,也就是这里的servletB。
例3: 比如servletA的url-pattern:*.action ,servletB的url-pattern为 /* ,这个时候,如果我访问的url为http://localhost/test.action,这个时候容器就会优先进行路径匹配,而不是去匹配扩展名,这样就去调用servletB。
filter匹配规则:
例子:Afilter urlpattern:/*
Bfilter urlpattern::/a/c
servlet的url为:/a/c的时候,如上filter都会被使用,那Afilterr和Bfilter执行顺序是什么呢?
web.xml注册顺序:
<filter-name>FilterA</filter-name> <filter-class>jd.com.mapFilter.FilterA</filter-class> </filter> <filter-mapping> <filter-name>FilterA</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <filter> <filter-name>FilterB</filter-name> <filter-class>jd.com.mapFilter.FilterB</filter-class> </filter> <filter-mapping> <filter-name>FilterB</filter-name> <url-pattern>/a/c</url-pattern> </filter-mapping>
实际输出结果:
(响应回来的时候先经过B在经过A)
也就是说,执行filter的顺序是按照,在web.xml中的filter-mapping的顺序来决定,我们的这个2个顺序调换,看下输出:
1 <filter> 2 <filter-name>FilterA</filter-name> 3 <filter-class>jd.com.mapFilter.FilterA</filter-class> 4 </filter> 5 <filter-mapping> 6 <filter-name>FilterB</filter-name> 7 <url-pattern>/a/c</url-pattern> 8 </filter-mapping> 9 <filter-mapping> 10 <filter-name>FilterA</filter-name> 11 <url-pattern>/*</url-pattern> 12 </filter-mapping> 13 <filter> 14 <filter-name>FilterB</filter-name> 15 <filter-class>jd.com.mapFilter.FilterB</filter-class> 16 </filter>
4)filter在web.xml其他标签:
1、<servlet-name>Servletdemo1</servlet-name>位置 <filter-mapping>内表示匹配那个servlet。是servletname不是相对路径。
注意:
如果一个filter-mapping其中已经存在url-pattern 不要在存在servlet-name,在不同的版本中会重复执行2次过滤器!!
2、<dispatcher></dispatcher> dispatch filter作用那种请求。
请求(3和4了解):1、REQUEST:从浏览器发送过来的请求,这个filter的默认作用请求。
2、FORWARD:转发过来的请求。
3、ERROR:因为服务器错误而发送过来的请求。
4、INCLUDE:包含过来的请求。
1)默认情况(request)
demo1:
1 package jd.com.otherTag; 2 3 import javax.servlet.ServletException; 4 import javax.servlet.annotation.WebServlet; 5 import javax.servlet.http.HttpServlet; 6 import javax.servlet.http.HttpServletRequest; 7 import javax.servlet.http.HttpServletResponse; 8 import java.io.IOException; 9 10 @WebServlet(name = "Servletdemo1") 11 public class Servletdemo1 extends HttpServlet { 12 protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 13 14 } 15 16 protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 17 System.out.println("请求进入Servletdemo1"); 18 request.getRequestDispatcher("/a/b").forward(request,response); 19 } 20 }
demo2:
1 package jd.com.otherTag; 2 3 import javax.servlet.ServletException; 4 import javax.servlet.annotation.WebServlet; 5 import javax.servlet.http.HttpServlet; 6 import javax.servlet.http.HttpServletRequest; 7 import javax.servlet.http.HttpServletResponse; 8 import java.io.IOException; 9 10 @WebServlet(name = "Servletdemo2") 11 public class Servletdemo2 extends HttpServlet { 12 protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 13 14 } 15 16 protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 17 System.out.println("进入Servletdemo2 请求"); 18 } 19 }
web.xml
1 <servlet> 2 <servlet-name>Servletdemo1</servlet-name> 3 <servlet-class>jd.com.otherTag.Servletdemo1</servlet-class> 4 </servlet> 5 <servlet-mapping> 6 <servlet-name>Servletdemo1</servlet-name> 7 <url-pattern>/a</url-pattern> 8 </servlet-mapping> 9 <filter> 10 <filter-name>demoFilter</filter-name> 11 <filter-class>jd.com.otherTag.demoFilter</filter-class> 12 </filter> 13 <filter-mapping> 14 <filter-name>demoFilter</filter-name> 15 <url-pattern>/*</url-pattern> 16 </filter-mapping> 17 <servlet> 18 <servlet-name>Servletdemo2</servlet-name> 19 <servlet-class>jd.com.otherTag.Servletdemo2</servlet-class> 20 </servlet> 21 <servlet-mapping> 22 <servlet-name>Servletdemo2</servlet-name> 23 <url-pattern>/a/b</url-pattern> 24 </servlet-mapping>
注意:
因为filter的匹配url为/*所有 如果匹配的不是所有的话 需要注意的是filter的url和其他2个demo的url是包含关系。
1 <servlet> 2 <servlet-name>Servletdemo1</servlet-name> 3 <servlet-class>jd.com.otherTag.Servletdemo1</servlet-class> 4 </servlet> 5 <servlet-mapping> 6 <servlet-name>Servletdemo1</servlet-name> 7 <url-pattern>/a/c</url-pattern> 8 </servlet-mapping> 9 <filter> 10 <filter-name>demoFilter</filter-name> 11 <filter-class>jd.com.otherTag.demoFilter</filter-class> 12 </filter> 13 <filter-mapping> 14 <filter-name>demoFilter</filter-name> 15 <url-pattern>/a/*</url-pattern> 16 </filter-mapping> 17 <servlet> 18 <servlet-name>Servletdemo2</servlet-name> 19 <servlet-class>jd.com.otherTag.Servletdemo2</servlet-class> 20 </servlet> 21 <servlet-mapping> 22 <servlet-name>Servletdemo2</servlet-name> 23 <url-pattern>/a/b</url-pattern> 24 </servlet-mapping>
结果:
在转发的时候,没有经过demofilter,直接转发到servletdemo2.
解决方法:
默认情况下走的是请求是REQUEST,所以需要添加FORWARD的请求。注意需要写REQUEST请求,因为如果写其他请求默认请求不会生效。
1 <filter> 2 <filter-name>demoFilter</filter-name> 3 <filter-class>jd.com.otherTag.demoFilter</filter-class> 4 </filter> 5 <filter-mapping> 6 <filter-name>demoFilter</filter-name> 7 <url-pattern>/a/*</url-pattern> 8 <dispatcher>REQUEST</dispatcher> 9 <dispatcher>FORWARD</dispatcher> 10 </filter-mapping>
结果:
2)设置错误页。
1 <servlet> 2 <servlet-name>ServletError</servlet-name> 3 <servlet-class>jd.com.coding.ServletError</servlet-class> 4 </servlet> 5 <servlet-mapping> 6 <servlet-name>ServletError</servlet-name> 7 <url-pattern>/c</url-pattern> 8 </servlet-mapping> 9 <error-page> 10 <error-code>404</error-code> 11 <location>/c</location> 12 </error-page>
1 package jd.com.coding; 2 3 import javax.servlet.ServletException; 4 import javax.servlet.annotation.WebServlet; 5 import javax.servlet.http.HttpServlet; 6 import javax.servlet.http.HttpServletRequest; 7 import javax.servlet.http.HttpServletResponse; 8 import java.io.IOException; 9 10 @WebServlet(name = "ServletError") 11 public class ServletError extends HttpServlet { 12 protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 13 14 } 15 16 protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 17 response.setContentType("text/html;charset=UTF-8"); 18 response.getWriter().print("亲访问的资源不存在!"); 19 } 20 }