SpringMVC拦截器

Posted 楠黎倾风

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了SpringMVC拦截器相关的知识,希望对你有一定的参考价值。

7.SpringMVC拦截器

7.1-SpringMVC拦截器-拦截器的作用(理解)

Spring MVC 的拦截器类似于 Servlet 开发中的过滤器 Filter,用于对处理器进行预处理后处理

将拦截器按一定的顺序联结成一条链,这条链称为拦截器链(InterceptorChain)。在访问被拦截的方法或字段时,拦截器链中的拦截器就会按其之前定义的顺序被调用。拦截器也是AOP思想的具体实现。

7.2-SpringMVC拦截器-interceptor和filter区别(理解,记忆)

关于interceptor和filter的区别,如图所示:

7.3-SpringMVC拦截器-快速入门(应用)

自定义拦截器很简单,只有如下三步:

①创建拦截器类实现HandlerInterceptor接口

②配置拦截器

③测试拦截器的拦截效果

编写拦截器:

public class MyInterceptor1 implements HandlerInterceptor 
    //在目标方法执行之前执行

    /**
     * @param request
     * @param response
     * @param handler
     * @return         true:也许放行。false:不允许放行
     * @throws Exception
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception 
        System.out.println("preHandle..........");
        String param = request.getParameter("param");
        if("yes".equals(param))
            return true;
        else 
            request.getRequestDispatcher("/error.jsp").forward(request, response);
            return false;
        
    

    //在目标方法执行之后,视图返回之前执行
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception 
        modelAndView.addObject("name","NanMu");
        System.out.println("postHandle..........");
    

    //在整个流程都执行完毕后再执行
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception 
        //打印
        System.out.println("afterCompletion..........");
    

配置:在SpringMVC的配置文件中配置

 <!--配置拦截器-->
    <mvc:interceptors>
        <!--对那些资源执行拦截操作执行-->
        <mvc:interceptor>
            <mvc:mapping path="/**"/>
            <bean class="com.lfs.interceptor.MyInterceptor1"/>
        </mvc:interceptor>
    </mvc:interceptors>

编写测试程序测试:

编写Controller,发请求到controller,跳转页面

@Controller
public class TargetController 

    @RequestMapping("/target")
    public ModelAndView show() 
        //打印
        System.out.println("目标资源开始执行了");
        ModelAndView mv = new ModelAndView();
        mv.addObject("name", "NanYu");
        mv.setViewName("index");
        return mv;
    


页面:

<html>
<body>
<h1>Hello World! $name</h1>
</body>
</html>

7.4-SpringMVC拦截器-快速入门详解(应用)

拦截器在预处理后什么情况下会执行目标资源,什么情况下不执行目标资源,以及在有多个拦截器的情况下拦截器的执行顺序是什么?

再编写一个拦截器2,

public class MyInterceptor2 implements HandlerInterceptor 
    //在目标方法执行之前 执行
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws ServletException, IOException 
        System.out.println("preHandle22222.....");
        return true;
    

    //在目标方法执行之后 视图对象返回之前执行
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) 
        System.out.println("postHandle2222...");
    

    //在流程都执行完毕后 执行
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) 
        System.out.println("afterCompletion2222....");
    

配置拦截器2

<!--配置拦截器-->
    <mvc:interceptors>
        <mvc:interceptor>
            <!--对哪些资源执行拦截操作-->
            <mvc:mapping path="/**"/>
            <bean class="com.itheima.interceptor.MyInterceptor1"/>
        </mvc:interceptor>
        
        <mvc:interceptor>
            <!--对哪些资源执行拦截操作-->
            <mvc:mapping path="/**"/>
            <bean class="com.itheima.interceptor.MyInterceptor2"/>
        </mvc:interceptor>
    </mvc:interceptors>

结论:

当拦截器的preHandle方法返回true则会执行目标资源,如果返回false则不执行目标资源

多个拦截器情况下,配置在前的先执行,配置在后的后执行

拦截器中的方法执行顺序是:preHandler-------目标资源----postHandle---- afterCompletion

7.5-SpringMVC拦截器-知识小结(记忆)

拦截器中的方法说明如下

三个方法要执行都要基于preHandle返回true才能执行相应的逻辑;postHandle在preHandle后执行在目标方法返回视图熏染之前执行相应的逻辑代码。而afterCompletion在整个流程执行完毕后才能执行相应的逻辑代码。

7.6-SpringMVC拦截器-用户登录权限控制代码实现1(应用)

判断用户是否登录 本质:判断session中有没有user,如果没有登陆则先去登陆,如果已经登陆则直接放行访问目标资源

先编写拦截器如下:

public class PrivilegeInterceptor implements HandlerInterceptor 
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws IOException 
        //逻辑:判断用户是否登录  本质:判断session中有没有user
        HttpSession session = request.getSession();
        User user = (User) session.getAttribute("user");
        if(user==null)
            //没有登录
            response.sendRedirect(request.getContextPath()+"/login.jsp");
            return false;
        
        //放行  访问目标资源
        return true;
    


然后配置该拦截器:找到项目案例的spring-mvc.xml,添加如下配置:

<!--配置权限拦截器-->
    <mvc:interceptors>
        <mvc:interceptor>
            <!--配置对哪些资源执行拦截操作-->
            <mvc:mapping path="/**"/>
            <bean class="com.itheima.interceptor.PrivilegeInterceptor"/>
        </mvc:interceptor>
    </mvc:interceptors>

7.7-SpringMVC拦截器-用户登录权限控制代码实现2(应用)

在登陆页面输入用户名密码,点击登陆,通过用户名密码进行查询,如果登陆成功,则将用户信息实体存入session,然后跳转到首页,如果登陆失败则继续回到登陆页面

在UserController中编写登陆逻辑

@RequestMapping("/login")
    public String login(String username,String password,HttpSession session)
        User user = userService.login(username,password);
        if(user!=null)
            //登录成功  将user存储到session
            session.setAttribute("user",user);
            return "redirect:/index.jsp";
        
        return "redirect:/login.jsp";
    

service层代码如下:

//service层
public User login(String username, String password) 
            User user = userDao.findByUsernameAndPassword(username,password);
            return user;


dao层代码如下:

//dao层
 public User findByUsernameAndPassword(String username, String password) throws EmptyResultDataAccessException
        User user = jdbcTemplate.queryForObject("select * from sys_user where username=? and password=?", new BeanPropertyRowMapper<User>(User.class), username, password);
        return user;
    

此时仍然登陆不上,因为我们需要将登陆请求url让拦截器放行,添加资源排除的配置

<!--配置权限拦截器-->
    <mvc:interceptors>
        <mvc:interceptor>
            <!--配置对哪些资源执行拦截操作-->
            <mvc:mapping path="/**"/>
            <!--配置哪些资源排除拦截操作-->
            <mvc:exclude-mapping path="/user/login"/>
            <bean class="com.itheima.interceptor.PrivilegeInterceptor"/>
        </mvc:interceptor>
    </mvc:interceptors>

7.8-SpringMVC拦截器-用户登录权限控制代码实现3(应用)

JdbcTemplate.queryForObject对象如果查询不到数据会抛异常,导致程序无法达到预期效果,如何来解决该问题?

在业务层处理来自dao层的异常,如果出现异常service层返回null,而不是将异常抛给controller

因此改造登陆的业务层代码,添加异常的控制

public User login(String username, String password) 
        try 
            User user = userDao.findByUsernameAndPassword(username,password);
            return user;
        catch (EmptyResultDataAccessException e)
            return null;
        
    

SpringMVC(十三):SpringMVC拦截器介绍使用

文章目录

SpringMVC拦截器介绍使用

前言

一、拦截器使用

二、拦截器内容详解

1、preHandle方法

2、postHandle方法

3、afterCompletion方法

三、多个拦截器执行顺序


SpringMVC拦截器介绍使用

前言

在之前的系列文章里,我们学习了过滤器的知识。过滤器的作用是保护请求的服务器资源,在请求资源被执行之前,如果请求地址符合拦截范围,则会先执行过滤器。过滤器的执行时机,是在Servlet之前执行的。但是在使用了SpringMVC后,Servlet只有一个了,也就是DisptcherServlet。那么,如果我们仍然使用过滤器来完成请求的拦截,因为过滤器是在Servlet之前执行的,就会造成,过滤器会拦截DispatcherServlet所有的请求。那么,如果我们有部分请求不想被拦截,怎么办?

一、拦截器使用

Spring MVC中的拦截器(Interceptor)类似于Servlet中的过滤器(Filter),它主要用于拦截用户请求并作相应的处理。例如通过拦截器可以进行权限验证、记录请求信息的日志、判断用户是否登录等。 要使用Spring MVC中的拦截器,就需要对拦截器类进行定义和配置。通常拦截器类可以通过两种方式来定义。
  • 通过实现HandlerInterceptor接口,或继承HandlerInterceptor接口的实现类(如HandlerInterceptorAdapter)来定义。
  • 通过实现WebRequestInterceptor接口,或继承WebRequestInterceptor接口的实现类来定义。

拦截器和过滤器的区别

  • 拦截器SpringMVC的,而过滤器是servlet的。
  • 拦截器不依赖与servlet容器,由spring容器初始化,过滤器依赖与servlet容器,由servlet容器初始化。
  • 拦截器只能对action请求起作用,而过滤器则可以对几乎所有的请求起作用。
  • 拦截器可以访问action上下文、值栈里的对象,而过滤器不能访问。
  • 在action的生命周期中,拦截器可以多次被调用,而过滤器只能在容器初始化时被调用一次。
  • 拦截器可以获取IOC容器中的各个bean,而过滤器就不太方便,这点很重要,在拦截器里注入一个service,可以调用业务逻辑。

定义一个拦截器

package com.lanson.interceptor;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
 * @Author: Lansonli
 * @Description: MircoMessage:Mark_7001
 */
