Java框架(八)--SpringMVC拦截器

SpringMVC拦截器

一、拦截器-Interceptor

拦截器(Interceptor)用于对URL请求进行前置/后置过滤。
Interceptor与Filter用途相似,但实现方式不同。
Interceptor为SpringMVC的标准组件。
Filter为J2EE的标准组件。
Interceptor底层就是基于Spring AOP面向切面编程实现。

1、HandlerInterceptor接口

preHandle - 前置执行处理
postHandle - 目标资源已被SpringMVC框架处理
afterCompletion - 响应文本已经产生

2、拦截器开发流程

Maven依赖servlet-api
实现HandlerInterceptor接口
applicationContext配置过滤地址

新建工程interceptor并把RESTful风格的应用部分的restfull工程源代码复制到当前工程
在这里插入图片描述
打开pom.xml引入servlet依赖

        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>3.1.0</version>
            <scope>provided</scope>
            <!--<scope>provided</scope>含义是只有开发编译才会引用,
            项目最终运行环境tomcat会自带servlet-api jar包,如果不引用该属性,
            可能会出现jar包版本冲突等问题-->
        </dependency>

在com.ql.restful.interceptor包下创建MyInterceptor类

package com.ql.restful.interceptor;

import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

public class MyInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response, Object handler) throws Exception {
        System.out.println(request.getRequestURL()+"准备执行");
        return true;
    }

    @Override
    public void postHandle(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println(request.getRequestURL()+"-目标处理成功");
    }

    @Override
    public void afterCompletion(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println(request.getRequestURL()+"-响应内容已产生");
    }
}

修改com.ql.restful.controller包下RestfulController类的findPersons方法

    @GetMapping("/persons")
    public List<Person> findPersons(){
        List list = new ArrayList();
        Person person1 = new Person();
        person1.setName("lily");
        person1.setAge(23);
        person1.setBirthday(new Date());
        list.add(person1);
        Person person2 = new Person();
        person2.setName("smith");
        person2.setAge(22);
        person2.setBirthday(new Date());
        list.add(person2);
        System.out.println("RestfulController.findPersons() - return list");
        return list;

在applicationContext.xml中配置拦截器

    <mvc:interceptors>
        <mvc:interceptor>
            <!--<mvc:mapping path="/**"/>-->
            <!--对指定路径进行拦截-->
            <mvc:mapping path="/restful/**"/>
            <!--对指定类型资源不拦截-->
            <mvc:exclude-mapping path="/**.js"/>
            <mvc:exclude-mapping path="/**.css"/>
            <mvc:exclude-mapping path="/**.ico"/>
            <!--对指定路径下所有资源不进行拦截-->
            <mvc:exclude-mapping path="/resources/**"/>
            <bean class="com.ql.restful.interceptor.MyInterceptor"/>
        </mvc:interceptor>
    </mvc:interceptors>

运行工程,在浏览器地址栏中输入http://localhost:8080/restful/persons,控制台中会输出
在这里插入图片描述

3、多Interceptor执行顺序

有多个拦截器时按照配置的顺序依次访问执行。
在这里插入图片描述
在com.ql.restful.interceptor目录下再创建一个拦截器MyInterceptor1

package com.ql.restful.interceptor;

import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

public class MyInterceptor1 implements HandlerInterceptor {
    @Override
    public boolean preHandle(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response, Object handler) throws Exception {
        System.out.println(request.getRequestURL()+"准备执行1");
        return true;
    }

    @Override
    public void postHandle(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println(request.getRequestURL()+"-目标处理成功1");
    }

    @Override
    public void afterCompletion(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println(request.getRequestURL()+"-响应内容已产生1");
    }
}

然后在applicationContext.xml中配置拦截器

    <mvc:interceptors>
        <mvc:interceptor>
            <!--<mvc:mapping path="/**"/>-->
            <!--对指定路径进行拦截-->
            <mvc:mapping path="/restful/**"/>
            <!--对指定类型资源不拦截-->
            <mvc:exclude-mapping path="/**.js"/>
            <mvc:exclude-mapping path="/**.css"/>
            <mvc:exclude-mapping path="/**.ico"/>
            <!--对指定路径下所有资源不进行拦截-->
            <mvc:exclude-mapping path="/resources/**"/>
            <bean class="com.ql.restful.interceptor.MyInterceptor"/>
        </mvc:interceptor>
    </mvc:interceptors>

    <mvc:interceptors>
        <mvc:interceptor>
            <!--<mvc:mapping path="/**"/>-->
            <!--对指定路径进行拦截-->
            <mvc:mapping path="/restful/**"/>
            <!--对指定类型资源不拦截-->
            <mvc:exclude-mapping path="/**.js"/>
            <mvc:exclude-mapping path="/**.css"/>
            <mvc:exclude-mapping path="/**.ico"/>
            <!--对指定路径下所有资源不进行拦截-->
            <mvc:exclude-mapping path="/resources/**"/>
            <bean class="com.ql.restful.interceptor.MyInterceptor1"/>
        </mvc:interceptor>
    </mvc:interceptors>

运行工程,在浏览器中访问http://localhost:8080/restful/persons控制台输出为
在这里插入图片描述

4、preHandle返回值

拦截器中preHandle方法返回boolean值,返回true则请求依次向后传递,如果返回false请求会被中断。

修改com.ql.restful.interceptor包下的MyInterceptor拦截器

package com.ql.restful.interceptor;

import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

public class MyInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response, Object handler) throws Exception {
        System.out.println(request.getRequestURL()+"准备执行");
        response.setContentType("text/html;charset=utf-8");
        response.getWriter().print("请求被拦截");
        return false;
    }

    @Override
    public void postHandle(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println(request.getRequestURL()+"-目标处理成功");
    }

    @Override
    public void afterCompletion(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println(request.getRequestURL()+"-响应内容已产生");
    }
}

