ThreadLoacl的反思
在我的随笔 spring mvc:注解@ModelAttribue妙用 中使用ThreadLocal来简化spring mvc控制层controller中的ModelMap,Response、Json数据封装结构的声明。
这种方式很明显地可以减少方法参数以及变量数量,于是乎,我在每个新系统上都将上述一套搬了过去!
经过一段时间,(经人指点)发现会有以下问题:
- 因为没有在每个线程结束后清除变量,在线程池(比如:tomcat线程池)的作用下就会出现脏数据;
- Json数据封装结构其实每次只在返回客户端的时候使用,没必要使用ThreadLocal,在Json数据封装结构中定义一个静态方法即可
定义如下(类名称:JsonData):
1 /** 2 * 静态工厂方法 3 * 4 * @return 5 */ 6 public static JsonData newInstance() { 7 return new JsonData(); 8 } 9 10 /** 11 * 设置成功json 12 * 13 * @param message 14 * @return 15 */ 16 public static JsonData successJson(String message) { 17 return successJson(null, message); 18 } 19 20 /** 21 * 设置成功的json 22 * 23 * @param data 24 * @return 25 */ 26 public static JsonData successJson(Object data) { 27 JsonData jsonData = newInstance(); 28 jsonData.setSuccessJson(data); 29 return jsonData; 30 } 31 32 /** 33 * 设置成功的json 34 * 35 * @param data 36 */ 37 public void setSuccessJson(Object data) { 38 setSuccessJson(data, null); 39 }
使用如下:
1 @RequestMapping("/xx/list") 2 @ResponseBody 3 public JsonData list(@ModelAttribute final DataQuery query) { 4 try { 5 //逻辑 6 return JsonData.successJson(queryResult); 7 } catch (Exception e) { 8 LOGGER.error("查询异常", e); 9 return JsonData.exceptionJson("查询异常"); 10 } 11 }
这样不仅可以达到减少代码的目的,另外也去除了线程脏数据问题,也更加简洁明了!
事实上,这是一个很小的问题,却暴露了一个问题:一旦掌握一个新的技能,在未详细论证的情况下就开始使用,是极其危险的!