public class MyInterceptor implements HandlerInterceptor 
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception 
        /*在请求到达我们定义的handler之前工作的*/
        System.out.println("MyInterceptor preHandle");
        /*返回的是true,代表放行,可以继续到达handler*/
        return true;
    
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception 
        System.out.println("MyInterceptor postHandle");
        /*handler 处理单元返回ModelAndView 时候进行 拦截*/
    
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception 
        /*
        页面渲染完毕,但是还没有给浏览器响应数据的时候
         */
        System.out.println("MyInterceptor afterCompletion");
    

springmvc.xml中注册拦截器

   <!--注册拦截器-->
    <mvc:interceptors>
        <mvc:interceptor>
            <mvc:mapping path="/login.action"/>
            <bean id="myInterceptor" class="com.lanson.interceptor.MyInterceptor"></bean>
        </mvc:interceptor>
    </mvc:interceptors>

二、拦截器内容详解

1、preHandle方法

执行时机:

再进入控制单元方法之前执行

如何调用:

按拦截器定义顺序调用

具体作用:

如果程序员决定该拦截器对请求进行拦截处理后还要调用其他的拦截器,或者是业务处理器去 进行处理,则返回 true。 如果程序员决定不需要再调用其他的组件去处理请求,则返回 false。

参数详解:

  • HttpServletRequest arg0,拦截的请求的request对象
  • HttpServletResponse arg1,,拦截的请求的response对象
  • Object arg2       封存了单元方法对象的HandleMethod对象 
