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 绑定的过程分析
3. **使用`@RequestParam`绑定请求参数值** - **基本使用**:`@RequestParam`注解用于在方法参数上指定要绑定的请求参数。例如,`showDetail2`方法使用`@RequestParam("userName")`来获取URL查询参数`userName`的值...
最后,`@ModelAttribute`注解具有更广泛的用途,它可以用于绑定请求参数到一个对象实例,通常用于处理复杂的数据模型。Spring MVC会尝试从请求中找到匹配的参数,并将它们设置到对象的相应属性上。例如: ```java @...
"相关函数.txt"文件可能包含了一些关键的API函数,这些函数用于执行绑定操作,例如设置绑定表、发送绑定请求和处理绑定响应等。通过研究这些函数,开发者可以更好地理解ZStack协议栈如何支持绑定通信。 "第十二部分...
- 对于绑定请求,协调器可能返回`ZDP_SUCCESS`(成功)、`ZDP_TABLE_FULL`(绑定表满)或`ZDP_NOT_SUPPORTED`(不支持)的状态。 - 对于解除绑定请求,可能返回`ZDP_SUCCESS`(成功)、`ZDP_NO_ENTRY`(无此条目)或`ZDP_NOT_...
在 SPRING MVC 中,也可以使用 @RequestParam 注解来绑定请求参数。例如: ```java @RequestMapping(value = "/requestParam", method = RequestMethod.GET) public String setupForm(@RequestParam("a") String a, ...
例如,使用@PathVariable注解绑定URL中的参数,使用@RequestParam注解绑定请求参数。 五、SSM整合 SSM整合是指将SpringMVC、MyBatis和Spring框架整合在一起,用于开发复杂的Web应用程序。SSM整合的优点是可以充分...
自动绑定适用于自发现的网络环境,ZigBee设备对象绑定请求和委托绑定适用于需要远程配置或辅助设备操作的场景,而目标绑定则适用于需要控制目标设备响应的设置。这些方法共同确保了ZigBee网络中的高效、可靠和自动化...
在三层架构的MAC绑定系统中,服务器会接收来自客户端的MAC地址绑定请求,验证用户身份,并将绑定信息存储到数据库中。此外,服务器还可能负责动态分配IP地址、监控网络活动和报告异常行为。 3. **数据库层**: ...
gin提供快速数据绑定api,可以通过ShouldBind映射的方式绑定请求数据,其中ShouldBindQuery用于GET请求数据的绑定,ShouldBind方法用于POST请求的数据绑定;gin提供的多项式渲染,让返回到客户端的数据处理变得简单...
在任务处理函数中,我们需要监听`ZDO_STATE_CHANGE`事件,根据设备状态(如终端设备、路由器或协调器)来执行相应的操作,例如允许绑定或发送绑定请求: ```c case ZDO_STATE_CHANGE: // If the device has ...
在此期间,系统会在24小时内处理绑定请求。如果用户想要取消绑定,可以在待绑定状态下按照提示操作,取消后账号将回到未绑定状态。 - **状态3:已绑定** - 成功发送绑定短信并被系统接受后,账号将变为“已绑定”...
- **Spring Boot 方式**:使用 `@RequestParam` 注解来绑定请求参数到方法参数。 ```java @GetMapping("/example") public String handleRequest(@RequestParam("name") String name) { // 使用 name 参数... ...
2. ZigBee设备对象绑定请求:这是由一个设备发起的辅助绑定,帮助目标设备创建绑定条目。任何设备或应用服务都可以通过无线信道发送ZDO消息,包含所需的服务入口参数(地址、端点和簇ID),从而启动委托绑定申请。 ...
实验内容主要包含以下环节:协调器广播绑定请求,终端节点接收到请求后进行绑定,成功后向协调器发送“Hello World”消息,并在液晶屏上显示。绑定完成后,按下协调器的中心键可以触发双方指示灯的点亮,验证绑定...
- **自定义类型**:开发者可以根据需求定义自己的复杂类型,Spring MVC会尝试自动绑定请求参数到这些类型的属性上。 ### 2. `@RequestParam`注解 对于那些不是通过模型绑定(ModelDriven)或者命令对象(Command ...
5. **采集节点处理绑定请求并发送绑定响应**:采集节点接收绑定请求后进行处理,并发送绑定响应。 6. **传感节点接收并处理绑定响应**:传感节点接收到绑定响应后,完成绑定过程。 7. **传感节点发送数据**:传感...
- `@ModelAttribute`:用于绑定请求参数到模型对象,通常与表单数据绑定一起使用。 2. **异步请求处理** - Spring MVC支持异步请求处理,主要通过`@Async`注解实现。这个注解可以应用在方法上,使该方法在一个...
5. **实现流程**:具体的操作流程,包括用户如何操作移动设备进行设备绑定,以及设备如何响应和确认绑定请求。 6. **优势与应用场景**:列举使用这种方法的优点,如提高效率、增强安全性等,并给出具体的使用场景,...