• spring拦截器


    网上查了一下django怎么实现类似spring的拦截器功能,发现这篇关于spring的拦截器写得挺好,转过来。

    原文地址:https://www.cnblogs.com/lyq-biu/p/11017106.html

    Spring拦截器

     

    一.应用场景

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

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

      性能监控:慢日志等。

    二.拦截器接口

      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()方法。

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

    复制代码
    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配置文件中定义的顺序执行;

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

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

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

      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>
    复制代码
  • 相关阅读:
    【转】Eclipse中查看jar包中的源码
    maven No compiler is provided in this environment. Perhaps you are running on a JRE rather than a JDK?
    Android问题-DelphiXE8新建AVD出现“no system images installed for this target”
    Android教程-DelphiXE Android自适应屏幕办法
    教程-在F9后提示内存错误,点击了乎略,之后怎么取消乎略?
    PC问题-该虚拟机似乎正在使用中
    PC问题-(仅供备用)取消磁盘的自动扫描
    Delphi实例-IdTCPServer和IdTCPClient的使用(支持文件发送)
    Android教程-DelphiXE Android的所有权限按照分类总结说明
    C++问题-UniqueAppObject.cpp(147): error C3861: “GUXClientInit”: 找不到标识符
  • 原文地址:https://www.cnblogs.com/linwenbin/p/11389252.html
Copyright © 2020-2023  润新知