spring中拦截器的实现

前言

  • web项目开发中拦截器是常用的功能,帮我们实现登陆验证,设置数据,统计时效等功能 。spring中拦截器一共分两种aop的methodInterceptor和spring mvc HandlerInterceptor
  • HandlerInterceptor拦截的目标是请求的地址,比MethodInterceptor先执行。实现一个HandlerInterceptor拦截器可以直接实现HandlerInterceptor接口,也可以继承HandlerInterceptorAdapter类
  • MethodInterceptor它拦截的目标是方法。实现MethodInterceptor拦截器,使用proxyBean代理配置或AspectJ自动代理。

实例

  • 使用HandlerInterceptor实现接口访问信息记录。 preHandle方法在请求到达controller之前执行,postHandle方法在请求过后执行
定义拦截的类TimeCostIntereptor实现handlerinterceptor接口

public class TimeCostIntereptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object o) throws Exception {
        //记录拦截开始的时间
        Long startTime = System.currentTimeMillis();
        request.setAttribute("startTime",startTime);
        if (o instanceof HandlerMethod){
            //开始获取拦截的方法信息、
            StringBuffer sb = new StringBuffer();
            HandlerMethod handlerMethod = (HandlerMethod) o;
            String controller = handlerMethod.getBean().getClass().getName();
            String method = handlerMethod.getMethod().getName();
            String params = getParamString(request.getParameterMap());
            System.out.println("拦截的类是: "+controller);
        }
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object o, ModelAndView modelAndView) throws Exception {
        Long endTime = System.currentTimeMillis();
        long startTime = (long) request.getAttribute("startTime");
        long costTIme = endTime - startTime;
        if (o instanceof HandlerMethod) System.out.println("花费的时间是: "+costTIme);

    }

    @Override
    public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {

    }

    private String getParamString(Map<String, String[]> map){
        StringBuffer sb = new StringBuffer();
        for (Map.Entry<String, String[]> e: map.entrySet()){
            sb.append(e.getKey()).append("=");
            String[] value = e.getValue();
            if (value != null && value.length == 1) sb.append(value[0]).append("\t");
            else sb.append(Arrays.toString(value)).append("\t");
        }
        return sb.toString();
    }
}
spring mvc的配置文件

<!--拦截器的配置-->
    <mvc:interceptors>
        <!-- 使用bean定义一个Interceptor,直接定义在mvc:interceptors根下面的Interceptor将拦截所有的请求 -->
        <mvc:interceptor>
            <mvc:mapping path="/**"/>
            <!-- 需排除拦截的地址 -->
            <mvc:exclude-mapping path="/" />
            <mvc:exclude-mapping path="/test" />
            <!-- 定义在mvc:interceptor下面的表示是对特定的请求才进行拦截的 ,可以配置拦截器的链-->
            <bean class="com.tianzhuan.web.interceptor.TimeCostIntereptor"/>
        </mvc:interceptor>
    </mvc:interceptors>
image.png
  • 使用aop的 MethodInterceptor 接口的拦截分别使用spirng的ProxyFactoryBean代理和引入aspectj的AOP自动代理
定义接口

public interface TestService {
    void test(String name);
}

//实现类
public class TestServiceImpl implements TestService {

    @Override
    public void test(String name) {
        System.out.println(name);

    }
}
实现接口

public class TestInterceptor implements MethodInterceptor {
    @Override
    public Object invoke(MethodInvocation ivo) throws Throwable {
        String method = ivo.getMethod().getName();
        Object[] arg = ivo.getArguments();
        arg[0] = "hahaha 我被拦截了";
        return ivo.proceed();
    }
}
旧版本的spirng ProxyFactoryBean代理配置方式
 <bean id="testimpl" class="com.tianzhuan.web.service.impl.TestServiceImpl"/>
    <bean id="testInterceptor" class="com.tianzhuan.web.service.impl.TestInterceptor"/>
    <bean id="test" class="org.springframework.aop.framework.ProxyFactoryBean">
        <!--代理接口-->
        <property name="proxyInterfaces" value="com.tianzhuan.web.service.TestService"/>
        <!--目标实现类-->
        <property name="target" ref="testimpl"/>
        <!--拦截器类-->
        <property name="interceptorNames">
            <list>
                <value>testInterceptor</value>
            </list>
        </property>
    </bean>
aspectj的AOP自动代理配置注意引入aspectj的jar

<bean id="testInterceptor" class="com.tianzhuan.web.service.impl.TestInterceptor"/>

    <aop:config proxy-target-class="true">
        <!--切点-->
        <aop:pointcut id="test" expression="execution(* com.tianzhuan.web.service.impl.*.test(..))"/>
        <!--拦截-->
        <aop:advisor advice-ref="testInterceptor" pointcut-ref="test"/>
    </aop:config>

  • 测试
在使用ProxyFactoryBean代理时,应为TestService有两个实现类,TestServiceImpl和proxy代理。
如果按类型注解(Autowired)会有找不到bean的错误,应使用@Resource按名称注入资源文件中的bean
id.
  @Resource(name="test")
    private TestService testimpl;
aspectj的注入和平时一样
@Autowired
private TestService testimpl;

@Test
    public void testProxy(){
        String name = "我被拦截修改了";
        testimpl.test(name);

    }

测试结果


image.png
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 135,079评论 19 139
  • Spring Boot 参考指南 介绍 转载自:https://www.gitbook.com/book/qbgb...
    毛宇鹏阅读 46,985评论 6 342
  • 什么是Spring Spring是一个开源的Java EE开发框架。Spring框架的核心功能可以应用在任何Jav...
    jemmm阅读 16,574评论 1 133
  • 本章内容: 面向切面编程的基本原理 通过POJO创建切面 使用@AspectJ注解 为AspectJ切面注入依赖 ...
    谢随安阅读 3,223评论 0 9
  • 男人的人品,只看两点 经常在一些饭局或公共场合看到一些人接到家人的电话,口气非常不耐烦:“不正忙着嘛,吃完就回。”...
    感情洁癖_2790阅读 209评论 0 0