相关推荐recommended
一文学会 SpringMVC 拦截器
作者:mmseoamin日期:2024-02-22

一文学会 SpringMVC 拦截器,在这里插入图片描述,第1张

✅作者简介:2022年博客新星 第八。热爱国学的Java后端开发者,修心和技术同步精进。

🍎个人主页:Java Fans的博客

🍊个人信条:不迁怒,不贰过。小知识,大智慧。

💞当前专栏:SSM 框架从入门到精通

✨特色专栏:国学周更-心性养成之路

🥭本文内容:一文学会 SpringMVC 拦截器

文章目录

    • 项目准备
    • 单个拦截器的执行流程
    • 多个拦截器的执行流程
    • 权限拦截器(案例分享)

      一文学会 SpringMVC 拦截器,在这里插入图片描述,第2张

      SpringMVC 的拦截器 Interceptor 的主要用来拦截指定的用户请求,并进行相应的预处理或后处理。它的主要作用是拦截用户的请求并进行相应的处理。比如通过它来进行权限验证,或者是来判断用户是否登录等操作。

      其拦截的时间点是在处理器适配器执行处理器之前。创建拦截器类需要实现 HandlerInterceptor 接口,然后在配置文件中注册并指定拦截目标。

      对于 SpringMVC 拦截器的定义方式有两种:

      • 实现接口: org.springframework.web.servlet.Handlerlnterceptor
      • 继承适配器: org.springframework.web.servethandler.HandlerInterceptorAdapter

        项目准备

        目录结构:

        一文学会 SpringMVC 拦截器,在这里插入图片描述,第3张

        为了便于下面知识结构的讲解,先创建好未使用拦截器的项目,步骤如下:

        【1】创建 spring-config.xml 文件,代码如下:

        
        
            
            
                
                
                
                
            
            
            
        
        

        【2】创建 User 实体类,代码如下:

        package cn.hh.springmvc03.entity;
        import lombok.Data;
        @Data
        public class User {
        	String username;
        	String password;
        }
        

        单个拦截器的执行流程

        项目案例:创建第一个拦截器。

        实现步骤:

        【1】新建处理器 UserController,添加方法如下:

        	//测试拦截器
        	@RequestMapping("/test1.do")
        	public String doTestInterceptor(){
        		System.out.println("执行了处理器的方法!");
        		return "welcome";
        	}
        

        【2】新建包 cn.hh.springmvc03.intercepter,在包下新建一个自定义拦截器类 Intercepter1,实现 HandlerInterceptor 接口,重写以下3个方法,代码如下:

        package cn.hh.springmvc03.intercepter;
        import javax.servlet.http.HttpServletRequest;
        import javax.servlet.http.HttpServletResponse;
        import org.springframework.web.servlet.HandlerInterceptor;
        import org.springframework.web.servlet.ModelAndView;
        public class Intercepter1 implements HandlerInterceptor{
        	@Override
        	public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception arg3)
        			throws Exception {
        		System.out.println("执行了Intercepter1 ----------afterCompletion");
        	}
        	@Override
        	public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView)
        			throws Exception {
        		System.out.println("执行了Intercepter1 ----------postHandle");
        	}
        	@Override
        	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        		System.out.println("执行了Intercepter1 ----------preHandle");
        		return true;
        	}
        }
        

        自定义拦截器,需要实现HandlerInterceptor接口,实现该接口中的以下三个方法:

        • preHandle(request, response, Object handler): 该方法在处理器方法执行之前执行。其返回值为boolean,若为true,则紧接着会执行处理器方法,且会将afterCompletion()方法放入到一个专门的方法栈中等待执行。若为false则不会执行处理器方法。 
        • postHandle(request, response, Object handler, modelAndView): 该方法在处理器方法执行之后执行。处理器方法若最终未被执行,则该方法不会执行。由于该方法是在处理器方法执行完后执行,且该方法参数中包含ModelAndView,所以该方法可以修改处理器方法的处理结果数据,且可以修改跳转方向。
        • afterCompletion(request, response, Object handler, Exception ex): 当 preHandle()方法返回 true 时,会将该方法放到专门的方法栈中,等到对请求进行响应的所有工作完成之后才执行该方法。

          拦截器中方法与处理器方法的执行顺序如图所示。

          一文学会 SpringMVC 拦截器,在这里插入图片描述,第4张

          也可以这样来看 ,如下图:

          一文学会 SpringMVC 拦截器,在这里插入图片描述,第5张

          【3】在 spring-config.xml 配置文件中注册拦截器,代码如下:

              
              
                  
                      
                      
                  
              
          

          【4】运行测试,则控制台输出如下:

          执行了Intercepter1 ----------preHandle
          执行了处理器的方法!
          执行了Intercepter1 ----------postHandle
          执行了Intercepter1 ----------afterCompletion
          

          多个拦截器的执行流程

          项目案例: 创建多个拦截器。(在上面案例的基础上编写以下代码)

          【1】创建Intercepter2,代码如下所示:

          package cn.hh.springmvc03.intercepter;
          import javax.servlet.http.HttpServletRequest;
          import javax.servlet.http.HttpServletResponse;
          import org.springframework.web.servlet.HandlerInterceptor;
          import org.springframework.web.servlet.ModelAndView;
          public class Intercepter2 implements HandlerInterceptor{
          	@Override
          	public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception arg3)
          			throws Exception {
          		System.out.println("执行了Intercepter2----------afterCompletion");		
          	}
          	@Override
          	public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView)
          			throws Exception {
          		System.out.println("执行了Intercepter2----------postHandle");		
          	}
          	@Override
          	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
          		System.out.println("执行了Intercepter2----------preHandle");
          		return true;
          	}
          }
          

          【2】在 spring-config.xml 文件中注册多个拦截器,代码如下:

          	
          	
          		 
          		 	
          		 	
          		 
          		 
          		 
          		 	
          		 	
          		 
           	
          

          【3】运行测试,则控制台输出如下:

          执行了Intercepter1 ----------preHandle
          执行了Intercepter2 ----------preHandle
          执行了处理器的方法!
          执行了Intercepter2 ----------postHandle
          执行了Intercepter1 ----------postHandle
          执行了Intercepter2 ----------afterCompletion
          执行了Intercepter1 ----------afterCompletion
          

          当有多个拦截器时,形成拦截器链。拦截器的执行顺序与其注册顺序一致。需要再次强调一点的是当某一个拦截器的 preHandle() 方法返回 true 并被执行到时,会向一个专门的方法栈中放入该拦截器的 afterCompletion() 方法。

          多个拦截器方法与处理器方法的执行顺序如下图所示:

          一文学会 SpringMVC 拦截器,在这里插入图片描述,第6张

          只要有一个 preHandler() 方法返回 false,则上部的执行链将被断开,其后续的处理器方法与 postHandle() 方法将无法执行。但无论执行链执行情况怎样,只要方法栈中有方法,即执行链中只要有 preHandle() 方法返回 true,就会执行方法栈中的 afterCompletion() 方法,最终都会给出响应。

          权限拦截器(案例分享)

          项目案例: 只有经过登录的用户方可访问处理器,否则,将返回“无权访问”提示。 本例的登录,由一个 JSP 页面完成。即在该页面里将用户信息放入 session 中。也就是说,只要访问过该页面,就说明登录了。没访问过,则为未登录用户。

          实现步骤:

          【1】web.xml 代码如下:

          
          
              
              
                  dispatcherServlet
                  org.springframework.web.servlet.DispatcherServlet
                  
                      contextConfigLocation
                      classpath:spring-config.xml
                  
                  
                  1
              
              
                  dispatcherServlet
                  /
              
          
          

          【2】spring-config.xml 配置文件代码如下:

          
          
              
              
              
              
                  
                  
                  
                  
              
              
              
              
              
              
              
                  
                      
                      
                      
                      
                  
              
              
              
          
          

          【3】UserController 类中添加登陆方法,代码如下:

              //登陆
              @RequestMapping("login")
              @ResponseBody
              public Map login(User user, HttpSession session,@SessionAttribute("code") String attribute){
                  HashMap map = new HashMap<>();
                  System.out.println("--------login方法-------"+attribute);
                  if(user.getCode().equals(attribute)){//验证码填写正确
                      if("tom".equals(user.getUsername())&&"123456".equals(user.getPassword())){//账号密码正确
                          session.setAttribute("user",user);
                          map.put("code",200);
                          map.put("msg","登陆成功");
                      }else{//账号密码不正确
                          map.put("code",500);
                          map.put("msg","登陆失败");
                      }
                  }else{//验证码填写不正确
                      map.put("code",500);
                      map.put("msg","验证码输入不正确");
                  }
                  return map;
              }
          

          【4】添加拦截器 LoginInterceptor 代码如下:

          package cn.kgc.springmvc03.interceptor;
          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 request, HttpServletResponse response, Object handler) throws Exception {
                  System.out.println("-------------preHandle方法--------------");
                  HttpSession session = request.getSession();
                  Object user = session.getAttribute("user");
                  if(user==null){
                      response.sendRedirect("/login.jsp");
                      return false;
                  }
                  return true;
              }
          }
          

          【5】添加前端页面 login.jsp 代码如下:

          <%--
            Created by IntelliJ IDEA.
            User: hhzb100
            Date: 2023/3/2
            Time: 9:35
            To change this template use File | Settings | File Templates.
          --%>
          <%@ page contentType="text/html;charset=UTF-8" language="java" %>
          
          
              Title
              
              
          
          
          

          【6】运行测试


            码文不易,本篇文章就介绍到这里,如果想要学习更多Java系列知识点击关注博主,博主带你零基础学习Java知识。与此同时,对于日常生活有困扰的朋友,欢迎阅读我的第四栏目:《国学周更—心性养成之路》,学习技术的同时,我们也注重了心性的养成。

          一文学会 SpringMVC 拦截器,在这里插入图片描述,第7张