title: 自用日志中ThreadLocal的使用 date: 2017.05.29 12:44 categories:
- 技术博客 tags:
- 实现方式
- 日志
- ThreadLocal
做过好几种权限控制,今天写的这个是我目前知道从实现上来说最简单的。
1. 实现步骤
- 写一个基本的注解,用于标识请求资源是否需要进行权限控制,哪儿用贴哪儿
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface RequiredPermission {
String value();
}
- 实现基于
Spring的拦截器,用于做权限逻辑判断
public class LoginInterceptor extends HandlerInterceptorAdapter{
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
if(handler instanceof HandlerMethod){
LoginInfo current = UserContext.getCurrent();
if(((HandlerMethod) handler).getMethodAnnotation(RequireLogin.class) !=null && current==null){
response.sendRedirect("/login.html");
}
}
return super.preHandle(request, response, handler);
}
}
- 在对应项目的
applicationContext.xml中配置这个拦截器bean,一是为了拦截生效,二是配置拦截规则
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/**"/>
<bean class="com.mycompany.myproject.util.LoginInterceptor"/>
</mvc:interceptor>
</mvc:interceptors>
2. 使用注解
见过的几种方式中,基本都用到了注解,主要还是由于反射机制允许我们的程序可以在运行时拿到一些想要的东西,比如请求资源相关,在这里我们是通过handler直接拿到了方法上的注解对象,判断起来也很省事,贴了就是需要登录才可以access的,不贴就直接请求放行。
3. 实现拦截器
我们这里没有直接implements HandlerInterceptor,因为在处理请求的生命周期中只需要对Controller中的方法前拦截一下即可,此处只需要复写preHandle方法,所以小用了一下Adapter即适配器模式。
HandlerInterceptor下有个子接口AsyncHandlerInterceptor(异步处理拦截器),然后HandlerInterceptorAdapter抽象类实现了这个类,因此,我们只需要继承这个抽象类,复写所需的方法即可,不必将四五个方法都放到自己的类中。
这里的HandlerInterceptorAdapter抽象类就是适配器,主要解决的问题就是我们刚刚所面临的,起一个中间转换且适配的作用。
想想生活中的电源适配器、Mac转接线,这些都是适配器,逻辑上的作用是一模一样的,跟我之前说过的一句话不谋而合:本身设计上的很多东西都是从物理世界模拟过去的。因而没必要神化设计模式,该用的时候用就行了。
4. 关于「HandlerMethod」
逻辑中做了一个判断:handler instanceof HandlerMethod,外加这么一层判断主要是为了防止请求上的逻辑异常,说白了,当你请求例如静态图片或者js资源时,不存在我们需要判断的必要(因为要拦截早就放到WEB-INF下面了)。
所以为了保证拦截的请求是我们配置好并且存在于Controller中的,就用了下SpringMVC中的HandlerMethod,有空的时候你可以去看看框架的源码,这个类主要的作用就是封装了请求方法的相关信息,说白了,它代表我们的请求过来在Controller中执行的方法。(定个不靠谱的flag:我真有心思了就来分析一下这块儿的源码)
因而,使用它作用就是强制性从逻辑上把它卡死,只判断MVC层里面存在的请求方法,防止了一些其他资源过来报错的情况,逻辑上更完善。
小结
- 给出了我目前认为最简化的权限控制方案,源码在最上面
- 对其中涉及到的几个关键点做了小分析