/**
     *
     * @param request  请求对象
     * @param response 响应对象
     * @param handler  目标要调用的Handler
     * @return 返回true放行,返回false拦截
     * @throws Exception
     */
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception 
        /*在请求到达我们定义的handler之前工作的*/
        System.out.println("MyInterceptor preHandle");
        /*设置请求和响应的乱码 */
        /* request.setCharacterEncoding("UTF-8");
        response.setCharacterEncoding("UTF-8");*/
        // 判断是否登录
        /*User user =(User) request.getSession().getAttribute("user");
        if(null == user)
            response.sendRedirect("index.jsp");
        return false;*/
        // 用户权限控制
        return true;
    

2、postHandle方法

执行时机:

在进行数据处理和做出响应之间进行这个方法的调用

如何调用:

在拦截器链内所有拦截器返成功调用

具体作用:

在业务处理器处理完请求后,但是 DispatcherServlet 向客户端返回响应前被调用,

在该方法中对用户请求 request域数据进行处理

参数详解:

  • HttpServletRequest arg0, 拦截的请求的request对象
  • HttpServletResponse arg1, 拦截的请求的response对象
  • Object arg2, 封存了单元方法对象的HandleMethod对象
  • ModelAndView arg3 封存了单元方法的返回值资源路径和请求转到的Map数据 
