java web过滤器_JavaWeb——过滤器

过滤器简介

WEB过滤器是一个服务器端的组件,它可以截取用户端的请求与相应信息,并对这些信息过滤。

过滤器的工作原理和生命周期

在没有Web过滤器的情况下,用户直接访问服务器上的Web资源。但是如果存在过滤器,用户就不可以直接访问过滤器了。

Web容器启动的时候过滤器就已经启动了,用户的请求到达过滤器,过滤器判断用户的请求是否符合过滤规则,如果符合规则则将用户的请求发送给Web资源,Web资源将响应信息发送给过滤器,过滤器将Web资源的响应发送给用户。工作原理如下图所示:

da153743a18163157dae24f6f62326cf.png

过滤器的生命周期:

b1e96b62bbe6095de160fe506907f875.png

其中实例化方法在Web容器开始装载的时候就执行,初始化方法配置一些初始化参数,Web容器卸载(服务器关闭)的时候执行销毁方法。过滤方法会执行多次,其他方法只会执行一次。

第一个过滤器

1.创建一个类实现javax.servlet.Filter接口。需要实现该接口中的3个方法。

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

1 packagefilter;2

3 importjava.io.IOException;4

5 importjavax.servlet.Filter;6 importjavax.servlet.FilterChain;7 importjavax.servlet.FilterConfig;8 importjavax.servlet.ServletException;9 importjavax.servlet.ServletRequest;10 importjavax.servlet.ServletResponse;11

12 public class FirstFilter implementsFilter {13

14 public voiddestroy() {15 System.out.println("*********执行过滤器的销毁方法*******");16

17 }18

19 public voiddoFilter(ServletRequest request, ServletResponse response,20 FilterChain filterChain) throwsIOException, ServletException {21 System.out.println("*******开始执行过滤器的doFilter方法*********");22 filterChain.doFilter(request, response);23 System.out.println("*******结束执行过滤器的doFilter方法**********");24 }25

26 public void init(FilterConfig arg0) throwsServletException {27 System.out.println("*******执行过滤器的初始化方法***********");28

29 }30

31 }

FirstFilter.java

init(FilterConfig ):过滤器的初始化方法,Web容器创建过滤器之后将调用这个方法,在这个方法中可以读取web.xml中的过滤器参数。

doFilter(ServletRequest,ServletResponse,FilterChain):完成实际的过滤操作,是过滤器的核心方法。当用户请求访问与过滤器相关联的URL的时候,Web容器将先调用过滤器的doFilter方法。FilterChain参数可以调用chain.doFilter方法【放行方法】,将请求传送给下一个过滤器(或者目标资源),或利用转发、重定向将请求转发给其他资源。

destroy():Web容器在销毁过滤器实例前调用该方法,在这个方法中可以释放过滤器占用的资源。【大多数情况下用不到】

2.在web.xml中配置过滤器(和再web.xml中注册servlet类似)

dfb4f6ac089f530d3a45cb45f6d24a28.png

在MyEclipse中提供了可视化的配置web.xml,如下图:

c24362f39863e8de6fb4caa43b5396a9.png

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

1 <?xml version="1.0" encoding="UTF-8"?>

2

3 xmlns="http://java.sun.com/xml/ns/javaee"

4 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

5 xsi:schemaLocation="http://java.sun.com/xml/ns/javaee6 http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">

7

8

9 index.jsp

10

11

12

13

14 FirstFilter

15 filter.FirstFilter

16

17

18 FirstFilter

