设计模式【1】- 过滤器/拦截器模式

过滤器模式

今天试着用刚看的过滤器模拟了一些web开发中的拦截器的功能,感觉还真的非常有意思

模拟场景

现在一个人想获取绝密信息,我们的任务就是在他获取绝密信息之前,判断一下他有没有权利访问。如果有,则打印绝密信息,否则则反馈不能获取的原因。

类之间的关系

类之间的关系

具体实现

  1. Controller.java
//模拟控制器类
public class Controller {
	/**
	 * 模拟渲染出文本
	 */
	public void renderText(String msg) {
		System.out.println(msg);
	}
}
  1. SecretController.java
//模拟绝密消息的获取控制器
public class SecretController extends Controller {
	/**
	 * 模拟获取绝密消息
	 */
	public void getSecretMsg() {
		// 假装从数据库取得绝密消息
		String secretMsg = "今天吃撑了!";
		// 渲染到界面
		renderText(secretMsg);
	}
}
  1. Invocation.java
//负责所有控制器的调度
public class Invocation {
	private InterceptorChain inters;
	private Controller controller;
	private Method method;
	private String methodName;
	//记录执行到哪个拦截器了
	private int index = 0;
	public Invocation(Controller controller, Method method, InterceptorChain inters) {
		this.inters = inters;
		this.controller = controller;
		this.method = method;
		this.methodName = method.getName();
	}
	//获取当前控制器
	public Controller getController() {
		return controller;
	}
	//获取方法名称
	public String getMethodName() {
		return methodName;
	}
	/**
	 * 继续执行后面的拦截器
	 * 如果无更多拦截器,则直接执行请求的方法
	 **/
	public void invoke() {
		if (index < inters.size()) {
			inters.getInterceptor(index++).intercept(this);
		} else if (index++ == inters.size()) {
			//每次index++表示进入下一个拦截器
			try {
				method.invoke(controller);
			} catch (SecurityException | IllegalAccessException | IllegalArgumentException
					| InvocationTargetException e) {
				e.printStackTrace();
			}
		}
	}
}
  1. LoginInterceptor.java
//检测当前用户是否已经登录了
public class LoginInterceptor implements Interceptor {
	@Override
	public void intercept(Invocation invocation) {
		// 获取当前要请求的Controller
		Controller con = invocation.getController();
		boolean isLogin = true;
		// 检查是否登录
		if (isLogin) {
			// 通过登录检查,继续
			invocation.invoke();
		} else {
			// 写出未登录信息
			con.renderText("您还没有登录!!!");
		}
	}
}
  1. AuthInterception.java
//检测当前用户是否有权利执行方法
public class AuthInterception implements Interceptor {
	@Override
	public void intercept(Invocation invocation) {
		// 获取当前要请求的ControllerMethodName
		Controller con = invocation.getController();
		// 当前要执行的方法名称
		String methodName = invocation.getMethodName();
		boolean isPrivileged = true;
		// 检查是否有权限
		if (isPrivileged) {
			// 通过权限检查,继续
			invocation.invoke();
		} else {
			// 没有权限执行
			con.renderText("您没有权限使用:" + invocation.getMethodName());
		}
	}
}
  1. Interceptor.java
//拦截器接口
public interface Interceptor {
	/** 拦截 **/
	void intercept(Invocation invocation);
}
  1. InterceptorChain.java
//拦截器链
public class InterceptorChain implements Interceptor {
	private List<Interceptor> interceptorList = new ArrayList<>();
	private int index = 0;
	public int size() {
		return interceptorList.size();
	}
	public Interceptor getInterceptor(int index) {
		if (index < 0 || index > interceptorList.size() - 1)
			throw new RuntimeException("数组越界 index=" + index);
		return interceptorList.get(index);
	}
	/**
	 * 添加拦截器
	 * 
	 * @param interceptor
	 * @return
	 */
	public InterceptorChain addInterceptor(Interceptor interceptor) {
		interceptorList.add(interceptor);
		return this;
	}
	/**
	 * 本身也是个拦截器
	 */
	@Override
	public void intercept(Invocation invocation) {
		if (index < size()) {
			interceptorList.get(index++).intercept(invocation);
		} else if (index++ == size()) {
			invocation.invoke();
		}
	}
}
  1. Test.java
//测试类
public class Test {
	public static void main(String[] args) throws NoSuchMethodException, SecurityException {
		// 初始化控制器以及拦截器,拦截器链
		Controller secretController = new SecretController();

		InterceptorChain ic = new InterceptorChain();
		InterceptorChain ic2 = new InterceptorChain();

		Interceptor inter1 = new LoginInterceptor();
		Interceptor inter2 = new AuthInterception();

		ic.addInterceptor(inter1);
		ic2.addInterceptor(inter2);

		ic.addInterceptor(ic2);
		String secretMsg = "getSecretMsg";

		// 模拟请求绝密数据
		Invocation invocation = new Invocation(secretController, secretController.getClass().getMethod(secretMsg), ic);
		invocation.invoke();
	}
}

运行结果图

结果图片

还有几个小问题注意

  1. Q:为什么InterceptorChain要实现Interceptor接口?
    A:InterceptorChain本身页是个拦截器,这样设计可以可以要InterceptorChain加入InterceptorChain里面,实现拦截器组加入拦截器组里面的功能。
  2. Q:拦截器拦截的顺序,和加入的顺序有什么关系?
    A:拦截器加入的顺序,就是拦截的顺序。
  3. Q:如果权限不够,怎样阻碍拦截器的传递呢?
    A:只要不用invoke方法就不会向下传递了,也就是接下来的拦截器,包括访问方法也不会执行了。
  4. Q:那这个拦截器只是在方法执行之前,也就是Before可以截取的,那这么在方法执行以后,也就是After可以做一些操作呢?
    A:在intercept方法中使用invoke之前就是Before,之后就是After了。
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值