/**
     *
     * @param request
     * @param response
     * @param handler
     * @param modelAndView  controller响应的结果,视图和数据
     * @throws Exception
     */
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception 
        System.out.println("MyInterceptor postHandle");
        /*控制数据*/
        /*Map<String, Object> map = modelAndView.getModel();
        String msg = (String)map.get("msg");
        String newMsg = msg.replaceAll("脏话", "**");
        map.put("msg", newMsg);*/
        /*控制视图*/
        /*modelAndView.setViewName("/testDemo1.jsp");*/
    

 

3、afterCompletion方法

执行时机:

在进行页面渲染的时候执行

如何调用:

按拦截器定义逆序调用  

具体作用:

在DispatcherServlet 完全处理完请求后被调用,可以在该方法中进行一些资源清理的操作

参数详解:

  • HttpServletRequest arg0拦截的请求的request对象
  • HttpServletResponsearg1拦截的请求的response对象
  • Object arg2封存了单元方法对象的HandleMethod对象
  • Exception arg3 存储了责任链的异常信息
/**
     * 无论controller是否出现异常,都会执行的方法
     *  一般来说都做一些资源释放工作
     * @param request
     * @param response
     * @param handler
     * @param ex
     * @throws Exception
     */
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception 
        /*页面渲染完毕,但是还没有给浏览器响应数据的时候*/
        System.out.println("MyInterceptor afterCompletion");
        System.out.println(ex);
    

三、多个拦截器执行顺序

多个拦截器同时存在时,执行的顺序由配置顺序决定.。先配置谁,谁就先执行。多个拦截器可以理解为拦截器栈,先进后出。如图所示:

<!--注册拦截器-->
    <mvc:interceptors>
        <mvc:interceptor>
            <mvc:mapping path="/login.action"/>
            <bean id="myInterceptor1" class="com.lanson.interceptor.MyInterceptor"></bean>
        </mvc:interceptor>
        <mvc:interceptor>
            <mvc:mapping path="/login.action"/>
            <bean id="myInterceptor2" class="com.lanson.interceptor.MyInterceptor2"></bean>
        </mvc:interceptor>
    </mvc:interceptors>
  1. MyInterceptor preHandle
  2. MyInterceptor2 preHandle
  3. login.action
  4. MyInterceptor2 postHandle
  5. MyInterceptor postHandle
  6. success.jsp
  7. MyInterceptor2 afterCompletion
  8. MyInterceptor afterCompletion

  • 📢博客主页:https://lansonli.blog.csdn.net
  • 📢欢迎点赞 👍 收藏 ⭐留言 📝 如有错误敬请指正!
  • 📢本文由 Lansonli 原创,首发于 CSDN博客🙉
  • 📢停下休息的时候不要忘了别人还在奔跑,希望大家抓紧时间学习,全力奔赴更美好的生活✨

以上是关于SpringMVC拦截器的主要内容,如果未能解决你的问题,请参考以下文章

解决springmvc拦截器拦截静态资源的两种方式

SpringMVC的拦截器和过滤器的区别与联系

使用springmvc怎么配置

记一次诡异的SpringMVC中拦截路径的问题

简单使用拦截器

SpringMVC-- 14 拦截器