19 /*

20

21

22

23

web.xml

在index.jsp中我们在控制台打印一行信息:"**********这是index.jsp*********";

将项目部署到服务器,启动服务器:

b51b5379f04b9b1060eca9ebe93a0e32.gif

在Servlet容器装载的时候,执行过滤器的init方法,当用户请求页面的时候首先执行doFilter()方法,当Servlet容器卸载的时候执行过滤器的销毁方法。【注意:用户的请求先是到达过滤器并不是直接访问的Web资源】

还有一点需要注意:用户虽然能够改变用户请求的资源(例如:网上购物的时候点击“立即购买”,这个请求先要到达过滤器,如果过滤器检测到用户没有登录,就会将页面重定向到登陆页),但是过滤器不能直接处理用户的请求(过滤器不是Servlet),不能直接返回数据。

过滤器链

针对同一个用户请求(url-pattern),与之匹配的过滤器有多个,这个时候用户请求就会依次通过各个过滤器到达web资源。

daac6a0e0c882cd64b50613b9b42c2a2.png

d6ec8543e7c39b159b2a65aae4046879.png

新建2个过滤器:

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

1 packagefilter;2

3 importjava.io.IOException;4

5 importjavax.servlet.Filter;6 importjavax.servlet.FilterChain;7 importjavax.servlet.FilterConfig;8 importjavax.servlet.ServletException;9 importjavax.servlet.ServletRequest;10 importjavax.servlet.ServletResponse;11

12 public class FirstFilter implementsFilter {13

14 public voiddestroy() {15 System.out.println("*********过滤器1----->销毁方法*******");16

17 }18

19 public voiddoFilter(ServletRequest request, ServletResponse response,20 FilterChain filterChain) throwsIOException, ServletException {21 System.out.println("*******开始执行过滤器1----->doFilter方法*********");22 filterChain.doFilter(request, response);23 System.out.println("*******结束执行过滤器1----->doFilter方法**********");24 }25

26 public void init(FilterConfig arg0) throwsServletException {27 System.out.println("*******执行过滤器1------>初始化方法***********");28

29 }30

31 }

FirstFilter.java

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

1 packagefilter;2

3 importjava.io.IOException;4

5 importjavax.servlet.Filter;6 importjavax.servlet.FilterChain;7 importjavax.servlet.FilterConfig;8 importjavax.servlet.ServletException;9 importjavax.servlet.ServletRequest;10 importjavax.servlet.ServletResponse;11

12 public class SecondFilter implementsFilter {13

14 public voiddestroy() {15 System.out.println("*********过滤器2----->销毁方法*******");16 }17

18 public voiddoFilter(ServletRequest request, ServletResponse response,19 FilterChain filterChain) throwsIOException, ServletException {20 System.out.println("*******开始执行过滤器2----->doFilter方法*********");21 filterChain.doFilter(request, response);22 System.out.println("*******结束执行过滤器2----->doFilter方法**********");23 }24

25 public void init(FilterConfig arg0) throwsServletException {26 System.out.println("*******执行过滤器2------>初始化方法***********");27 }28

29 }

SecondFilter.java

在web.xml中配置两个过滤器(第一个过滤器在前面,两个过滤器都匹配index.jsp)

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

1 <?xml version="1.0" encoding="UTF-8"?>

2

3 xmlns="http://java.sun.com/xml/ns/javaee"

4 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

5 xsi:schemaLocation="http://java.sun.com/xml/ns/javaee6 http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">

7

8

9 index.jsp

10

11

12

13

14

15 FirstFilter

16 filter.FirstFilter

17

18

19 FirstFilter

20 /index.jsp

21

22

23

24 SecondFilter

25 filter.SecondFilter

26

27

28 SecondFilter

29 /index.jsp

30

31

32

33

web.xml

在index.jsp中我们打印如下的一句话: System.out.println("******** 这是index.jsp,处理过程完成 *********");

运行结果:

4cce98d2ed30b0f156395e1b16d4a4cb.gif

过滤器的分类:

Servlet 2.5中将过滤器分为4种,如下图所示:

ef1a02376f5ea08996ff13df18720052.png

1.REQUEST过滤器

新建一个过滤器FirstFilter(在web.xml中配置两个过滤地址index.jsp和main.jsp):

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

1 <?xml version="1.0" encoding="UTF-8"?>

2

3 xmlns="http://java.sun.com/xml/ns/javaee"

4 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

5 xsi:schemaLocation="http://java.sun.com/xml/ns/javaee6 http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">

7

8

9 index.jsp

10

11

12

13

14 FirstFilter

15 filter.FirstFilter

16

17

18 FirstFilter

19 /index.jsp

20 REQUEST

21

22

23 FirstFilter

24 /main.jsp

25 REQUEST

26

27

28

29

web.xml

在FirstFilter的doFilter方法中将页面重定向到main.jsp

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

1 packagefilter;2

3 importjava.io.IOException;4

5 importjavax.servlet.Filter;6 importjavax.servlet.FilterChain;7 importjavax.servlet.FilterConfig;8 importjavax.servlet.ServletException;9 importjavax.servlet.ServletRequest;10 importjavax.servlet.ServletResponse;11 importjavax.servlet.http.HttpServletRequest;12 importjavax.servlet.http.HttpServletResponse;13

14 public class FirstFilter implementsFilter {15

16 public voiddestroy() {17 System.out.println("*********过滤器1----->销毁方法*******");18

19 }20

21 public voiddoFilter(ServletRequest request, ServletResponse response,22 FilterChain filterChain) throwsIOException, ServletException {23

24 HttpServletRequest req =(HttpServletRequest) request;25 HttpServletResponse res =(HttpServletResponse) response;26

27 System.out.println("*******开始执行过滤器1----->doFilter方法*********");28 res.sendRedirect(req.getContextPath() + "/main.jsp");//重定向

29 System.out.println("*******结束执行过滤器1----->doFilter方法**********");30 }31

32 public void init(FilterConfig arg0) throwsServletException {33 System.out.println("*******执行过滤器1------>初始化方法***********");34

35 }36

37 }

FirstFilter.java

启动服务器:

013c765ef24a5bee661c46b5f1c35947.gif

79132f9631bceabc0decfc8ca7ff7fd0.png

当我们访问index.jsp的时候,过滤器将页面重定向到main.jsp——相当于我们又重新请求了main.jsp,main.jsp又会遇到过滤器,如此页面不停重定向到main.jsp,产生了死循环不会输出任何内容!

换一种方式,我们在过滤器中使用服务器内部转发的方式将页面转发到main.jsp(main.jsp向页面打印"这是main.jsp")。

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

1 packagefilter;2

3 importjava.io.IOException;4

5 importjavax.servlet.Filter;6 importjavax.servlet.FilterChain;7 importjavax.servlet.FilterConfig;8 importjavax.servlet.ServletException;9 importjavax.servlet.ServletRequest;10 importjavax.servlet.ServletResponse;11 importjavax.servlet.http.HttpServletRequest;12 importjavax.servlet.http.HttpServletResponse;13

14 public class FirstFilter implementsFilter {15

16 public voiddestroy() {17 System.out.println("*********过滤器1----->销毁方法*******");18

19 }20

21 public voiddoFilter(ServletRequest request, ServletResponse response,22 FilterChain filterChain) throwsIOException, ServletException {23

24 HttpServletRequest req =(HttpServletRequest) request;25 HttpServletResponse res =(HttpServletResponse) response;26

27 System.out.println("*******开始执行过滤器1----->doFilter方法*********");28 req.getRequestDispatcher("main.jsp").forward(request, response);//使用服务器内部转发

29 System.out.println("*******结束执行过滤器1----->doFilter方法**********");30 }31

32 public void init(FilterConfig arg0) throwsServletException {33 System.out.println("*******执行过滤器1------>初始化方法***********");34

35 }36

37 }

FirstFilter.java

运行结果:

1a232e3592e3f0e2cee3b956cdd875a3.gif

2.FORWARD过滤器

将main.jsp的过滤规则改为FORWARD。

1 ……2

3 FirstFilter

4 /main.jsp

5 FORWARD

6

7 ……

重新访问index.jsp

c4374c1e5d6a9bdc2670f4b878234821.gif

3.INCLUDE过滤器

INCLUDE和FORWARD过滤器的使用类似,对应的jsp动作是include。

4.ERROR过滤器

例如我们访问一个错误的页面时,系统会给出一个错误,用户看不懂这个错误是什么概念——我们需要给出一些人性化的提示。

以下是没有在web.xml中配置错误页,用户访问一个不存在的页面:

ba9f0f264765aca12e702892e8f5460a.png

在web.xml中配置错误页:

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

1 <?xml version="1.0" encoding="UTF-8"?>

2

3 xmlns="http://java.sun.com/xml/ns/javaee"

4 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

5 xsi:schemaLocation="http://java.sun.com/xml/ns/javaee6 http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">

7

8

9 index.jsp

10

11

12

13

14 404

15 /error.jsp

16

17

18

web.xml

在web.xml中配置404错误的页面为error.jsp则当用户访问一个不存在的页面时将会将error.jsp中的内容输出(以人性化的方式提示用户):

5d7c09c0b8af6256d7477d99789a9e1c.png

当页面出现错误或者异常的时候,ERROR过滤器可以将错误或者异常捕捉到,系统会记录下错误的信息,程序员就可以查找错误的来源。

新建一个ErrorFilter,并在web.xml中进行如下配置:

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

1

2

3 404

4 /error.jsp

5

6 ……7

8 ErrorFilter

9 filter.ErrorFilter

10

11

12 ErrorFilter

13 /error.jsp

14 ERROR

15

16 ……

web.xml

错误过滤器ErrorFilter

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

1 packagefilter;2

3 importjava.io.IOException;4

5 importjavax.servlet.Filter;6 importjavax.servlet.FilterChain;7 importjavax.servlet.FilterConfig;8 importjavax.servlet.ServletException;9 importjavax.servlet.ServletRequest;10 importjavax.servlet.ServletResponse;11

12 public class ErrorFilter implementsFilter {13

14 public voiddestroy() {15

16 }17

18 public voiddoFilter(ServletRequest request, ServletResponse response,19 FilterChain filterChain) throwsIOException, ServletException {20 System.out.println("检测到错误信息!");21 filterChain.doFilter(request, response);//注意打印错误后要放行,不然页面不会显示

22 }23

24 public void init(FilterConfig filterConfig) throwsServletException {25

26 }27

28 }

ErrorFilter.java

0433c736f0c4486b82ed9b7e8f629ea6.png

J2EE5默认的web.xml是Servlet 2.5,J2EE6默认的web.xml是Servlet 3.0【支持异步处理】。

异步处理:如果在过滤器的doFilter()方法中页面跳转到了一个Servlet用于业务的处理,加入Servlet处理的业务时间花费很多,这时过滤器就会一直等待Servlet执行完成。这样用户体验就会非常差。Servlet 3.0支持异步处理。

在Servlet中新加入了@WebFilter Annotation。该Annotation用于将一个类声明为过滤器,该注解将会在部署时被容器处理,容器将根据具体的属性配置相应的类,将响应的类部署为过滤器。——因此我们不需要在web.xml中配置过滤器,只需要用注解的方式。@WebFilter的常用属性如下:

8dfed6b6845303a9f480fd813fa7c905.png

下面使用J2EE6.0创建一个Web项目,创建一个过滤器名称为AsyncFilter,使用@WebFilter Annotation配置该过滤器(PS:可以不再web.xml中注册该过滤器):

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

1 packagefilter;2

3 importjava.io.IOException;4

5 importjavax.servlet.DispatcherType;6 importjavax.servlet.Filter;7 importjavax.servlet.FilterChain;8 importjavax.servlet.FilterConfig;9 importjavax.servlet.ServletException;10 importjavax.servlet.ServletRequest;11 importjavax.servlet.ServletResponse;12 importjavax.servlet.annotation.WebFilter;13

14 @WebFilter(filterName = "AsyncFilter", value = { "/servlet/AsyncServlet" }, asyncSupported = true, dispatcherTypes ={15 DispatcherType.ASYNC, DispatcherType.REQUEST })16 public class AsyncFilter implementsFilter {17

18 @Override19 public voiddestroy() {20 System.out.println("***** 销毁AsyncFilter *****");21 }22

23 @Override24 public voiddoFilter(ServletRequest request, ServletResponse response,25 FilterChain filterChain) throwsIOException, ServletException {26 System.out.println("***** 开始AsyncFilter *****");27 filterChain.doFilter(request, response);//放行

28 System.out.println("***** 结束AsyncFilter *****");29 }30

31 @Override32 public void init(FilterConfig filterConfig) throwsServletException {33 System.out.println("***** 初始化AsyncFilter *****");34 }35

36 }

AsyncFilter.java

创建一个处理业务的Servlet(该Servlet在doGet方法中使用了线程的休眠方法休眠了10s模拟业务的花费时间)

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

1 packageservlet;2

3 importjava.io.IOException;4 importjava.util.Date;5

6 importjavax.servlet.AsyncContext;7 importjavax.servlet.ServletException;8 importjavax.servlet.http.HttpServlet;9 importjavax.servlet.http.HttpServletRequest;10 importjavax.servlet.http.HttpServletResponse;11

12 public class AsyncServlet extendsHttpServlet {13

14 public class Excutor implementsRunnable{15 privateAsyncContext context;16 publicExcutor(AsyncContext context) {17 this.context =context;18 }19

20 @Override21 public voidrun() {22 //执行相关的复杂业务

23 try{24 Thread.sleep(1000*10);//休眠10s25 //context.getRequest();26 //context.getResponse();

27 System.out.println("业务完成执行时间:"+newDate());28 } catch(InterruptedException e) {29 e.printStackTrace();30 }31 }32

33 }34

35 publicAsyncServlet() {36 super();37 }38

39 public voiddestroy() {40 super.destroy(); //Just puts "destroy" string in log

41 }42

43 public voiddoGet(HttpServletRequest request, HttpServletResponse response)44 throwsServletException, IOException {45

46 AsyncContext context = request.startAsync(); //HttpServletRequest对象开始异步方法47 //context.getRequest();48 //context.getResponse();

49

50 System.out.println("Servlet执行开始时间:"+newDate());51 new Thread(newExcutor(context)).start();52 request.getRequestDispatcher("/index.jsp").forward(request, response);53 System.out.println("Servlet执行结束时间:"+newDate());54 }55

56 public voiddoPost(HttpServletRequest request, HttpServletResponse response)57 throwsServletException, IOException {58

59 doGet(request, response);60 }61

62 public void init() throwsServletException {63

64 }65

66 }

AsyncServlet.java

编写好异步处理业务的Servlet类之后一定要在web.xml中配置该Servlet启用异步,如下图所示:

92661d3e11e9abed4fe8a0708b4a0ffc.png

在index.jsp中有一个链接指向AsyncServlet:

/servlet/AsyncServlet">点击跳转到AsyncServlet处理业务

运行结果:

d3a9376480f999593f150ed6fe4918a0.png

过滤器在实际项目中的应用场景

81242b39edbb0aa66380bb2e139a2f16.png

用户身份的验证

例如现在有一个web项目,登陆页login.jsp将用户名和密码提交给LoginServlet处理,Servlet使用request.getParameter方法获得表单中的用户名和密码,将用户名和密码进行验证,验证成功则页面重定向到success.jsp,显示登陆成功和登录的用户名【保存在session中再从session中取出】;如果登录失败则重定向到failure.jsp。

在不使用过滤器的情况下,即使用户不进行登录也可以访问到success.jsp——任何人都可以访问到success.jsp,这显然来说不安全。

验证用户身份的Servlet(验证用户名和密码都是admin):

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

1 packageservlet;2

3 importjava.io.IOException;4

5 importjavax.servlet.ServletException;6 importjavax.servlet.http.HttpServlet;7 importjavax.servlet.http.HttpServletRequest;8 importjavax.servlet.http.HttpServletResponse;9 importjavax.servlet.http.HttpSession;10

11 public class LoginServlet extendsHttpServlet {12

13 publicLoginServlet() {14 super();15 }16

17 public voiddestroy() {18 super.destroy(); //Just puts "destroy" string in log

19 }20

21 public voiddoPost(HttpServletRequest request, HttpServletResponse response)22 throwsServletException, IOException {23 String username = request.getParameter("username");24 String password = request.getParameter("password");25

26 if ("admin".equals(username)&&"admin".equals(password)) {27 //验证通过

28 HttpSession session =request.getSession();29 session.setAttribute("username", username);//把用户名放入session中

30 response.sendRedirect(request.getContextPath()+"/success.jsp");31 }else{32 //验证失败

33 response.sendRedirect(request.getContextPath()+"/failure.jsp");34 }35 }36

37 public void init() throwsServletException {38

39 }40

41 }

LoginServlet.java

如下图所示:

7ebd39f5d6b089bf7fedcdd84d2e684d.png

现在我们要做这样一件事:只有用户登录成功才可以访问到success.jsp,反之跳转到登录界面。即:不允许未登录用户访问success.jsp。

创建一个登录校验的过滤器LoginFilter并在web.xml中配置该过滤器的url为success.jsp

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

1 packageservlet;2

3 importjava.io.IOException;4

5 importjavax.servlet.ServletException;6 importjavax.servlet.http.HttpServlet;7 importjavax.servlet.http.HttpServletRequest;8 importjavax.servlet.http.HttpServletResponse;9 importjavax.servlet.http.HttpSession;10

11 public class LoginServlet extendsHttpServlet {12

13 publicLoginServlet() {14 super();15 }16

17 public voiddestroy() {18 super.destroy(); //Just puts "destroy" string in log

19 }20

21 public voiddoPost(HttpServletRequest request, HttpServletResponse response)22 throwsServletException, IOException {23 String username = request.getParameter("username");24 String password = request.getParameter("password");25

26 if ("admin".equals(username)&&"admin".equals(password)) {27 //验证通过

28 HttpSession session =request.getSession();29 session.setAttribute("username", username);//把用户名放入session中

30 response.sendRedirect(request.getContextPath()+"/success.jsp");31 }else{32 //验证失败

33 response.sendRedirect(request.getContextPath()+"/failure.jsp");34 }35 }36

37 public void init() throwsServletException {38

39 }40

41 }

LoginFilter.java

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

1 <?xml version="1.0" encoding="UTF-8"?>

2

3 xmlns="http://java.sun.com/xml/ns/javaee"

4 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

5 xsi:schemaLocation="http://java.sun.com/xml/ns/javaee6 http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">

7

8

9 This is the description of my J2EE component

10 This is the display name of my J2EE component

11 LoginServlet

12 servlet.LoginServlet

13

14

15

16 LoginServlet

17 /servlet/LoginServlet

18

19

20 index.jsp

21

22

23 LoginFilter

24 filter.LoginFilter

25

26

27 LoginFilter

28 /success.jsp

29

30

web.xml

加入过滤器之后(只有成功登录的用户【session中保存了该用户的用户名】才可以访问index.jsp):

89afdc0e6a5b83b0b372b571a28cabd9.gif

在实际的开发中一个网站的页面成百上千,这时我们可以使用通配符"/*"来匹配所有的url。但是这样带来一个问题:

当我们新建立一个session的时候,访问任何页面都会被重定向到login.jsp,login.jsp自己也重定向到login.jsp,这样就形成了重定向循环

436ba7eebe52b0e5be3aa547a62deea7.gif

这时就需要在过滤器中判断页面是否是login.jsp,如果是login.jsp或者请求的是LoginServlet就直接放行。在LoginFilter的doFilter方法中添加这样几行代码:

1 if (req.getRequestURI().indexOf("login.jsp")!=-1||req.getRequestURI().indexOf("LoginServlet")!=-1) {2 filterChain.doFilter(request, response); //如果用户请求的是login.jsp直接放行

3 return; //这一行代码一定要加上啊!

4 }

运行结果:

a536a88cba6f15b84c4478c88e441494.gif

上述程序看似已经没有问题,但是还存在一个小bug,当我们在登陆页输入一个错误的用户名和密码页面并不会重定向到failure.jsp而是重定向到了login.jsp。如下图所示:

3a06db057e75411ca857fd133adf478d.gif

这是因为虽然我们在Servlet验证失败的时候将页面重定向到了failure.jsp,failure.jsp又被过滤器重定向到了login.jsp【因为过滤规则为所有的页面,并且session中没有用户名】

这时我们就会发现我们在doFilter中需要例外的页面越来越多(登陆页面、成功页面、失败页面、错误页面……)。为了减轻工作的复杂度,我们可以使用过滤器的init方法中的FilterConfig对象。

1.在web.xml中配置不过滤页面的初始化参数:

dd4976b85072b9efe32037e76af90c1d.png

2.  在过滤方法中使用以上初始化参数。

1 public class LoginFilter implementsFilter{2

3 private FilterConfig filterConfig;//声明一个FilterConfig对象

4

5 public void init(FilterConfig filterConfig) throwsServletException {6 this.filterConfig = filterConfig; //初始化方法的时候给filterConfig赋值

7 }8

9 public voiddestroy() {10

11 }12

13 public voiddoFilter(ServletRequest request, ServletResponse response,14 FilterChain filterChain) throwsIOException, ServletException {15 //代码省略

16 }17

18 }

3. 在doFilter方法中使用FilterConfig对象获得初始化参数。

1 public voiddoFilter(ServletRequest request, ServletResponse response,2 FilterChain filterChain) throwsIOException, ServletException {3 HttpServletRequest req =(HttpServletRequest) request;4 HttpServletResponse res =(HttpServletResponse) response;5 HttpSession session =req.getSession();6

7 String noLoginPaths = filterConfig.getInitParameter("noLoginPaths");8 if (noLoginPaths!=null&&noLoginPaths.length()>0) {9 String[]temp = noLoginPaths.split(";");10 for(String string : temp) {11 if (string==null||"".equals(string)) {12 continue;13 }14 //例外的URL,如果符合这些URL就直接放行

15 if (req.getRequestURI().indexOf(string)!=-1) {16 filterChain.doFilter(request, response); //如果用户请求的是login.jsp直接放行

17 return; //这一行代码一定要加上啊!

18 }19 }20 }21

22 if (session.getAttribute("username")!=null) {23 filterChain.doFilter(request, response); //如果用户已经登录则放行

24 }else{25 res.sendRedirect("login.jsp");26 }27 }

这样就完成了一个比较完整的登录验证。

编码转换

以上面的登录页面为例,在处理登录页的LoginServlet中我们将用户提交的用户名打印出来:

1 public voiddoPost(HttpServletRequest request, HttpServletResponse response)2 throwsServletException, IOException {3 String username = request.getParameter("username");4 System.out.println("用户提交的用户名是:" +username);5

6 }

4acec50f4a234cb5b309a203268e66a0.gif

后台的输出出现了乱码!

已知的2种处理乱码的方式:

1 String username = request.getParameter("username");2

3 request.setCharacterEncoding("utf-8"); //【方式1】修改请求的编码方式

4 new String(username.getBytes("iso-8859-1"),"utf-8") //【方式2】使用特定编码重新构建字符串

除此之外,还可以使用过滤器解决以上问题。

在过滤器的doFilter方法的第一行代码加上以下代码:

request.setCharacterEncoding("utf-8");

这样一次设置就可以让该网站的所有页面都不会乱码(因为请求总是先到达过滤器)。但是为了更好地完成服务器的配置,我们一般在过滤器的初始化参数里配置字符集:

c90e56c30211998b67a9bb37c9a18858.png

然后在doFilter方法中这样调用:

1 public class LoginFilter implementsFilter{2

3 private FilterConfig filterConfig;//声明一个FilterConfig对象

4

5 public voiddestroy() {6

7 }8

9 public voiddoFilter(ServletRequest request, ServletResponse response,10 FilterChain filterChain) throwsIOException, ServletException {11

12 String charset = filterConfig.getInitParameter("charset");13 if (charset == null) {14 charset = "utf-8"; //如果没有指定字符集,默认是utf-8

15 }16 request.setCharacterEncoding(charset); //从初始化参数里面获得字符集17

18 //代码省略

19

20 }21

22 public void init(FilterConfig filterConfig) throwsServletException {23 this.filterConfig = filterConfig; //初始化方法的时候给filterConfig赋值

24 }25

26 }

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值