Spring拦截器

一.应用场景

  权限检查:如是否已经登陆,或则对某些数据具备增删改查等权限;html

  日志记录:能够记录请求信息的日志,以便进行信息监控,信息统计等;java

  性能监控:慢日志等。web

二.拦截器接口

  1.处理器拦截器(HandlerIntercepto):

public interface HandlerInterceptor {

   /**
     * 预处理回调方法,实现处理器的预处理(如检查登录),第三个参数为响应的处理器,自定义Controller
     * 返回值:true表示继续流程(如调用下一个拦截器或处理器);false表示流程中断(如登陆检查失败),不会继续调用其余的拦截器或处理器,此时咱们须要经过response来产生响应;
   */
    boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
            throws Exception;

   /**
     * 后处理回调方法,实现处理器的后处理(但在渲染视图以前),此时咱们能够经过modelAndView(模型和视图对象)对模型数据进行处理或对视图进行处理,modelAndView也可能为null。
   */
    void postHandle(
            HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView)
            throws Exception;

   /**
    * 整个请求处理完毕回调方法,即在视图渲染完毕时回调,如性能监控中咱们能够在此记录结束时间并输出消耗时间,还能够进行一些资源清理,相似于try-catch-finally中的finally,但仅调用处理器执行链中
   */
    void afterCompletion(
            HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
            throws Exception;

}

 

  2.拦截适配器(初始化了HandlerIntercepto的相应方法,不用都实现):

    若是只须要实现三个回调方法中的某些方法,能够继承该抽象类,该抽象类至关于对HandlerIntercepto进行简单实现。如记录日志,须要在程序跑完后,记录相应的增删改查,只需实现afterConcurrentHandlingStarted()方法。spring

    注:该拦截器中多了一个afterConcurrentHandlingStarted()方法,该方法用于处理异步请求,当Controller中有异步请求方法的时候会触发该方法时,异步请求先支持preHandle、而后执行afterConcurrentHandlingStarted。异步线程完成以后执行preHandle、postHandle、afterCompletion。session

public abstract class HandlerInterceptorAdapter implements AsyncHandlerInterceptor {

    /**
     * 默认是true
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
            throws Exception {

        return true;
    }

    /**
     * This implementation is empty.
     */
    @Override
    public void postHandle(
            HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView)
            throws Exception {
    }

    /**
     * This implementation is empty.
     */
    @Override
    public void afterCompletion(
            HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
            throws Exception {
    }

    /**
     * 不是HandlerInterceptor的接口实现,是AsyncHandlerInterceptor的,AsyncHandlerInterceptor实现了HandlerInterceptor
     */
    @Override
    public void afterConcurrentHandlingStarted(
            HttpServletRequest request, HttpServletResponse response, Object handler)
            throws Exception {
    }

}

 三.拦截器运行流程

  1.流程顺序:

    1.1拦截器执行顺序按照Spring配置文件中定义的顺序执行;mvc

    1.2首先按照执行顺序执行全部拦截器的preHandle()方法【用于预处理等】,若是遇到返回值是false,则不会执行还未执行的拦截器,而是直接倒序执行afterCompletion()方法,若是为true,则依次执行剩下的拦截器;app

    1.3若是全部拦截器的preHandle()方法返回值都为true,则执行相应的控制层接口(controller),若是在该接口中有异常抛出,则和preHandle()方法返回false同样,不会执行postHandle(),而是直接倒序执行afterCompletion()方法;异步

    1.4若是接口(controller)中业务逻辑执行完成(页面还未渲染数据),会倒序执行postHandle()方法,渲染完数据后,而后倒序执行afterCompletton()方法。ide

  2.运行流程图:

    2.1正常流程(均执行):

    2.2preHandle返回false:

 

四.相关配置及实现

  1.自定义拦截器类实现:

