拦截器 订阅
拦截器(Interceptor),主要完成请求参数的解析、将页面表单参数赋给值栈中相应属性、执行功能检验、程序异常调试等工作。 [1] 展开全文
拦截器(Interceptor),主要完成请求参数的解析、将页面表单参数赋给值栈中相应属性、执行功能检验、程序异常调试等工作。 [1]
信息
外文名
Interceptor
领    域
计算机与信息科学 [2]
中文名
拦截器
应    用
java [2]
拦截器简介
拦截器(Interceptor)是Struts2框架的核心功能之一,Struts 2是一个基于MVC设计模式的开源框架, [3]  主要完成请求参数的解析、将页面表单参数赋给值栈中相应属性、执行功能检验、程序异常调试等工作。Struts2拦截器是一种可插拔策略,实现了面向切面的组件开发,当需要扩展功能时,只需要提供对应拦截器,并将它配置在Struts2容器中即可,如果不需要该功能时,也只需要在配置文件取消该拦截器的设置,整个过程不需要用户添加额外的代码。拦截器中更为重要的概念即拦截器栈(Interceptor Stack),拦截器栈就是Struts2中的拦截器按一定的顺序组成的一个线性链,页面发出请求,访问Action对象或方法时,栈中被设置好的拦截器就会根据堆栈的原理顺序的被调用。 [1] 
收起全文
精华内容
下载资源
问答
  • Spring Boot 拦截器

    万次阅读 多人点赞 2016-01-12 09:21:48
    Web开发中,我们除了使用 Filter 来过滤请web求外,还可以使用Spring提供的HandlerInterceptor(拦截器)。HandlerInterceptor 的功能跟过滤器类似,但是提供更精细的的控制能力:在request被响应之前、request被...

    上一篇对过滤器的定义做了说明,也比较简单。过滤器属于Servlet范畴的API,与Spring 没什么关系。
    Web开发中,我们除了使用 Filter 来过滤请web求外,还可以使用Spring提供的HandlerInterceptor(拦截器)。

    HandlerInterceptor 的功能跟过滤器类似,但是提供更精细的的控制能力:在request被响应之前、request被响应之后、视图渲染之前以及request全部结束之后。我们不能通过拦截器修改request内容,但是可以通过抛出异常(或者返回false)来暂停request的执行。

    实现 UserRoleAuthorizationInterceptor 的拦截器有:
    ConversionServiceExposingInterceptor
    CorsInterceptor
    LocaleChangeInterceptor
    PathExposingHandlerInterceptor
    ResourceUrlProviderExposingInterceptor
    ThemeChangeInterceptor
    UriTemplateVariablesHandlerInterceptor
    UserRoleAuthorizationInterceptor

    其中 LocaleChangeInterceptor 和 ThemeChangeInterceptor 比较常用。

    配置拦截器也很简单,Spring 为什么提供了基础类WebMvcConfigurerAdapter ,我们只需要重写 addInterceptors 方法添加注册拦截器。

    实现自定义拦截器只需要3步:
    1、创建我们自己的拦截器类并实现 HandlerInterceptor 接口。
    2、创建一个Java类继承WebMvcConfigurerAdapter,并重写 addInterceptors 方法。
    2、实例化我们自定义的拦截器,然后将对像手动添加到拦截器链中(在addInterceptors方法中添加)。
    PS:本文重点在如何在Spring-Boot中使用拦截器,关于拦截器的原理请大家查阅资料了解。

    代码示例:

    MyInterceptor1.java

    package org.springboot.sample.interceptor;
    
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    import org.springframework.web.servlet.HandlerInterceptor;
    import org.springframework.web.servlet.ModelAndView;
    
    /**
     * 自定义拦截器1
     *
     * @author   单红宇(365384722)
     * @myblog  http://blog.csdn.net/catoop/
     * @create    2016年1月7日
     */
    public class MyInterceptor1 implements HandlerInterceptor {
    
    	@Override
    	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
    			throws Exception {
    		System.out.println(">>>MyInterceptor1>>>>>>>在请求处理之前进行调用(Controller方法调用之前)");
    		
    		return true;// 只有返回true才会继续向下执行,返回false取消当前请求
    	}
    
    	@Override
    	public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
    			ModelAndView modelAndView) throws Exception {
    		System.out.println(">>>MyInterceptor1>>>>>>>请求处理之后进行调用,但是在视图被渲染之前(Controller方法调用之后)");
    	}
    
    	@Override
    	public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
    			throws Exception {
    		System.out.println(">>>MyInterceptor1>>>>>>>在整个请求结束之后被调用,也就是在DispatcherServlet 渲染了对应的视图之后执行(主要是用于进行资源清理工作)");
    	}
    
    }
    
    

    MyInterceptor2.java

    package org.springboot.sample.interceptor;
    
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    import org.springframework.web.servlet.HandlerInterceptor;
    import org.springframework.web.servlet.ModelAndView;
    
    /**
     * 自定义拦截器2
     *
     * @author   单红宇(365384722)
     * @myblog  http://blog.csdn.net/catoop/
     * @create    2016年1月7日
     */
    public class MyInterceptor2 implements HandlerInterceptor {
    
    	@Override
    	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
    			throws Exception {
    		System.out.println(">>>MyInterceptor2>>>>>>>在请求处理之前进行调用(Controller方法调用之前)");
    		
    		return true;// 只有返回true才会继续向下执行,返回false取消当前请求
    	}
    
    	@Override
    	public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
    			ModelAndView modelAndView) throws Exception {
    		System.out.println(">>>MyInterceptor2>>>>>>>请求处理之后进行调用,但是在视图被渲染之前(Controller方法调用之后)");
    	}
    
    	@Override
    	public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
    			throws Exception {
    		System.out.println(">>>MyInterceptor2>>>>>>>在整个请求结束之后被调用,也就是在DispatcherServlet 渲染了对应的视图之后执行(主要是用于进行资源清理工作)");
    	}
    
    }
    
    

    MyWebAppConfigurer.java

    package org.springboot.sample.config;
    
    import org.springboot.sample.interceptor.MyInterceptor1;
    import org.springboot.sample.interceptor.MyInterceptor2;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
    import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
    
    @Configuration
    public class MyWebAppConfigurer 
    		extends WebMvcConfigurerAdapter { // 这里注意,在spring 5.0之后 WebMvcConfigurerAdapter 过时了,可以直接实现接口 implements WebMvcConfigurer(下面实现的方法是一样的)
    
    	@Override
    	public void addInterceptors(InterceptorRegistry registry) {
    		// 多个拦截器组成一个拦截器链
    		// addPathPatterns 用于添加拦截规则
    		// excludePathPatterns 用户排除拦截
    		registry.addInterceptor(new MyInterceptor1()).addPathPatterns("/**");
    		registry.addInterceptor(new MyInterceptor2()).addPathPatterns("/**");
    		super.addInterceptors(registry);
    	}
    
    }
    
    

    然后在浏览器输入地址: http://localhost:8080/index 后,控制台的输出为:

    >>>MyInterceptor1>>>>>>>在请求处理之前进行调用(Controller方法调用之前)
    >>>MyInterceptor2>>>>>>>在请求处理之前进行调用(Controller方法调用之前)
    >>>MyInterceptor2>>>>>>>请求处理之后进行调用,但是在视图被渲染之前(Controller方法调用之后)
    >>>MyInterceptor1>>>>>>>请求处理之后进行调用,但是在视图被渲染之前(Controller方法调用之后)
    >>>MyInterceptor2>>>>>>>在整个请求结束之后被调用,也就是在DispatcherServlet 渲染了对应的视图之后执行(主要是用于进行资源清理工作)
    >>>MyInterceptor1>>>>>>>在整个请求结束之后被调用,也就是在DispatcherServlet 渲染了对应的视图之后执行(主要是用于进行资源清理工作)
    

    根据输出可以了解拦截器链的执行顺序(具体原理介绍,大家找度娘一问便知)

    最后强调一点:只有经过DispatcherServlet 的请求,才会走拦截器链,我们自定义的Servlet 请求是不会被拦截的,比如我们自定义的Servlet地址 http://localhost:8080/xs/myservlet 是不会被拦截器拦截的。并且不管是属于哪个Servlet 只要复合过滤器的过滤规则,过滤器都会拦截。

    最后说明下,我们上面用到的 WebMvcConfigurerAdapter 并非只是注册添加拦截器使用,其顾名思义是做Web配置用的,它还可以有很多其他作用,通过下面截图便可以大概了解,具体每个方法都是干什么用的,留给大家自己研究(其实都大同小异也很简单)。
    这里写图片描述

    展开全文
  • 配置图文,超详细!!SpringMVC拦截器Interceptor详解,多个拦截器的执行顺序,拦截器进行权限判断和日志记录,拦截器和过滤器的区别

    SpringMVC拦截器

      Interceptor拦截器,是SpringMVC提供用来拦截发送给Controller层方法请求的拦截器。类似于filter 主要进行记录日志,判断用户是否登录,过滤权限(没有登录就跳转登录之类的)
      拦截器和我们所学的过滤器是很相似的,只是范围不一样。

    • 过滤器filter:是JavaEE提供的用来拦截所有的请求,进行过滤,它主要用于实现编码过滤,进行统一编码,防止乱码。
    • 拦截器interceptor:主要用来拦截Controller控制器的方法,一般用于拦截Controller层,满足条件才放行,主要用于实现权限分配,不满足条件不能访问一些界面(比如登录才能进入)。

    【注意】一般请求都是先通过过滤器filter过滤,才会被拦截器interceptor处理,决定是否放行,两个过程有任何一个不放行,都不能访问到Controller层方法。

    1. 过滤器和拦截器的大概执行流程【***】

    在这里插入图片描述

    2. 拦截器的三个方法

    1. boolean preHandle():在访问controller方法之前执行,返回为true才会去执行Controller方法,返回false,就被拦截了,原路打回(主要做权限控制,有权限才放行)。
    2. void postHandle():在执行controller方法之后执行jsp页面之前执行该方法,可以向作用域中放入数据,影响jsp展示效果,(可以在执行jsp之前做渲染)
    3. void afterCompletion在jsp页面渲染完成之后执行,(主要用于记录日志,资源释放
      ,
      【注意小知识点来啦】如果preHadle返回true,但是没有找到对应的Controller,是不会执行postHandle方法哦。

    差不多就是这样的模板

    public class MyInterceptor implements HandlerInterceptor {
    
    //    在访问controller方法之前执行
        @Override
        public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
            //prehandle:访问controller之前执行,返回true 继续访问controller。
            System.out.println("\n----------AuthInterceptor 【preHandle】--------------");
            return true;//返回false就不再继续执行controller方法
        }
    
    //    如果没有controller就不执行postHandle方法
        @Override
        public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
    		//posthandle:在执行controller方法之后, 执行jsp之前执行该方法,可以向作用域中放入数据,影响jsp展示效果,(可以执行jsp之前做渲染)
            System.out.println("----------AuthInterceptor 【postHandle】-------------- ");
        }
    
        @Override
        public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
            //afterCompletion:在jsp渲染之后执行,用于记录日志,资源释放
            System.out.println("----------AuthInterceptor 【afterCompletion】--------------");
    
    		//记录日志  向文件里面写日志
            String logdir = request.getServletContext().getRealPath("log");//获取服务器记录日志log文件所存放的目录位置 -- tomcat下的真实路径+log目录
            //路径不存在就创建
            Path logdirPath = Paths.get(logdir);
            if(Files.notExists(logdirPath)){
                Files.createDirectories(logdirPath);
            }
            //目录存在就将数据[字符]写入
            Path logfile = Paths.get(logdir,"userlog.log");//存放日志的路径+文件名
            BufferedWriter writer = new BufferedWriter(new FileWriter(logfile.toFile(),true));//logfile.toFile() paths转换为File类型 true以追加的方式写入
    		
    		//获取登录用户信息
            Users user = (Users)request.getSession().getAttribute("user");
            String username = user.getUsername();
            //记录user登录时间,存入日志
            String message = username+" 登录时间:"+new Date();
            writer.write(message+"\r\n");
            writer.flush();
            writer.close();
        }
    }
    

    3. 多个拦截器的执行顺序

    如果所有拦截器都通过(都不拦截)执行顺序是这样的:
    (都执行的话,preHandle顺序执行,postHandler逆序执行,最后再afterCompletion逆序执行)
    在这里插入图片描述
    如果拦截器1拦截(也就是preHandle1返回false),那么后面的拦截器也不执行,直接原路打回。
    在这里插入图片描述
    如果拦截器3拦截,那么也不执行controller方法,大概是这样的。
    在这里插入图片描述


    4. SpringMVC拦截器的配置

    4.1 自定义拦截器,实现HandlerInterceptor接口

    //实现一个接口HandlerInterceptor
    public class Demo01Interceptor  implements HandlerInterceptor {
        public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
            System.out.println("preHandle");
            return true;//放行执行controller
        }
    
        public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        
        }
    
        public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
    
        }
    }
    

    4.2 springmvc.xml配置拦截器

    配置多个拦截器

    <!-- /** 是拦截所有的请求   path="/interceptor"只拦截interceptor路径-->
         <mvc:interceptors>
             <mvc:interceptor>
             	<!-- /**拦截所有请求,配置全局拦截器 -->
                 <mvc:mapping path="/**"/>
                 <bean class="com.xgf.springmvc.ajax.interceptor.AuthInterceptor"/>
             </mvc:interceptor>
             <mvc:interceptor>
             	<!-- /interceptor 之拦截interceptor该路径 -->
                 <mvc:mapping path="/interceptor"/>
                 <bean class="com.xgf.springmvc.ajax.interceptor.AuthInterceptor1"/>
             </mvc:interceptor>
         </mvc:interceptors>
    

    5. 案例:用户权限拦截器和日志记录

    有些页面只有用户登录才能访问,未登录不能访问。

    5.1 案例图解【***】

    在这里插入图片描述
    浏览器进行访问,想去购物车模块/订单模块需要先进行用户登录,用户权限拦截器进行判断用户登录没有,登录成功,放行,可以访问。未登录,拦截,跳转登录界面。

    5.2 用户权限拦截器UserAuthInterceptor

    作用:判断访问路径,如果访问的是order订单模块或者cart购物车模块.就需要判断用户是否登录,读取session中的用户信息,未登录强制跳转到登入页面,登录就放行,进入相应页面

    public class UserAuthInterceptor implements HandlerInterceptor {
        public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
            System.out.println("UserAuthInterceptor preHandle------------------------");
            User user = (User) request.getSession().getAttribute("user");
            if(user == null){//未登录才判断,登录了直接放行
                String address = request.getRequestURI();//获取路径
                System.out.println("address = "+address);
                //是购物车或者订单页面,就直接跳转登录界面
                if(address.contains("order")||address.contains("cart")){
    	            //强制到登录页面
                    response.sendRedirect(request.getContextPath() + "/login.jsp");
                    //设置为false,不访问controller
                    return false;
                }
            }
            //其它模块或者已经登录,就直接放行
            return true;
        }
    
        public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
            System.out.println("UserAuthInterceptor postHandle------------------------");
        }
    
        public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
            System.out.println("UserAuthInterceptor afterCompletion------------------------");
            
    		//记录日志  向文件里面写日志
            String logdir = request.getServletContext().getRealPath("log");//获取服务器记录日志log文件所存放的目录位置 -- tomcat下的真实路径+log目录
            //路径不存在就创建
            Path logdirPath = Paths.get(logdir);
            if(Files.notExists(logdirPath)){
                Files.createDirectories(logdirPath);
            }
            //目录存在就将数据[字符]写入
            Path logfile = Paths.get(logdir,"userlog.log");//存放日志的路径+文件名
            BufferedWriter writer = new BufferedWriter(new FileWriter(logfile.toFile(),true));//logfile.toFile() paths转换为File类型 true以追加的方式写入
    		
    		//获取登录用户信息
            Users user = (Users)request.getSession().getAttribute("user");
            String username = user.getUsername();
            //记录user登录时间,存入日志
            String message = username+" 登录时间:"+new Date();
            writer.write(message+"\r\n");
            writer.flush();
            writer.close();
        }
    }
    
    

    5.3 OrderController订单controller

    订单模块

    @Controller
    @RequestMapping("/toOrder")
    public class OrderController {
        @RequestMapping(path = "/orderInfo.action",method = {RequestMethod.GET,RequestMethod.POST})
        public String query(Integer id){
            System.out.println("订单信息");
            return "order";
        }
    }
    

    5.4 CartController购物车controller

    购物车模块

    @Controller
    @RequestMapping("/toCart")
    public class OrderController {
        @RequestMapping(path = "/cartInfo.action",method = {RequestMethod.GET,RequestMethod.POST})
        public String query(Integer id){
            System.out.println("购物车信息");
            return "cart";
        }
    }
    

    5.5 springmvc中配置拦截器

       <!--配置用户权限拦截器-->
        <mvc:interceptors>
            <!--用于测试的拦截器-->
            <mvc:interceptor>
                <!--拦截路径的配置 /**拦截所有请求 -->
                <mvc:mapping path="/**"/>
                <bean id="interceptor1" class="com.xgf.interceptor.UserAuthInterceptor"/>
            </mvc:interceptor>
    	<!-- 可以配置多个拦截器,继续用mvc:interceptor-->
        </mvc:interceptors>
    

    大佬们,画图不容易啊,给个关注给个赞呗,感谢感谢=

    展开全文
  • 前端路由的基本原理、使用 history 路由模式时后端登录拦截器的配置、Vuex 的引入以及前端拦截器的实现。

    前言

    这一篇主要讲前端路由与登录拦截器的实现。放在一起讲是因为我在开发登录拦截器时因为这个路由的问题遇到了很多坑,花费了很长时间,网上的解决方案都不怎么靠谱,综合了好几种办法才最终成功,其实关于这个部分能写两三篇文章,名字起好了还能多很多访问量,不过为了保证文章的质量我没有这么做,毕竟我不是大神,如果再不用点心,写出来的文章自己都不想再看第二遍,更别提能对大家有所帮助了。

    一、前端路由

    大家如果留心观察就会发现,之前我们做的页面的 URL 里有一个 # 号,这个 # 号有什么含义呢?

    假设在 html 中有这么一段代码:<div id="test">This is a test</div>,如果我们想让页面定位到这个 div 所在的位置,可以加一个超链接 <a herf="#test">Jump to test</a>,这里的 # 被称为“锚点”,点击超链接,可以发现网页的 URL 发生了变化,但页面并不会跳转。

    在互联网流量如此庞大的今天,我们需要想办法后端服务器的压力,利用 AJAX,我们可以不重载页面就刷新数据,如果再加上 # 号的特性(即改变 URL 却不请求后端),我们就可以在前端实现页面的整体变化,而不用每次都去请求后端。

    为了实现前端路由,我们可以监听 # 号后面内容的变化(hashChange),从而动态改变页面内容。URL 的 # 号后面的地址被称为 hash ,估计是哪个大神拍脑袋想的,不用深究。这种实现方式我们称之为 Hash 模式,是非常典型的前端路由方式。

    另一种常用的方式被称为 History 模式,这种方式使用了 History APIHistory API 顾名思义就是针对历史记录的 API ,这种模式的原理是先把页面的状态保存到一个对象(state)里,当页面的 URL 变化时找到对应的对象,从而还原这个页面。其实原本人家这个功能是为了方便浏览器前进后退的,不得不说程序员们的脑洞真大。使用了这种模式,就可以摆脱 # 号实现前端路由。

    Vue 已经为我们提供了两种模式的前端路由,无需我们自己去实现。

    二、使用 History 模式

    首先我们把 Vue 中配置的路由从默认的 hash 模式切换为 histroy 模式。打开我们的前端项目 wj-vue,修改 router\index.js,加入 mode: 'history 这句话。整体代码如下:

    import Vue from 'vue'
    import Router from 'vue-router'
    import AppIndex from '@/components/home/AppIndex'
    import Login from '@/components/Login'
    
    Vue.use(Router)
    
    export default new Router({
      mode: 'history',
      routes: [
        {
          path: '/login',
          name: 'Login',
          component: Login
        },
        {
          path: '/index',
          name: 'AppIndex',
          component: AppIndex
        }
      ]
    })
    

    运行项目,访问不加 # 号的 http://localhost:8080/login ,成功加载页面。

    接下来,我们把前端打包后部署在后端。这不是前后端分离项目推荐的做法,之前我们讲过其实应该把前后端分别部署在不同的服务器中,但实际上仍有不少项目会选择把前后端整合在一起,只使用一个服务器,所以这里我们也提及一下这种方式,但在之后的开发中不会这样部署。

    先在项目目录执行 npm run build,控制台输出如下内容表明执行完毕:
    在这里插入图片描述
    这时在项目的 dist 文件夹下生成了 static 文件夹和 index.html 文件,把这两个文件,拷贝到我们后端项目的 wj\src\main\resources\static 文件夹下,一定要注意这个位置,这时后端配置的静态文件的 path,虽然看起来很诡异,但一般都不作修改。
    在这里插入图片描述
    接下来,打开后端项目并运行,访问 http://localhost:8443/index.html ,(注意输入后缀 .html)发现页面是空白的,但确实取到了这个页面,再访问 http://localhost:8443/login ,发现跳转到了错误页面(White Error Page)。
    在这里插入图片描述
    这里我们回顾一下单页面应用的概念,在我们这个项目中,其实只有 index.html 这一个页面,所有的其它内容都是在这个页面里动态渲染的。当我们直接在后端访问 /login 路径时,服务器会后端并没有这个路径对应的内容,所以返回了 Error Page。

    为了获取到我们需要的内容,我们要想办法触发前端路由,即在后端添加处理内容,把 通过这个 URL 渲染出的 index.html 返回到浏览器。

    在后端项目中新建一个 package 名为 error,新建实现 ErrorPageRegistrar 接口的类 ErrorConfig,把默认的错误页面设置为 /index.html,代码如下

    package com.evan.wj.error;
    
    import org.springframework.boot.web.server.ErrorPageRegistrar;
    import org.springframework.boot.web.server.ErrorPage;
    import org.springframework.boot.web.server.ErrorPageRegistry;
    import org.springframework.http.HttpStatus;
    import org.springframework.stereotype.Component;
    
    @Component
    public class ErrorConfig implements ErrorPageRegistrar {
    
        @Override
        public void registerErrorPages(ErrorPageRegistry registry) {
            ErrorPage error404Page = new ErrorPage(HttpStatus.NOT_FOUND, "/index.html");
            registry.addErrorPages(error404Page);
        }
    
    }
    

    重新启动项目,访问 http://localhost:8443/login ,成功进入登录页面。

    三、后端登录拦截器

    为了完善登录功能,我们需要限制未登录状态下对核心功能页面的访问。登录拦截可以由多种方式来实现,我们首先讲解后端拦截器的开发。(注意如果没有把前后端项目整合起来,就没有办法使用这种方式)

    一个简单拦截器的逻辑如下:

    1.用户访问 URL,检测是否为登录页面,如果是登录页面则不拦截
    2.如果用户访问的不是登录页面,检测用户是否已登录,如果未登录则跳转到登录页面

    1.LoginController

    首先我们修改 LoginController 的内容。之前我们实现了通过查询数据库验证用户名是否正确,但仅此而已。

    为了保存登录状态,我们可以把用户信息存在 Session 对象中(当用户在应用程序的 Web 页之间跳转时,存储在 Session 对象中的变量不会丢失),这样在访问别的页面时,可以通过判断是否存在用户变量来判断用户是否登录。这是一种比较简单的方式,感兴趣的同学可以尝试别的方法。

    修改后的代码内容如下:

    package com.evan.wj.controller;
    
    import com.evan.wj.pojo.User;
    import com.evan.wj.result.Result;
    import com.evan.wj.service.UserService;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.*;
    import org.springframework.web.util.HtmlUtils;
    
    import javax.servlet.http.HttpSession;
    
    @Controller
    public class LoginController {
    
        @Autowired
        UserService userService;
    
        @CrossOrigin
        @PostMapping(value = "/api/login")
        @ResponseBody
        public Result login(@RequestBody User requestUser, HttpSession session) {
            String username = requestUser.getUsername();
            username = HtmlUtils.htmlEscape(username);
    
            User user = userService.get(username, requestUser.getPassword());
            if (null == user) {
                return new Result(400);
            } else {
                session.setAttribute("user", user);
                return new Result(200);
            }
        }
    }
    
    

    其实只是添加了一条语句 session.setAttribute("user", user);

    2.LoginInterceptor

    新建 package 名为 interceptor,新建类 LoginInterceptor

    Interceptor 即拦截器,在 Springboot 我们可以直接继承拦截器的接口,然后实现 preHandle 方法。preHandle 方法里的代码会在访问需要拦截的页面时执行。

    代码如下:

    package com.evan.wj.interceptor;
    
    import com.evan.wj.pojo.User;
    import org.apache.commons.lang.StringUtils;
    import org.springframework.web.servlet.HandlerInterceptor;
    
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import javax.servlet.http.HttpSession;
    
    public class LoginInterceptor  implements HandlerInterceptor{
    
        @Override
        public boolean preHandle (HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception {
            HttpSession session = httpServletRequest.getSession();
            String contextPath=session.getServletContext().getContextPath();
            String[] requireAuthPages = new String[]{
                    "index",
            };
    
            String uri = httpServletRequest.getRequestURI();
    
            uri = StringUtils.remove(uri, contextPath+"/");
            String page = uri;
    
            if(begingWith(page, requireAuthPages)){
                User user = (User) session.getAttribute("user");
                if(user==null) {
                    httpServletResponse.sendRedirect("login");
                    return false;
                }
            }
            return true;
        }
    
        private boolean begingWith(String page, String[] requiredAuthPages) {
            boolean result = false;
            for (String requiredAuthPage : requiredAuthPages) {
                if(StringUtils.startsWith(page, requiredAuthPage)) {
                    result = true;
                    break;
                }
            }
            return result;
        }
    }
    
    

    看起来似乎比较长,其实就是判断 session 中是否存在 user 属性,如果存在就放行,如果不存在就跳转到 login 页面。这里使用了一个路径列表(requireAuthPages),可以在里面写下需要拦截的路径。当然我们也可以拦截所有路径,那样就不用写这么多了,但会有逻辑上的问题,就是你访问了 \login 页面,仍然会需要跳转,这样就会引发多次重定向问题。

    3.WebConfigurer

    我们写完了拦截器,但是它却并不会生效,因为我们还没有把它配置到项目中。

    新建 package 名为 config,新建类 MyWebConfigurer,代码如下:

    package com.evan.wj.config;
    
    import com.evan.wj.interceptor.LoginInterceptor;
    import org.springframework.boot.SpringBootConfiguration;
    import org.springframework.context.annotation.Bean;
    import org.springframework.web.servlet.config.annotation.*;
    
    @SpringBootConfiguration
    public class MyWebConfigurer implements WebMvcConfigurer {
    
        @Bean
        public LoginInterceptor getLoginIntercepter() {
            return new LoginInterceptor();
        }
    
        @Override
        public void addInterceptors(InterceptorRegistry registry){
            registry.addInterceptor(getLoginIntercepter()).addPathPatterns("/**").excludePathPatterns("/index.html");
        }
    }
    
    

    通过这个配置类,我们添加了之前写好的拦截器。这里有一句非常重要的语句,即

    registry.addInterceptor(getLoginIntercepter()).addPathPatterns("/**").excludePathPatterns("/index.html");
    

    这条语句的作用是对所有路径应用拦截器,除了 /index.html

    之前我们在拦截器 LoginInterceptor 中配置的路径,即 index,触发的时机是在拦截器生效之后。也就是说,我们访问一个 URL,会首先通过 Configurer 判断是否需要拦截,如果需要,才会触发拦截器 LoginInterceptor,根据我们自定义的规则进行再次判断。

    /index/index.html 是不同的,也就是说 /index 会触发拦截器而 /index.html 不会,但根据拦截器 LoginInterceptor 中我们定义的判断条件,以 /index 开头的路径都会被转发,包括 index.html

    因为我们做的是单页面应用,之前通过配置 ErrorPage,实际上访问所有路径都会重定向到 /index.html 。我们直接在浏览器地址栏输入 /index 会触发拦截器,经过拦截器重定向到 /login,然后 /login 再经过 Configurer 的判断,再次触发拦截器,由于不在需要拦截的路径中,所以被放行,页面则重新定向到了 /index.html,如果没有再 Configurer 中取消对 /index.html 的拦截,则会再次触发拦截器,再次重定向到 /login,引发如下错误。
    在这里插入图片描述
    上述过程比较绕,这是我开发时的失误,但我觉得恰好可以帮助大家理解拦截器与单页面应用,所以保留了下来。

    4.效果检验

    运行后端项目,访问 http://localhost:8443/index ,发现页面自动跳转到了 http://localhost:8443/login ,输入用户名和密码登录,跳转到 http://localhost:8443/index , 这时可以把浏览器标签关掉,再在一个新标签页输入 http://localhost:8443/index ,发现不会被拦截。

    四、Vuex 与前端登录拦截器

    前面我们使用了后端拦截器,但这种拦截器只有在将前后端项目整合在一起时才能生效,而前后端分离的项目实际上不推荐这么做,接下来我们尝试用前端实现相似的功能。

    实现前端登录器,需要在前端判断用户的登录状态。我们可以像之前那样在组件的 data 中设置一个状态标志,但登录状态应该被视为一个全局属性,而不应该只写在某一组件中。所以我们需要引入一个新的工具——Vuex,它是专门为 Vue 开发的状态管理方案,我们可以把需要在各个组件中传递使用的变量、方法定义在这里。之前我一直没有使用它,所以在不同组件传值的问题上十分头疼,要写很多多余的代码来调用不同组件的值,所以推荐大家从一开始就去熟悉这种管理方式。

    1.引入 Vuex

    在我们的项目文件夹中,运行 npm install vuex --save,之后,在 src 目录下新建一个文件夹 store,并在该目录下新建 index.js 文件,在该文件中引入 vue 和 vuex,代码如下:

    import Vue from 'vue'
    import Vuex from 'vuex'
    
    Vue.use(Vuex)
    

    之后,我们在 index.js 里设置我们需要的状态变量和方法。为了实现登录拦截器,我们需要一个记录用户信息的变量。为了方便日后的扩展(权限认证等),我们使用一个用户对象而不是仅仅使用一个布尔变量。同时,设置一个方法,触发这个方法时可以为我们的用户对象赋值。完整的代码如下:

    import Vue from 'vue'
    import Vuex from 'vuex'
    
    Vue.use(Vuex)
    
    export default new Vuex.Store({
      state: {
        user: {
          username: window.localStorage.getItem('user' || '[]') == null ? '' : JSON.parse(window.localStorage.getItem('user' || '[]')).username
        }
      },
      mutations: {
        login (state, user) {
          state.user = user
          window.localStorage.setItem('user', JSON.stringify(user))
        }
      }
    })
    

    这里我们还用到了 localStorage,即本地存储,在项目打开的时候会判断本地存储中是否有 user 这个对象存在,如果存在就取出来并获得 username 的值,否则则把 username 设置为空。这样我们只要不清除缓存,登录的状态就会一直保存。

    2.修改路由配置

    为了区分页面是否需要拦截,我们需要修改一下 src\router\index.js,在需要拦截的路由中加一条元数据,设置一个 requireAuth 字段如下:

        {
          path: '/index',
          name: 'AppIndex',
          component: AppIndex,
          meta: {
            requireAuth: true
          }
        }
    

    完整的 index.js 代码如下:

    import Vue from 'vue'
    import Router from 'vue-router'
    import AppIndex from '@/components/home/AppIndex'
    import Login from '@/components/Login'
    
    Vue.use(Router)
    
    export default new Router({
      mode: 'history',
      routes: [
        {
          path: '/login',
          name: 'Login',
          component: Login
        },
        {
          path: '/index',
          name: 'AppIndex',
          component: AppIndex,
          meta: {
            requireAuth: true
          }
        }
      ]
    })
    
    

    3.使用钩子函数判断是否拦截

    钩子函数及在某些时机会被调用的函数。这里我们使用 router.beforeEach(),意思是在访问每一个路由前调用。

    打开 src\main.js ,首先添加对 store 的引用

    import store from './store'
    

    并修改 Vue 对象里的内容

    new Vue({
      el: '#app',
      render: h => h(App),
      router,
      // 注意这里
      store,
      components: { App },
      template: '<App/>'
    })
    

    接着写 beforeEach() 函数

    router.beforeEach((to, from, next) => {
        if (to.meta.requireAuth) {
          if (store.state.user.username) {
            next()
          } else {
            next({
              path: 'login',
              query: {redirect: to.fullPath}
            })
          }
        } else {
          next()
        }
      }
    )
    

    这个的逻辑很简单,首先判断访问的路径是否需要登录,如果需要,判断 store 里有没有存储 user 的信息,如果存在,则放行,否则跳转到登录页面,并存储访问的页面路径(以便在登录后跳转到访问页)。

    完整的 main.js 代码如下:

    import Vue from 'vue'
    import App from './App'
    import router from './router'
    import store from './store'
    import ElementUI from 'element-ui'
    import 'element-ui/lib/theme-chalk/index.css'
    
    var axios = require('axios')
    axios.defaults.baseURL = 'http://localhost:8443/api'
    Vue.prototype.$axios = axios
    Vue.config.productionTip = false
    
    Vue.use(ElementUI)
    
    router.beforeEach((to, from, next) => {
        if (to.meta.requireAuth) {
          if (store.state.user.username) {
            next()
          } else {
            next({
              path: 'login',
              query: {redirect: to.fullPath}
            })
          }
        } else {
          next()
        }
      }
    )
    
    /* eslint-disable no-new */
    new Vue({
      el: '#app',
      render: h => h(App),
      router,
      store,
      components: { App },
      template: '<App/>'
    })
    
    

    4.修改 Login.vue

    之前的登录组件中,我们只是判断后端返回的状态码,如果是 200,就重定向到首页。在经过前面的配置后,我们需要修改一下登录逻辑,以最终实现登录拦截。

    修改后的逻辑如下:

    1.点击登录按钮,向后端发送数据
    2.受到后端返回的成功代码时,触发 store 中的 login() 方法,把 loginForm 对象传递给 store 中的 user 对象
    (*这里只是简单的实现,在后端我们可以通过用户名和密码查询数据库,获得 user 表的完整信息,比如用户昵称、用户级别等,返回前端,并传递给 user 对象,以实现更复杂的功能)
    3.获取登录前页面的路径并跳转,如果该路径不存在,则跳转到首页

    修改后的 login() 方法如下:

    login () {
      var _this = this
      console.log(this.$store.state)
      this.$axios
        .post('/login', {
          username: this.loginForm.username,
          password: this.loginForm.password
        })
        .then(successResponse => {
          if (successResponse.data.code === 200) {
            // var data = this.loginForm
            _this.$store.commit('login', _this.loginForm)
            var path = this.$route.query.redirect
            this.$router.replace({path: path === '/' || path === undefined ? '/index' : path})
          }
        })
        .catch(failResponse => {
        })
    }
    

    完整的 Login.vue 代码如下:

    <template>
      <body id="poster">
        <el-form class="login-container" label-position="left"
                 label-width="0px">
          <h3 class="login_title">系统登录</h3>
          <el-form-item>
            <el-input type="text" v-model="loginForm.username"
                      auto-complete="off" placeholder="账号"></el-input>
          </el-form-item>
          <el-form-item>
            <el-input type="password" v-model="loginForm.password"
                      auto-complete="off" placeholder="密码"></el-input>
          </el-form-item>
          <el-form-item style="width: 100%">
            <el-button type="primary" style="width: 100%;background: #505458;border: none" v-on:click="login">登录</el-button>
          </el-form-item>
        </el-form>
      </body>
    </template>
    
    <script>
    
      export default {
        name: 'Login',
        data () {
          return {
            loginForm: {
              username: 'admin',
              password: '123'
            },
            responseResult: []
          }
        },
        methods: {
          login () {
            var _this = this
            console.log(this.$store.state)
            this.$axios
              .post('/login', {
                username: this.loginForm.username,
                password: this.loginForm.password
              })
              .then(successResponse => {
                if (successResponse.data.code === 200) {
                  // var data = this.loginForm
                  _this.$store.commit('login', _this.loginForm)
                  var path = this.$route.query.redirect
                  this.$router.replace({path: path === '/' || path === undefined ? '/index' : path})
                }
              })
              .catch(failResponse => {
              })
          }
        }
      }
    </script>
    
    <style>
      #poster {
        background:url("../assets/eva.jpg") no-repeat;
        background-position: center;
        height: 100%;
        width: 100%;
        background-size: cover;
        position: fixed;
      }
      body{
        margin: 0px;
      }
      .login-container {
        border-radius: 15px;
        background-clip: padding-box;
        margin: 90px auto;
        width: 350px;
        padding: 35px 35px 15px 35px;
        background: #fff;
        border: 1px solid #eaeaea;
        box-shadow: 0 0 25px #cac6c6;
      }
      .login_title {
        margin: 0px auto 40px auto;
        text-align: center;
        color: #505458;
      }
    
    </style>
    
    

    5.效果检验

    同时运行前后端项目,访问 http://localhost:8080/index ,发现页面直接跳转到了 http://localhost:8080/login?redirect=%2Findex

    在这里插入图片描述
    输入账号密码后登录,成功跳转到 http://localhost:8080/index ,之后再次访问则无需登录(除非清除缓存)。


    最后吐槽两句,人呐,真是不能乱立 flag,写第一篇文章的时候,我说感谢老板不让我 996,然后就 895 了,上一篇文章我说这两天闲,多写几篇文章,然后就又接了个大项目,周末还在出差开会,昨天晚上忙到 12 点困得不行,想着先睡觉早上早点起来再把工作收个尾,结果酒店隔壁房间一群小孩儿在玩狼人杀,回想起我们过去同样的行径,这口气我忍了。。。

    所以读者大人们请原谅我没有及时更新,作为一个不知名博主,十分感谢大家的支持。我会坚持下去的,希望大家都能坚持做自己想做的事,一起变得更加牛批!

    查看系列文章目录:
    https://learner.blog.csdn.net/article/details/88925013

    上一篇:Vue + Spring Boot 项目实战(五):使用 Element 辅助前端开发

    下一篇: Vue + Spring Boot 项目实战(七):导航栏与图书页面设计

    展开全文
  • 拦截器

    千次阅读 2010-03-24 22:37:00
    拦截器可以拦截SessionBean和Message-drivenBean的方法调用或生命周期事件。拦截器用于封装应用的公用行为,使这些行为与业务逻辑分离。拦截器可以使同一bean类中的方法或者是一个外部类。HelloChinaBeanimport ...

    拦截器可以拦截Session BeanMessage-driven Bean的方法调用或生命周期事件。拦截器用于封装应用的公用行为,使这些行为与业务逻辑分离。拦截器可以使同一bean类中的方法或者是一个外部类。

    HelloChinaBean


    @Interceptors注释指定一个或多个在外部类中定义的拦截器,多个拦截器用逗号隔开。

     

    上面拦截器HelloInterceptorHelloChinaBean的所有方法进行拦截。如果你只需对某一方法拦截,你可以在方法上面定义拦截器,如:


    拦截器HelloInterceptor.java


    @AroundInvoke注释指定了要用作拦截器的方法,拦截器方法与被拦截的业务方法执行同一个java调用堆栈、同一个事务和安全上下文中。用@AroundInvoke注释指定的方法必须遵守以下格式:

    public Object XXX(javax.interceptor.InvocationContext ctx) throws Exception

    下面是javax.interceptor.InvocationContext封装了客户端所调用业务方法的一些信息。


    getTarget() 指向被调用的bean实例

    getMethod() 指向被拦截的业务方法

    getParameters() 获取被拦截业务方法的参数

    setParameters() 设置被拦截业务方法的参数

    getContextData() 返回一个Map对象,它在整个方法调用期间都可以被访问到。位于同一个方法调用内的不同拦截器之间可以利用它来传递上下文相关的数据。

    HelloInterceptor代码中,我们调用了ctx.proceed()方法。如果还有其他拦截器未执行,ctx.proceed()方法内部会调用后面拦截器的@AroundInvoke方法。直到后面的拦截器全部执行结束,EJB容器才会执行被拦截的业务方法。另外如果我们想在被拦截的业务方法执行结束后再执行一些自定义的代码,我们可以在ctx.proceed()执行后方法返回前加入自己的代码。


    由于拦截器和被拦截的bean方法同处于一个java调用堆栈中,如果你希望终止方法执行,可以抛出异常。业务方法也告结束。

     

     

     

     

     

     

     

     

     

     

    展开全文
  • SpringBoot之HandlerInterceptor拦截器的使用 ——(一)

    万次阅读 多人点赞 2018-08-15 14:06:37
    拦截器我想大家都并不陌生,最常用的登录拦截、或是权限校验、或是防重复提交、或是根据业务像12306去校验购票时间,总之可以去做很多的事情。 1、定义实现类 定义一个Interceptor 非常简单方式也有几种,...
  • Springboot 拦截器链 - 加载拦截器

    千次阅读 2018-04-01 17:30:39
    Springboot 拦截器链 - 加载拦截器 1.创建拦截器 // 创建拦截器需要实现 HandlerInterceptor 接口 @Slf4j public class HandleInterceptorImpl implements HandlerInterceptor{ @Override public boolean...
  • Mybatis拦截器

    万次阅读 多人点赞 2019-04-16 22:31:18
    一 Mybatis拦截器介绍        Mybatis拦截器设计的初衷就是为了供用户在某些时候可以实现自己的逻辑而不必去动Mybatis固有的逻辑。通过Mybatis拦截器我们可以拦截某些方法的调用,我们可以选择...
  • 请问谁有Struts2拦截器学习的详细资料,请问谁有Struts2拦截器学习的详细资料,感谢哈
  • SpringBoot使用拦截器

    万次阅读 多人点赞 2020-12-22 15:52:56
    拦截器对使用SpringMvc、的开发人员来说特别熟悉,因为你只要想去做好一个项目必然会用到它。拦截器在我们平时的项目中用处有很多,如:日志记录、用户登录状态拦截、安全拦截等等。而SpringBoot内部集成的是...
  • Struts2拦截器原理 Struts2拦截器是在访问某个Action或Action的方法之前或之后实施拦截。在请求Struts2的Action时,Struts2会查找配置文件,并根据配置文件实例化相应的拦截器对象。Struts2拦截器配置 struts.xml...
  • 之前记录了SpringBoot中使用过滤器,其实拦截器和过滤器从功能上来说,拦截器/过滤器所能实现的功能过滤器/拦截器都能够实现。但是过滤器是java实现的,它需要依赖于Servlet容器,而拦截器是SprignMVC实现的一个机制...
  • 请求拦截器和响应拦截器

    千次阅读 2019-11-21 21:36:46
    请求拦截器 请求拦截器的作用是在请求发送前进行一些操作,例如在每个请求体里加上token,统一做了处理如果以后要改也非常容易。 关于拦截,这里只说原理,前端的请求,最终还是离不开 ajax,像vue 的 vue-resource ...
  • 默认拦截器栈与自定义拦截器

    千次阅读 2017-02-28 22:30:21
    默认拦截器栈与自定义拦截器1.在struts-default.xml中定义一个defaultStack拦截器,并将其指定为默认拦截器。 2.只要在定义包的过程中继承struts-default包,那么defaultStack将是默认的拦截器。 3.当为包中的某个...
  • Cxf拦截器

    万次阅读 2017-05-17 08:59:39
    Cxf的拦截器包括入拦截器和出拦截器,所有的入拦截器或出拦截器构成了一个拦截器链,它们可以作用在Server端也可以作用在Client端。当需要使用拦截器链处理消息的时候,Cxf会确保对应的消息被拦截器链里面的每一个...
  • 详述 Spring MVC 框架中拦截器 Interceptor 的使用方法

    万次阅读 多人点赞 2017-03-30 17:02:05
    1 前言 昨天新接了一个需要,“拦截 XXX,然后 OOO”,好吧,说白了就是要用拦截器干点事(实现一个具体的功能)。之前,也在网络上搜了很多关于Interceptor的文章,但感觉内容都大同小异,而且知识点零零散散,不...
  • Spring Boot 拦截器无效,不起作用

    万次阅读 多人点赞 2018-08-10 10:37:49
    导致这个问题可能有两个原因:一个是拦截器写错了,另一个是拦截器配置错了。 1、需求是这样的 拦截所有的api请求,判断其请求头中的secret参数是否正确,正确的请求才能访问api。 2、拦截器配置 需要先写...
  • springboot拦截器

    千次阅读 2021-02-27 21:49:31
    1.什么是拦截器 拦截器(Interceptor)类似于Servlet中的过滤器,主要用于拦截客户请求并做出相应的处理。与过滤器有如下区别: 1.过滤器只能在容器初始化时被调用一次,在action的生命周期中,而拦截器可以多次被...
  • flume拦截器

    万次阅读 2018-09-11 03:02:32
    摘要: 拦截器是简单的插件式组件,设置在source和channel之间。...flume内置了很多拦截器,并且会定期的添加一些拦截器,在这里列出一些flume内置的,经常使用的拦截器。 一、拦截器的种类介绍 1、Timestamp Int...
  • axios的实例拦截器配置不会继承axios全局的拦截器,也就是说axios的instance的拦截器配置时单独服务的,不会被全局拦截器影响。
  • 【WebService】CXF拦截器的设置以及自定义CXF拦截器

    万次阅读 多人点赞 2016-07-31 20:29:22
    我们可以在调用ws服务前设置拦截器,也可以在调用ws服务后设置拦截器,当然了,拦截器也可以添加多个,CXF中有自己内置的拦截器,先来写个简单CXF自带的拦截器实例熟悉一下在CXF中如何添加,然后再来自定义CXF拦截器...
  • SpringMVC 拦截器

    千次阅读 2019-07-08 23:58:17
    1、拦截器 项目目录 类似于Servlet开发中的过滤器Filter,用于对处理器(controller)进行预处理和后处理。用户可以自己定义一些拦截器来实现特定的功能。 拦截器链就是将拦截器按一定顺序联结成一条链。在访问被...
  • angular9拦截器的使用

    万次阅读 2020-07-06 22:10:29
    angular9拦截器的简单使用拦截器统一添加token拦截器使用拦截器实现后的效果参考资料 拦截器统一添加token 我们在做一个后台管理系统时,需要给每个请求的请求头里面添加token,所以下面我们来了解一下angular的拦截器...
  • kafka自定义拦截器|案例实战

    千次阅读 多人点赞 2020-04-29 14:33:01
    本文详细解释kafka的拦截器拦截器链,并根据案例实现两个常见的自定义拦截器并组成拦截链,Talk is cheap,Show me the code
  • 浅谈axios的拦截器

    万次阅读 2021-04-26 09:17:13
    什么是axios?...axios分为请求拦截器和响应拦截器 看名字就可以看出来 请求拦截器是请求之前拦截 响应拦截器是响应完成后拦截 请求拦截器 请求拦截器模板 // 添加一个请求拦截器 axios.intercepto
  • 当配置多个拦截器拦截器1:拦截器2:当没有设置路径的时候,拦截器都会执行到,那么执行顺序为:
  • 如果还没有实现拦截器 可以 点这里 项目中发现拦截器无效 , 访问接口 /user/xxx/xxx 没有进入到拦截器中 @Configuration public class WebConfigurer implements WebMvcConfigurer { @Autowired private ...
  • 内置拦截器 Struts2中内置类许多的拦截器,它们提供了许多Struts2的核心功能和可选的高级特性。这些内置的拦截器在struts-default.xml中配置。只有配置了拦截器拦截器才可以正常的工作和运行。Struts 2已经为您...
  • springboot下使用拦截器和过滤器

    万次阅读 多人点赞 2018-07-01 13:29:06
    1. 拦截器Interceptor Spring MVC的拦截器(Interceptor)和Filter不同,但是也可以实现对请求进行预处理,后处理。先介绍它的使用,只需要两步: 1.1 实现拦截器 实现拦截器可以自定义实现HandlerInterceptor...
  • Spring拦截器

    千次阅读 2021-06-27 23:36:00
    Spring拦截器 1.如何写拦截器 ​ 1.在java类中要实现Handlerinterceptor接口。 ​ 2.在接口方法里面,实现拦截处理逻辑。 2.代码演示 2.1Spring-Mvc.xml配置文件 <!--配置拦截器--> <mvc:interceptors&...
  • springboot的拦截器也是对请求进行的系列验证或处理,关于拦截器和过滤器的区别此文不做介绍,详细可阅读:拦截器与过滤器的区别,下面说一下SSM项目中自定义拦截器的实现。 二、自定义拦截器类,写一个类实现...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 367,994
精华内容 147,197
关键字:

拦截器