过滤器/拦截器/AOP----springmvc之拦截器

录:

1、springmvc 执行流程 和 HandlerExecutionChain(handler 执行链,包含 handler 方法和拦截器
2、开发拦截器
3、多个拦截器的执行顺序
4、拦截器的例子
5、spring mvc的 HandlerMethod 和 ResourceHttpRequestHandler

6、springboot 注册拦截器

1、springmvc 执行流程 和 HandlerExecutionChain(handler 执行链,包含 handler 方法和拦截器)  <--返回目录

  springmvc 执行流程:

  拦截器是 springmvc 中强大的控件,可以在进入处理器之前做一些操作,或者在处理器完成后进行操作,甚至是在渲染视图后进行操作。springmvc 会在启动期间就通过 @RequestMapping 的注解解析URI 和处理器的对应关系,在运行的时候通过请求找到对应的 HandlerMapping,然后构建 HandlerExecutionChain 对象,它是一个执行的责任链对象,这个对象指向了控制器所对应的方法和拦截器。

2、开发拦截器  <--返回目录

  使用拦截器需要实现接口 org.springframework.web.servlet.HandlerInterceptor,这个接口定义了三个方法,源码:

package org.springframework.web.servlet;

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

import org.springframework.web.method.HandlerMethod;

public interface HandlerInterceptor {

    /**
     * Intercept the execution of a handler. Called after HandlerMapping determined
     * an appropriate handler object, but before HandlerAdapter invokes the handler.*/
    boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
        throws Exception;

    /**
     * Intercept the execution of a handler. Called after HandlerAdapter actually
     * invoked the handler, but before the DispatcherServlet renders the view.
     * Can expose additional model objects to the view via the given ModelAndView.*/
    void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView)
            throws Exception;

    /**
     * Callback after completion of request processing, that is, after rendering
     * the view. Will be called on any outcome of handler execution, thus allows
     * for proper resource cleanup.
     * <p>Note: Will only be called if this interceptor's {@code preHandle}
     * method has successfully completed and returned {@code true}!*/
    void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
            throws Exception;

}

  1) PreHandle(request, response, handler):在处理器之前执行的前置方法,这样 springmvc 可以在进入 handler 方法前处理一些逻辑。注意,此方法返回一个 boolean 值,会影响后面 springmvc 的流程。返回 true,拦截。

  2) PostHandle(request, response, handler, modelAndView): 在处理器之后执行的后置方法,此时 DispatcherServlet 还没开始渲染视图,可以在这个方法里面 通过 ModelAndView 添加一些数据得等等。

  3) afterCompletion(request, response, handler, exception): 无论是否产生异常都会在渲染视图后执行的方法。

  开发拦截器

  1)可以通过实现 HandlerInterceptor 接口,但是这样要同时实现 HandlerInterceptor  接口的三个方法,通常开发中可以继承 HandlerInterceptorAdapter 类,然后重写相应的方法即可。

  2)注册拦截器。

  SSM项目里面,在springmvc配置文件里面配置

<mvc:interceptors>
    <mvc:interceptor>
        <mvc:mapping path="/**">
        <bean class="com.oy.interceptor.MyInterceptor" />
    </mvc:interceptor>
</mvc:interceptors>

  使用 JavaConfig 配置:

public class WebConfig extends WebMvcConfigurerAdapter {

    /**
     * 注册拦截器
     */
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new LoginInterceptor()).addPathPatterns("/**");
    }
    
}

  拦截器的执行流程:

3、多个拦截器的执行顺序  <--返回目录

  首先拦截器执行顺序按照注册配置拦截器顺序前后执行。

4、拦截器的例子  <--返回目录

  需求:实现功能:标注@IsLogin的方法,必须登录才能访问;没有登录重定向到login.jsp

  步骤:

 * spring自定义注解拦截器的配置
 *      1)自定义注解IsLogin;
 *      2)自定义拦截器LoginInterceptor,映射路径"/**",拦截所有请求;
 *      3)注册拦截器;
 *      4)在contrller中测试LoginInterceptor + 注解@IsLogin的使用

   自定义注解 IsLogin

package com.oy.annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface IsLogin {
}
View Code

  拦截器(注册拦截器代码省略)

package com.oy.interceptor;

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

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

import com.oy.Pojo.User;
import com.oy.annotation.IsLogin;

public class LoginInterceptor extends HandlerInterceptorAdapter {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
            throws Exception {

        // 请求的目标不是方法,放行
        if (!(handler instanceof HandlerMethod)) {
            return true;
        }

        // 请求的目标是方法
        HandlerMethod hm = (HandlerMethod) handler;
        Object o = hm.getMethodAnnotation(IsLogin.class);
        
        if (o == null) {// 没有这个注解
            return true; // 放行
        }
        // 有注解
        User currentUser = (User) request.getSession().getAttribute("currentUser");

        if (currentUser == null) {// 没有登录
            response.sendRedirect("/login.jsp");
            return false;
        } else { // 登录了
            return true; // 放行
        }
    }

}
View Code

  测试 controller

package com.oy.controller;

import javax.servlet.http.HttpServletRequest;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import com.oy.Pojo.User;
import com.oy.annotation.IsLogin;

/**
 * spring自定义注解拦截器的配置
 *     1)自定义注解IsLogin;
 *  2)自定义拦截器LoginInterceptor,映射路径"/**",拦截所有请求;
 *  3)注册拦截器;
 *  4)在本方法中测试LoginInterceptor + 注解@IsLogin的使用
 *  
 *  实现功能:标注@IsLogin的方法,必须登录才能访问;没有登录重定向到login.jsp;
 */
@Controller
public class CustomerInterceptorController {
    
    /**
     * 登录
     * @return
     */
    @RequestMapping("/test/login")
    @ResponseBody
    public String login(HttpServletRequest request) {
        
        User user = new User();
        user.setId(1);
        user.setUsername("xxx");
        user.setPassword("123");
        request.getSession().setAttribute("currentUser", user);
        return "<a href='/test/isLogin'>click,test is logged in or not</a>";
    }
    
    /**
     * 此方法被@IsLogin标注,只有登录才能调用此方法
     * @return
     */
    @IsLogin
    @RequestMapping("/test/isLogin")
    @ResponseBody
    public String add() {
        return "hello, xxx, you are welcome!";
    }
}
View Code

5、spring mvc的 HandlerMethod 和 ResourceHttpRequestHandler  <--返回目录

  HandlerInterceptor 接口三个方法都有一个参数 handler, 如果请求目标是 controller 的方法,则 handler 类型是 org.springframework.web.method.HandlerMethod。HandlerMethod封装了很多属性,在访问请求方法的时候可以方便的访问到方法、方法参数、方法上的注解、所属类等并且对方法参数封装处理,也可以方便的访问到方法参数的注解等信息。如果请求目标是静态资,handler 类型是org.springframework.web.servlet.resource.ResourceHttpRequestHandler。

6、springboot 注册拦截器  <--返回目录

  https://www.cnblogs.com/tiancai/p/11196667.html

参考:

  1)《JavaEE互联网轻量级框架整合开发SSM框架(SpringMVC+Spring+MyBatis)和Redis实现》杨开振

原文地址:https://www.cnblogs.com/xy-ouyang/p/12690512.html