运行项目浏览器中访问http://localhost:8080/restful/persons响应结果为
在这里插入图片描述
控制台中也只输出了preHandle中的打印语句内容。
在这里插入图片描述

二、开发“用户流量”拦截器

打开上文的interceptor项目。
在com.ql.restful.interceptor包下新建类为AccessHistoryInterceptor

package com.ql.restful.interceptor;

import org.springframework.web.servlet.HandlerInterceptor;

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

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

        return true;
    }
}

在pom.xml文件,引入Logback组件

        <!--Logback日志输出组件-->
        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-classic</artifactId>
            <version>1.2.3</version>
        </dependency>

然后在src/main/resources目录下创建logback.xml

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <appender name="console" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>[%thread] %d %level %logger{10} - %msg%n</pattern>
        </encoder>
    </appender>
    <!--生成按天滚动的日志文件-->
    <appender name="accessHistoryLog" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <!--滚动策略-->
        <!--TimeBasedRollingPolicy按照时间进行滚动-->
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <!--配置日志文件存储路径,%d为当天日期-->
            <fileNamePattern>d:/logs/history.%d.log</fileNamePattern>
        </rollingPolicy>
        <encoder>
            <pattern>[%thread] %d %level %logger{10} - %msg%n</pattern>
        </encoder>
    </appender>
    <!--
        日志输出级别(优先级高到低):
        error: 错误 - 系统的故障日志
        warn: 警告 - 存在风险或使用不当的日志
        info: 一般性消息
        debug: 程序内部用于调试信息
        trace: 程序运行的跟踪信息
     -->
    <root level="debug">
        <appender-ref ref="console"/>
    </root>
    <!--AccessHistoryInterceptor类中产生的日志都会使用当前标签所描述规则
    additivity叠加的意思,若值为true,则当前类的日志也会在控制台中输出,
    若值为false,则只会在设置的文件中输出
    -->
    <logger name="com.ql.restful.interceptor.AccessHistoryInterceptor"
        level="INFO" additivity="false">
        <appender-ref ref="accessHistoryLog"/>
    </logger>
</configuration>

修改AccessHistoryInterceptor拦截器类,编写获取日志代码

package com.ql.restful.interceptor;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.servlet.HandlerInterceptor;

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

public class AccessHistoryInterceptor implements HandlerInterceptor {
    private Logger logger = LoggerFactory.getLogger(AccessHistoryInterceptor.class);
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        StringBuilder log = new StringBuilder();
        log.append(request.getRemoteAddr());//IP地址
        log.append("|");
        log.append(request.getRequestURL());//访问地址
        log.append("|");
        log.append(request.getHeader("user-agent"));//访问客户端信息(操作系统、浏览器等)
        logger.info(log.toString());
        return true;
    }
}

在applicationContext.xml中添加拦截器配置

    <mvc:interceptors>
        <mvc:interceptor>
            <mvc:mapping path="/**"/>
            <mvc:exclude-mapping path="/resources/**"/>
            <bean class="com.ql.restful.interceptor.AccessHistoryInterceptor"/>
        </mvc:interceptor>
    </mvc:interceptors>

运行项目,在浏览器中访问http://localhost:8080/client.html并测试相关按钮,在D:\logs目录里生成相应的日志文件
在这里插入图片描述
打开日志文件,可以看看获取的日志内容。
在这里插入图片描述

三、Spring MVC处理流程

在这里插入图片描述

1、执行链

在这里插入图片描述

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Spring MVC 中的过滤拦截都可以在请求处理之前或之后进行一些特定的操作,但它们的实现方式和作用范围不同。 过滤是基于 Servlet 规范实现的,在 Servlet 容中运行,可以拦截所有的请求(包括静态资源请求),并对请求进行处理。过滤通常用于请求的预处理和后处理,比如编码转换、日志记录、权限校验、资源缓存等。 拦截是基于 Spring MVC 框架实现的,在 DispatcherServlet 中运行,只能拦截 Spring MVC 的请求(即只能拦截到经过 DispatcherServlet 的请求),并对请求进行处理。拦截通常用于请求的预处理和后处理,比如权限校验、日志记录、性能监控等。 下面是一个简单的 Spring MVC 过滤拦截的示例: ```java // 过滤实现类 public class EncodingFilter implements Filter { @Override public void init(FilterConfig filterConfig) throws ServletException { // 初始化方法 } @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { // 处理请求的方法 request.setCharacterEncoding("UTF-8"); response.setContentType("text/html;charset=UTF-8"); chain.doFilter(request, response); } @Override public void destroy() { // 销毁方法 } } // 拦截实现类 public class LogInterceptor implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { // 处理请求前的方法 System.out.println("请求 URL:" + request.getRequestURI()); return true; } @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { // 处理请求后的方法 } @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { // 请求处理完成后的方法 } } ``` 在 Spring MVC 中配置过滤拦截: ```xml <!-- 配置过滤 --> <filter> <filter-name>encodingFilter</filter-name> <filter-class>com.example.EncodingFilter</filter-class> </filter> <filter-mapping> <filter-name>encodingFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <!-- 配置拦截 --> <mvc:interceptors> <bean class="com.example.LogInterceptor" /> </mvc:interceptors> ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值