    1.1是否登陆:

package com.swpu.o2o.interceptor.shopadmin;

import java.io.PrintWriter;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

import com.swpu.o2o.entity.PersonInfo;
/**
 * 管理系统拦截器
 * @author ASUS
 *
 */
public class ShopLoginInterceptor extends HandlerInterceptorAdapter{

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
            throws Exception {
        //从session中取出用户信息
        Object userObj=request.getSession().getAttribute("user");
        if(userObj!=null){
            //若用户信息不为空则将session里的用户信息转换成PersonInfos实体类对象
            PersonInfo user=(PersonInfo)userObj;
            if(user!=null&&user.getUserId()!=null&&user.getUserId()>0&&user.getEnableStatus()==1){
                //若经过验证则返回true,拦截器返回true,控制层业务执行
                return true;
            }
            
        }
        //若不满验证,则直接跳转到登陆界面
        PrintWriter out=response.getWriter();
        out.println("<html>");
        out.println("<script>");
        out.println("window.open ('" + request.getContextPath()
        + "/local/login?usertype=2','_self')");
        out.println("</script>");
        out.println("<html>");
        return false;
    }
    
}

 

    1.2是否有操做权限:

package com.swpu.o2o.interceptor.shopadmin;

import java.util.List;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

import com.swpu.o2o.entity.Shop;

public class ShopPermissionInterceptor extends HandlerInterceptorAdapter{
    /**
     * 在控制层执行业务前进行用户操做权限拦截
     */
    @Override
    public boolean preHandle(HttpServletRequest request,
            HttpServletResponse response, Object handler) throws Exception {
        //从session获取当前选择的店铺
        Shop currentShop = (Shop) request.getSession().getAttribute(
                "currentShop");
        @SuppressWarnings("unchecked")
        //从session中获取当前用户可操做的d店铺列表
        List<Shop> shopList = (List<Shop>) request.getSession().getAttribute(
                "shopList");
        //非空判断
        if (currentShop != null && shopList != null) {
            //遍历可操做的店铺列表
            for (Shop shop : shopList) {
                //若是当前店铺在可操做的列表则返回true,进行接下来操做
                if (shop.getShopId() == currentShop.getShopId()) {
                    return true;
                }
            }
        }
        //不知足验证,返回false
        return false;
    }
}

 

 

  2.配置文件:

<!-- 5.权限拦截器 -->
    <mvc:interceptors>
        <!-- 校验是否登陆了该管理系统的拦截器 -->
        <mvc:interceptor>
            <!-- 定义拦截的路由,shopadmin包下的全部Controller -->
            <mvc:mapping path="/shopadmin/**" />
            <!-- 拦截方法 -->
            <bean class="com.swpu.o2o.interceptor.shopadmin.ShopLoginInterceptor"
                id="ShopInterceptor" />
        </mvc:interceptor>
        <!-- 校验是否对该店铺有操做权限的拦截器 -->
        <mvc:interceptor>
            <!-- 须要拦截的接口 -->
            <mvc:mapping path="/shopadmin/**" />
            <!-- shoplist page -->
            <!-- 排除该包下的某些接口不拦截 -->
            <mvc:exclude-mapping path="/shopadmin/shoplist" />
            <mvc:exclude-mapping path="/shopadmin/getshoplist" />
            <!-- shopmanage page -->
            <mvc:exclude-mapping path="/shopadmin/shopmanagement" />
            <mvc:exclude-mapping path="/shopadmin/getshopmanagementinfo" />
            <!-- shopregister page -->
            <mvc:exclude-mapping path="/shopadmin/getshopinitinfo" />
            <mvc:exclude-mapping path="/shopadmin/shopoperation" />
            <mvc:exclude-mapping path="/shop/registershop" />
            <bean class="com.swpu.o2o.interceptor.shopadmin.ShopPermissionInterceptor"
                id="ShopPermissionInterceptor" />
        </mvc:interceptor>
    </mvc:interceptors>
相关文章
相关标签/搜索