java访问时先过拦截器_Java知识总结----Spring拦截器(六)

在看到拦截器的时候,大家一定会想到另外一个词,就是过滤器。两者到底有什么区别呢?过滤器,从字面的意思理解就是过滤用的,当很多请求过来的时候,我们对其进行过滤,满足一定条件的时候,才放行。在Java中,过滤器是使用Filter实现的,实现原理都是基于回调函数的。最常见的过滤器的应用就是字符编码的过滤、用户信息验证的过滤等。拦截器呢,就是用来拦截的,可以在方法的执行时,添加一些其他的信息,拦截器是使用Interceptor实现的,实现原理是基于Java的反射机制的。最常见的拦截器的应用有:添加访问日志、性能监控等。今天我们就来看看怎么用Spring的拦截器为方法添加访问日志。

首先,我们创建一个拦截器类,由于我们需要拦截的是方法,所以,就继承MethodInterceptor类。

import org.aopalliance.intercept.MethodInterceptor;

import org.aopalliance.intercept.MethodInvocation;

import org.slf4j.Logger;

import org.slf4j.LoggerFactory;

/**

* 监控日志拦截器

* @author lizhiyang

*

*/

public class MonitorLogInterceptor implements MethodInterceptor {

private Logger logger = LoggerFactory.getLogger(MonitorLogInterceptor.class);

public Object invoke(MethodInvocation methodinvocation) throws Throwable {

Method method = methodinvocation.getMethod();

//方法执行前输出

logger.info("methodIn:methodName="+method.getName());

try {

//执行方法

return methodinvocation.proceed();

} finally {

//方法执行后输出

logger.info("methodOut:methodName="+method.getName());

}

}

}

在方法的执行前和执行后都加上日志输出。

接着,有的时候,我们可能需要自定义多个拦截器,这个时候,我们需要有一个拦截器链,把这些拦截器都串起来。

import java.util.ArrayList;

import java.util.List;

import org.aopalliance.intercept.MethodInterceptor;

import org.aopalliance.intercept.MethodInvocation;

/**

* 拦截器链

* @author lizhiyang

*

*/

public class InterceptorChain implements MethodInterceptor {

private List chains;

public Object invoke(MethodInvocation methodinvocation) throws Throwable {

InterceptorChainSupport support = new InterceptorChainSupport(methodinvocation, new ArrayList(chains));

return support.proceed();

}

public List getChains() {

return chains;

}

public void setChains(List chains) {

this.chains = chains;

}

}

里面我们用到了一个类:InterceptorChainSupport,他的实现如下:

import java.lang.reflect.AccessibleObject;

import java.lang.reflect.Method;

import java.util.List;

import org.aopalliance.intercept.MethodInterceptor;

import org.aopalliance.intercept.MethodInvocation;

public class InterceptorChainSupport implements MethodInvocation {

private MethodInvocation proxy;

private List chains;

public InterceptorChainSupport(MethodInvocation proxy,List chains) {

this.proxy = proxy;

this.chains = chains;

}

public MethodInvocation getProxy() {

return proxy;

}

public void setProxy(MethodInvocation proxy) {

this.proxy = proxy;

}

public List getChains() {

return chains;

}

public void setChains(List chains) {

this.chains = chains;

}

public Object[] getArguments() {

return proxy.getArguments();

}

public AccessibleObject getStaticPart() {

return proxy.getStaticPart();

}

public Object getThis() {

return proxy.getThis();

}

public Object proceed() throws Throwable {

//如果拦截器链不空,则继续执行拦截器

if(chains != null && chains.size() > 0) {

//递归调用,一直调用到拦截器链的最后一个

return (chains.remove(0)).invoke(this);

} else {

return proxy.proceed();

}

}

public Method getMethod() {

return proxy.getMethod();

}

}

InterceptorChainSupport是真正来处理拦截器链的,遍历执行所有的拦截器。在InterceptorChain中构造InterceptorChainSupport的时候要特别注意,一定要new一个新的List来存放chains,否则,会造成调用链只能执行一次的情况。

此处的执行过程是这样的:当调用相应的方法时,调用InterceptorChain.invoke()----->InterceptorChainSupport.proceed()---->***Interceptor.invoke()------>InterceptorChainSupport().proceed()------......---->真正的方法处理---->方法之后的拦截处理。

最后,我们在spring的配置文件中,来配置拦截器。

interceptorChain

*Service

这样配置之后,在spring容器加载的时候,spring就知道了执行*Service类中的方法时候,需要应用interceptorChain中的拦截器。

这个时候呢,就有了一个问题,如果我不想给这个类的每个方法都进行拦截,只拦截一部分呢?这个时候我们可以借助注解来实现。为需要拦截的方法上加上注解。

首先我们创建一个注解类,MonitorLog。

/**

* 1.RetentionPolicy.SOURCE ——只在源代码级别保留,编译时就会被忽略

2.RetentionPolicy.CLASS ——编译时被保留,在class文件中存在,但JVM将会忽略

3.RetentionPolicy.RUNTIME —— 被JVM保留,所以他们能在运行时被JVM或其他使用反射机制的代码所读取和使用.

*

*/

@Retention(RetentionPolicy.RUNTIME)

/**

* 该注解应用于方法

*/

@Target(ElementType.METHOD)

/**

* 指明被注解的类会自动继承,如果我们把注解放在接口的方法上,那么实现该接口的类也会被继承该注解

*/

@Inherited

/**

* Documented 注解表明这个注解应该被 javadoc工具记录.

*/

@Documented

public @interface MonitorLog {

}

然后我们在需要拦截的方法上天剑@MonitorLog注解。

public interface UserService {

@MonitorLog

public boolean insertUser(UserModel user);

public UserModel getUser(int userId);

public String test();

public void user(String name);

}

我们现在还需要修改MonitorLogInterceptor类,只有添加@MonitorLog的方法才进行拦截,其他的不拦截。

public class MonitorLogInterceptor implements MethodInterceptor {

private Logger logger = LoggerFactory.getLogger(MonitorLogInterceptor.class);

public Object invoke(MethodInvocation methodinvocation) throws Throwable {

Method method = methodinvocation.getMethod();

//获取方法的MonitorLog注解

MonitorLog log = method.getAnnotation(MonitorLog.class);

boolean bLog = false;

//该方法存在MonitorLog注解,则输出日志

if(log != null) {

bLog = true;

//方法执行前输出

logger.info("methodIn:methodName="+method.getName());

}

try {

//执行方法

return methodinvocation.proceed();

} finally {

if(bLog) {

//方法执行后输出

logger.info("methodOut:methodName="+method.getName());

}

}

}

} 以上,就是spring拦截器的一个简单的应用。当然了,我们也可以使用spring的aop标签,来进行具体的配置。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值