【Java基础】采用Filter实现AOP完成统一登录验证

来源:互联网 发布:app开发用什么软件 编辑:程序博客网 时间:2024/04/30 08:41

认识Filter

Servlet API中提供了一个Filter接口,开发web应用时,如果编写的Java类实现了这个接口,则把这个java类称之为过滤器Filter。通过Filter技术,开发人员可以实现用户在访问某个目标资源之前,对访问的请求和响应进行拦截。简单的说,就是Filter可以对Request和Response请求进行拦截。

利用Filter这种机制,可以大大简化开发人员的工作量,比如系统要加入登录验证,在访问其他页面前需要判断用户是否登录,是否存在session,如果不存在则跳转到登录页面。正常实现的话,需要每个页面都加一层判断,造成代码大量重复。采用Filter的话,可以声明一个专门做登陆验证的Filter,在访问任何jsp和servlet之前都会被Filter拦截下来并进行登录验证。这样验证代码只写一份即可。下面以登录验证为例,讲解Filter如何使用。


Filter应用实例

① 声明一个java类,实现Filter接口:

在doFilter方法中完成要做的工作,比如登录验证的逻辑判断。

public class AuthFilter implements Filter {    public void destroy() {        // Filter销毁    }    public void doFilter(ServletRequest request, ServletResponse response,            FilterChain chain) throws IOException, ServletException {        HttpServletRequest req = (HttpServletRequest)request;        HttpServletResponse res = (HttpServletResponse)response;        //如果没有登录        String requestURI = req.getRequestURI().substring(req.getRequestURI().indexOf("/", 1), req.getRequestURI().length());        System.out.println("requestURI=" + requestURI);        //访问除login.jsp(登录页面)和验证码servlet之外的jsp/servlet都要进行验证        if (!"/login.jsp".equals(requestURI) && !"/servlet/AuthImageServlet".equals(requestURI)) {            HttpSession session = req.getSession(false);            //判断session中是否有用户信息,如果没有则重定向到登录页面            if (session == null || session.getAttribute("user_info") == null) {                res.sendRedirect(req.getContextPath() + "/login.jsp");                return;            }        }        //继续访问其他资源        chain.doFilter(req, res);    }    public void init(FilterConfig filterConfig) throws ServletException {        // 初始化方法    }

② 在web.xml配置文件中对Filter进行配置,拦截对象,拦截所有的jsp和servlet。配置和servlet类似。

<filter>    <filter-name>AuthFilter</filter-name>    <filter-class>com.tgb.drp.util.filter.AuthFilter</filter-class></filter><filter-mapping>    <filter-name>AuthFilter</filter-name>    <url-pattern>*.jsp</url-pattern></filter-mapping>    <filter-mapping>    <filter-name>AuthFilter</filter-name>    <url-pattern>/servlet/*</url-pattern></filter-mapping>

完成这两步就实现了Filter的一个基本应用,当用户通过浏览器访问系统的某些资源时,就会对请求进行拦截,判断是否已经通过登录验证。


Filter的应用场景

通过对filter过滤器的了解,可以得知在以下三种情况下可以做些处理:

1. 通过控制chain.doFilter方法是否执行,来决定是否需要访问目标资源。
比如,可以在用户权限验证等等。判断用户是否有访问某些资源的权限,有权限放行,没权限不执行chain.doFilter方法。

2. 通过在调用chain.doFilter方法之前,做些处理来达到某些目的。
比如,解决中文乱码的问题等等。可以在doFilter方法前,执行设置请求编码与响应的编码。甚至可以对request接口进行封装装饰来处理get请求方式的中文乱码问题(重写相应的request.getParameter方法)。

3. 通过在调用chain.doFilter方法之后,做些处理来达到某些目的。
比如,对整个web网站进行压缩。在调用chain.doFilter方法之前用类A对response对象进行封装装饰,重写getOutputStream和重写getWriter方法。在类A内部中,将输出内容缓存进ByteArrayOutputStream流中,然后在chain.doFilter方法执行后,获取类A中ByteArrayOutputStream流缓存数据,用GZIPOutputStream流进行压缩下。


Filter生命周期

和Servlet一样Filter的创建和销毁也是由WEB服务器负责。不过与Servlet的区别是

1. 在应用启动的时候就进行装载Filter类(与Servlet的load-on-startup配置效果相同)。

2. 容器创建好Filter对象实例后,调用init()方法。接着被Web容器保存进应用级的集合容器中去了等待着用户访问资源。

3. 当用户访问的资源正好被Filter的url-pattern拦截时,容器会取出Filter类调用doFilter方法,下次或多次访问被拦截的资源时,Web容器会直接取出指定Filter对象实例调用doFilter方法(Filter对象常驻留Web容器了)。

4. 当应用服务被停止或重新装载了,则会执行Filter的destroy方法,Filter对象销毁。

注意:init方法与destroy方法只会直接一次。



小结

通过上面的实例可以看出,Filter也能够实现AOP的效果,基于拦截器的原理,在访问某个目标资源之前,会对访问的请求和响应进行拦截,然后在偷偷执行一些操作。同样动态代理也能够实现AOP效果,但是动态代理使用时是显示的主动的去调用代理类,从而实现方法的增强。这两种方式相比较而言,使用场景不一样,Filter适用于前台JSP,Servlet;动态代理适用于后台的一些service方法。

0 0