Interceptor

这篇主讲拦截器,在讲拦截器之前,顺便提两句监听器和过滤器。

拦截器、监听器、过滤器

过滤器(Filter):当你有一堆东西的时候,你只希望选择符合你要求的某一些东西。定义这些要求的工具,就是过滤器。
举例:在web.xml中会有很多过滤器,比如字符过滤器;比如对请求方法进行过滤的过滤器等。
拦截器(Interceptor):在一个流程正在进行的时候,你希望干预它的进展,甚至终止它进行,这是拦截器做的事情。
举例:本文下面的代码示例就是一个典型的拦截器例子。
监听器(Listener):当一个事件发生的时候,你希望获得这个事件发生的详细信息,而并不想干预这个事件本身的进程,这就要用到监听器。
举例:在web.xml中有时候会配置这一项 ↓

<listener>  
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>  
</listener>  

<context-param>  
        <param-name>contextConfigLocation</param-name>  
        <param-value>classpath:spring/applicationContext.xml</param-value>  
</context-param>  

诸如此类的监听器。

当然我这么解释肯定无法准确的理解它们之间的区别,所以请移步知乎大神的回答(第一个)

接下来看我的关于拦截器的小demo吧。

代码

Github地址
先看一下项目结构
这里写图片描述

主要讲一下LoginInterceptor类以及SomeUtils类,其他内容去Github上看吧。
首先看SomeUtils.java

@Service
public class SomeUtils {

    public void setCookies(HttpServletResponse response, User user) throws ServletException,IOException{
        System.out.println("Enter setCookie()");
        try{
            String username = user.getName();
            String password = user.getPassword();
            String token = username + "," + password;
            Cookie cookie = new Cookie("user", token);
            cookie.setMaxAge(60 * 2);
            cookie.setPath("/");
            response.addCookie(cookie);
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    public boolean checkCookie(HttpServletRequest request) throws ServletException,IOException{
        System.out.println("Enter checkCookie()");
        boolean flag = false;
        Cookie[] cookies = request.getCookies();
        if(cookies != null){
            for (int i=0; i<cookies.length; i++){
                if(cookies[i].getName().equals("user")){
                    try{
                        String token = cookies[i].getValue();
                        String[] elements = token.split(",");
                        String username = elements[0];
                        String password = elements[1];
                        if(username.equals("admin") && password.equals("key")){
                            flag = true;
                        }
                    }catch (Exception e){
                        e.printStackTrace();
                    }
                }
            }
        }
        return flag;
    }

}

里面实现了两个方法,一个是设置缓存,一个是检查缓存中的值是否正确,这里还是简化了操作,逻辑上可能会有瑕疵。

另一个就是拦截器类LoginInterceptor.java

public class LoginInterceptor implements HandlerInterceptor {

    @Autowired
    private SomeUtils utils;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception{
        boolean flag = utils.checkCookie(request);
        if(!flag) {
            response.sendRedirect("/login");
            return false;
        }
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request,HttpServletResponse response,Object handler,ModelAndView modelAndView) throws Exception {

    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
            throws Exception {
    }

}

在我们自己实现拦截器的时候,我们需要实现接口HandlerInterceptor,然后其中的三个方法分别是:
preHandle,在调用Controller相关方法之前执行,我们看到这个方法有个返回值,因为Interceptor可能有多个,是链式处理,所以如果其中有返回值为false的时候,整个请求就此中断,进入到相应的处理页面。
postHandle,在当前Interceptor中的preHandle返回值为true时才会执行,它的执行时间时Controller方法调用后,视图渲染之前。
afterCompletion,该方法也是需要preHandle方法返回值为true时才会执行,执行时间在视图渲染之后,一般用来清理资源。

拦截器我们定义好了,但是如何使用呢?我们看一下,我们在spring-web.xml中进行了如下对于拦截器的配置:

<!--配置拦截器-->
<mvc:interceptors>
        <mvc:interceptor>
            <mvc:mapping path="/a/**"/>
            <bean class="com.yubotao.interceptor.LoginInterceptor"/>
        </mvc:interceptor>
</mvc:interceptors>

简单解释一下:<mvc:mapping path="/a/**"/>定义了拦截规则,即所有/a开头的url都需要经过拦截器进行处理;然后下面的标签<bean class="com.yubotao.interceptor.LoginInterceptor"/>则定义了该拦截规则使用的拦截器类。

最后运行的结果就是,当第一次直接访问/a/Pass时,会重定向到/login,这时就是拦截器在起作用;然后当登陆的帐密完全正确的时候,才会进入成功界面,这个时候结合cookie的存在,在cookie时限内,可不用再次登陆即可进入/a/Pass的相关页面。

最后补充一句,因为之前有段时间没写java了,导致在进行字符串比较的时候使用了运算符==,这个比较的是两个字符串地址,所以永远不会相等;这时候使用equals()方法,可以避免这个问题,这是因为String类重写了equals()方法,否则和使用==是一样的,这里千万要注意,可能一不小心就会犯这种低级错误。

由于图片不方便演示就不贴图了,有什么地方出现错误,还望知会。

猜你喜欢

转载自blog.csdn.net/ybt_c_index/article/details/79393632