前言
- 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>

- 使用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);
}
测试结果

网友评论