public abstract class ThreadContext { /** * Private internal log instance. */ private static final Logger log = LoggerFactory.getLogger(ThreadContext.class); public static final String SECURITY_MANAGER_KEY = ThreadContext.class.getName() + "_SECURITY_MANAGER_KEY"; public static final String SUBJECT_KEY = ThreadContext.class.getName() + "_SUBJECT_KEY"; private static final ThreadLocal<Map<Object, Object>> resources = new InheritableThreadLocalMap<Map<Object, Object>>(); protected ThreadContext() { } public static Map<Object, Object> getResources() { return resources != null ? new HashMap<Object, Object>(resources.get()) : null; } public static void setResources(Map<Object, Object> newResources) { if (CollectionUtils.isEmpty(newResources)) { return; } resources.get().clear(); resources.get().putAll(newResources); } private static Object getValue(Object key) { return resources.get().get(key); } public static Object get(Object key) { if (log.isTraceEnabled()) { String msg = "get() - in thread [" + Thread.currentThread().getName() + "]"; log.trace(msg); } Object value = getValue(key); if ((value != null) && log.isTraceEnabled()) { String msg = "Retrieved value of type [" + value.getClass().getName() + "] for key [" + key + "] " + "bound to thread [" + Thread.currentThread().getName() + "]"; log.trace(msg); } return value; } public static void put(Object key, Object value) { if (key == null) { throw new IllegalArgumentException("key cannot be null"); } if (value == null) { remove(key); return; } resources.get().put(key, value); if (log.isTraceEnabled()) { String msg = "Bound value of type [" + value.getClass().getName() + "] for key [" + key + "] to thread " + "[" + Thread.currentThread().getName() + "]"; log.trace(msg); } } public static Object remove(Object key) { Object value = resources.get().remove(key); if ((value != null) && log.isTraceEnabled()) { String msg = "Removed value of type [" + value.getClass().getName() + "] for key [" + key + "]" + "from thread [" + Thread.currentThread().getName() + "]"; log.trace(msg); } return value; } public static void remove() { resources.remove(); } public static SecurityManager getSecurityManager() { return (SecurityManager) get(SECURITY_MANAGER_KEY); } public static void bind(SecurityManager securityManager) { if (securityManager != null) { put(SECURITY_MANAGER_KEY, securityManager); } } public static SecurityManager unbindSecurityManager() { return (SecurityManager) remove(SECURITY_MANAGER_KEY); } public static Subject getSubject() { return (Subject) get(SUBJECT_KEY); } public static void bind(Subject subject) { if (subject != null) { put(SUBJECT_KEY, subject); } } public static Subject unbindSubject() { return (Subject) remove(SUBJECT_KEY); } private static final class InheritableThreadLocalMap<T extends Map<Object, Object>> extends InheritableThreadLocal<Map<Object, Object>> { protected Map<Object, Object> initialValue() { return new HashMap<Object, Object>(); } @SuppressWarnings({"unchecked"}) protected Map<Object, Object> childValue(Map<Object, Object> parentValue) { if (parentValue != null) { return (Map<Object, Object>) ((HashMap<Object, Object>) parentValue).clone(); } else { return null; } } } }
公司现有的项目中要求具有登录校验工作,很多人提起shiro以及spring security等众多框架,不是说框架不好,只是个人感觉很多内容并不是很需要框架去依赖,反倒失去独立思考的能力,就比如说很多人总是说dubbo,其实看了dubbo的实现,并没有让我很惊艳的地方,完全可以使用netty的方式写一个。
今天我就把shiro中的ThreadContext的改造下,其实equest过来后,我们只需解决通过filter拦截请求是否有验证过就足矣,那要尽可能多接受请求,通过这些出发点后,最原始的肯定是能够接受最方便的。
ThreadLocal作为线程副本很好的解决线程之间的独立性,通过TL能够保证存储线程的变量,虽然可能是使用不到造成memory leadking,实际上因为线程副本的变量存储空间跟线程本身并不是同个生命周期,那就要小心在线程销毁的时候,记得ThreadLocal的remove掉。
结论:
其实很多开源框架并不一定全部适合所有场景,而且很多开源框架本身存在诸多问题,在并不能完全控制住的情况下,很容易产生杂七杂八的难以解决的问题。
相关推荐
使用ZDP EndDeviceBindReq 绑定的过程分析
gin提供快速数据绑定api,可以通过ShouldBind映射的方式绑定请求数据,其中ShouldBindQuery用于GET请求数据的绑定,ShouldBind方法用于POST请求的数据绑定;gin提供的多项式渲染,让返回到客户端的数据处理变得简单...
在学习SpringMVC的过程中,关于@ModelAttribute的使用方法一度遇到一些奇怪...1绑定请求参数到实体对象(表单的命令对象):一是将请求参数的输入封装到POJO对象中;二是创建具体实例,以value为键值存储在Model对象中
下列关于ModelAndView的说法错误的是( )。 (选择一项) A:控制器处理方法的返回值若为: ...下列关于@RequestParam绑定请求参数值的说法正确的是()。 (选择一项) A: Controller方法入参时,必须使用@RequestP
DailyNet 简单易用的Android网络请求框架,自动绑定生命周期调度请求
使用@RequestParam、@RequestHeader和@CookieValue注解分别映射请求参数、请求头和Cookie值信息到相应处理方法的入...另外,SpringMVC也支持使用POJO对象绑定请求参数,且也可以使用Servlet原生API作为目标方法的形参。
5.3 请求和方法参数的绑定 1 请求参数自动绑定controller方法的参数值 1.1 表单项自动绑定controller方法的对象参数 表单提交时,Spring mvc会按照请求表单项的名字自动为方法的参数对象填充属性值,并且支持级联的...
spring拦截器,高级参数绑定,controller返回值
NULL 博文链接:https://yfm049.iteye.com/blog/860494
WCF http绑定服务端,分享.net 中wcf的http绑定方式,分服务端和客户端,分享,供大家一起学习,提高!
android数据绑定
使用@RequestParam绑定请求参数到方法参数 13.12.5. 使用@ModelAttribute提供一个从模型到数据的链接 13.12.6. 使用@SessionAttributes指定存储在会话中的属性 13.12.7. 自定义WebDataBinder初始化 13.13. 更多...
使用@RequestParam绑定请求参数到方法参数 13.12.5. 使用@ModelAttribute提供一个从模型到数据的链接 13.12.6. 使用@SessionAttributes指定存储在会话中的属性 13.12.7. 自定义WebDataBinder初始化 13.13. 更多...
2.http请求代理方式 3.dns代理模式 此软件使用的是代理模式 缺点: 1.初次使用起来可能比较麻烦,但对于开发者来说应该很容易 2.每次开机需执行start.bat(也可以加入到开机启动) 优点: 1.切换方便快捷 2.可以根据...
easyui-combobox控件的后台数据递归生成json,前台绑定实例说明。 可直接拷贝到项目中,然后修改数据源即可使用。
在数据绑定过程中,Spring MVC框架会通过数据绑定组件(DataBinder)将请求参数串的内容进行类型转换,然后将转换后的值赋给控制器类中方法的形参,这样后台方法就可以正确绑定并获取客户端请求携带的参数了。...
由于我们不使用敏感信息或尝试实施身份验证,但是大多数手机在搜索前都要求使用用户名和密码进行绑定请求,因此它将对任何绑定请求成功做出响应,而无需检查凭据。 这意味着地址列表将始终是最新的,因为没有导入/...
今天小编就为大家分享一篇vue请求服务器数据后绑定不上的解决方法,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
NULL 博文链接:https://jinnianshilongnian.iteye.com/blog/1718813
此处根据请求到的页面代码,可以使用正则表达式或者使用:Document、Elements 对象定位AppId和AppSecret的位置,便于获取值。 7.在微信公众号设置页面,获取微信公众号信息持久化到数据库中; 如:公众号名称,...