SpringBoot拦截器

一般实现

  1. 定义一个拦截器类

MyInterceptor.java 实现HandlerInterceptor 接口

import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.PrintWriter;

@Component
public class MyInterceptor implements HandlerInterceptor {
    Logger logger = LoggerFactory.getLogger(MyInterceptor.class);

    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
            throws Exception {
        // TODO Auto-generated method stub
        //获取session
        logger.info("---------------------开始进入请求地址拦截----------------------------");
        //return true;
        HttpSession session = request.getSession(true);
        if (session.getAttribute("userId") == null) {
            logger.info("------:跳转到login页面!");
//            response.reset();

            response.setCharacterEncoding("UTF-8");
            response.setContentType("application/json; charset=utf-8");
            PrintWriter out = null;

            JSONObject res = new JSONObject();
            res.put("state", "0");
            res.put("msg", "login in first");
            res.put("output","");
            out = response.getWriter();
            out.append(res.toString());
            return false;
        } else {
            session.setAttribute("userId", session.getAttribute("userId"));
            return true;
        }
    }

    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
                           ModelAndView modelAndView) throws Exception {
        // TODO Auto-generated method stub
        logger.info("--------------处理请求完成后视图渲染之前的处理操作---------------");
    }

    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
            throws Exception {
        // TODO Auto-generated method stub
        logger.info("---------------视图渲染之后的操作-------------------------0");
    }
}

定义一个WebConfig类,并将
WebConfig.java

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import javax.annotation.Resource;

@Configuration
public class WebConfig implements WebMvcConfigurer{
    @Resource
    private MyInterceptor myInterceptor;
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(myInterceptor).addPathPatterns("/sensitiveword");//.excludePathPatterns("/login.html").excludePathPatterns("/*.min.js.*");
    }

}

这样一个拦截器就实现了
HandlerInterceptor是一个接口,其中定义了三个default方法

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.lang.Nullable;

public interface HandlerInterceptor {
    default boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        return true;
    }

    default void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable ModelAndView modelAndView) throws Exception {
    }

    default void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) throws Exception {
    }
}

WebMvcConfigurer也是一个接口,定义的方法都是default方法

import java.util.List;
import org.springframework.format.FormatterRegistry;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.lang.Nullable;
import org.springframework.validation.MessageCodesResolver;
import org.springframework.validation.Validator;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.HandlerMethodReturnValueHandler;
import org.springframework.web.servlet.HandlerExceptionResolver;

public interface WebMvcConfigurer {
    default void configurePathMatch(PathMatchConfigurer configurer) {
    }
    //内容协商配置
    default void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
    }

    default void configureAsyncSupport(AsyncSupportConfigurer configurer) {
    }

    default void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
    }
    //类型转换器和格式化器
    default void addFormatters(FormatterRegistry registry) {
    }
    //添加拦截器
    default void addInterceptors(InterceptorRegistry registry) {
    }
    //添加静态资源,重新定义静态资源的路径
    default void addResourceHandlers(ResourceHandlerRegistry registry) {
    }
    //添加跨域支持
    default void addCorsMappings(CorsRegistry registry) {
    }

    default void addViewControllers(ViewControllerRegistry registry) {
    }
    //配置视图解析器
    default void configureViewResolvers(ViewResolverRegistry registry) {
    }

    default void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {
    }

    default void addReturnValueHandlers(List<HandlerMethodReturnValueHandler> handlers) {
    }
    //配置消息转换器
    default void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
    }

    default void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
    }

    default void configureHandlerExceptionResolvers(List<HandlerExceptionResolver> resolvers) {
    }

    default void extendHandlerExceptionResolvers(List<HandlerExceptionResolver> resolvers) {
    }

    @Nullable
    default Validator getValidator() {
        return null;
    }

    @Nullable
    default MessageCodesResolver getMessageCodesResolver() {
        return null;
    }
}

Servlet过滤器

  • Servlet过滤器提供过滤作用,能够在调用前检查Request对象,修改Request Header和Request内容,在Servlet调用完成以后检查Response对象,修改Response Header和Respones内容
  • 可以串联
  • 只有特定的URL才会触发拦截器
public interface Filter {
        //Servlet过滤器的初始化方法,Servlet容器创建Servlet过滤器实例后将调用这个方法。在这个方法中可以读取web.xml文件中Servlet过滤器的初始化参数
    public void init(FilterConfig filterConfig) throws ServletException;
    //完成实际的过滤操作,当客户请求访问于过滤器关联的URL时,Servlet容器将先调用过滤器的doFilter方法。FilterChain参数用于访问后续过滤器
    public void doFilter(ServletRequest request, ServletResponse response,
            FilterChain chain) throws IOException, ServletException;
         //Servlet容器在销毁过滤器实例前调用该方法,这个方法中可以释放Servlet过滤器占用的资源
    public void destroy();
}
public interface FilterConfig {
 //返回web.xml部署文件中定义的该过滤器的名称
    String getFilterName();
 //返回调用者所处的servlet上下文
    ServletContext getServletContext();
//返回过滤器初始化参数值的字符串形式,当参数不存在时,返回nul1.name是初始化参数名
    String getInitParameter(String var1);
//以Enumeration形式返回过滤器所有初始化参数值,如果没有初始化参数,返回为空
    Enumeration<String> getInitParameterNames();
}

Servlet拦截过程

  1. 拦截器截获客户端请求
  2. 重新封装ServletResponse,在封装后的ServletResponse中提供用户自定义的输出流
  3. 将请求后续传递
  4. Web组件响应请求
  5. 获取ServletRespones中的输出流
  6. 将响应内容通过用户自定义的输出流写入到缓冲流中
  7. 修改响应内容清空缓冲流输出相应内容

对比

  • filter基于filter接口中的doFilter回调函数,interceptor则基于Java本身的反射机制;
  • filter是依赖于servlet容器的,没有servlet容器就无法回调doFilter方法,而interceptor与servlet无关;
  • filter的过滤范围比interceptor大,filter除了过滤请求外通过通配符可以保护页面、图片、文件等,而interceptor只能过滤请求,只对action起作用,在action之前开始,在action完成后结束(如被拦截,不执行action);
  • filter的过滤一般在加载的时候在init方法声明,而interceptor可以通过在xml声明是guest请求还是user请求来辨别是否过滤;
  • interceptor可以访问action上下文、值栈里的对象,而filter不能;
  • 在action的生命周期中,拦截器可以被多次调用,而过滤器只能在容器初始化时被调用一次。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 226,728评论 6 526
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 97,623评论 3 411
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 174,371评论 0 372
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 62,174评论 1 306
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 71,014评论 6 405
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 54,532评论 1 319
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 42,641评论 3 433
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 41,793评论 0 283
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 48,294评论 1 329
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 40,276评论 3 352
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 42,423评论 1 364
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 37,980评论 5 354
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 43,678评论 3 342
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 34,087评论 0 25
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 35,307评论 1 279
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 50,997评论 3 385
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 47,404评论 2 370