一个request引发的bug
有很多错误由于需要是多线程是才会发生,导致经常在开发时很难发现,
import java.lang.reflect.ParameterizedType;
import java.util.List; import javax.servlet.http.HttpServletRequest; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.context.support.WebApplicationContextUtils; import com.google.gson.Gson;
import com.qdyq.common.criteria.Criteria;
import com.qdyq.common.orm.BaseEntity;
import com.qdyq.common.orm.BaseMapper;
import com.qdyq.common.orm.MySqlSessionFactoryBean; import qdyq.api.service.CommonService;
import qdyq.api.service.exception.MapperNameErrorException; @Service("common")
@SuppressWarnings({ "rawtypes", "unchecked" })
public class CommonServiceImpl implements CommonService { //private String entityName;
private ThreadLocal<String> entityNameSafe = new ThreadLocal<String>(); @Autowired
private MySqlSessionFactoryBean sqlSessionFactory; public List list(Criteria criteria) {
BaseMapper mapper = getMapper();
System.out.println(mapper.getClass().getName());
return mapper.getBy(criteria);
} public BaseEntity getById(Long id) {
BaseMapper mapper = getMapper();
return mapper.getById(id);
} public int save(String entityJson) {
BaseMapper mapper = getMapper();
BaseEntity entity = (BaseEntity) new Gson().fromJson(entityJson, this.getEntityClass()); if(entity==null){
System.err.println(Thread.currentThread().getId() + entityJson + this.entityNameSafe.get());
} if (entity.getId() == null)
return mapper.insert(entity);
else
return mapper.update(entity);
} public int save(BaseEntity entity) { this.setEntityName(entity.getClass().getSimpleName()); BaseMapper mapper = getMapper(); System.err.println(mapper.getClass().getName() + Thread.currentThread().getId()); if (entity.getId() == null)
return mapper.insert(entity);
else
return mapper.update(entity);
} public int countBy(Criteria criteria) {
BaseMapper mapper = getMapper();
return mapper.countBy(criteria);
} public void setEntityName(String entityName) {
this.entityNameSafe.set(entityName);
//this.entityName = entityName;
} public Class getEntityClass() {
String daoName = this.sqlSessionFactory.getPkgName() + "." + this.entityNameSafe.get() + "Dao";
Class daoInterface;
try {
daoInterface = Class.forName(daoName);
return (Class) ((ParameterizedType) daoInterface.getGenericInterfaces()[0]).getActualTypeArguments()[0];
} catch (ClassNotFoundException e) {
throw new MapperNameErrorException("无效的entityName" + daoName, e, daoName);
} catch (Exception e) {
throw new MapperNameErrorException("未注册的entityName" + daoName, e, daoName);
}
} public List listAss(Criteria criteria) {
BaseMapper mapper = getMapper();
return mapper.getAssBy(criteria);
} public List all() {
BaseMapper mapper = getMapper();
return mapper.findAll();
} public int delete(Object[] id) {
BaseMapper mapper = getMapper();
return mapper.deleteByIds(id);
} protected BaseMapper getMapper(){
String daoName = this.sqlSessionFactory.getPkgName() + "." + this.entityNameSafe.get() + "Dao";
Class daoInterface;
System.err.println(daoName + Thread.currentThread().getId());
HttpServletRequest request = null;
try{
daoInterface = Class.forName(daoName);
request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
WebApplicationContext context = WebApplicationContextUtils.getWebApplicationContext(request.getSession().getServletContext());
return (BaseMapper) context.getBean(daoInterface);
}catch(Exception e){
throw new RuntimeException("无法获取到mapper:" + this.entityNameSafe.get());
} } public int saveAll(List<BaseEntity> list) {
BaseMapper mapper = getMapper();
return mapper.insertAll(list);
} public int removeBy(Criteria criteria){
BaseMapper mapper = getMapper();
return mapper.removeBy(criteria);
} public static void main(String[] args){
//String json = "{id:485,lastTraceDate:'2017-11-09T10:20:37.293Z'}"; }
}
这是一个公共的类,能满足一般的增删改查功能,通过参数,entityName来确定具体使用哪个mapper来完成任务,mapper只要有一个公共的基类,就可以实现上述
功能,但是由于网络请求是多线程的,所以及易导致entityName的冲突,因为原先的entityName只是一个本地字符串,而springmvc的对象又是单例的,这就导致错误的发生
ThreadLocal<String>是一种解决办法,第二种办法是把该对象配置成原型模式,也可以避免错误的发生. 既然类成员变量容易导致错误,哪么request会不会导致错误,因为这次错误引起了思考果断做了测试,
@ResponseBody
@RequestMapping(value = "/save/{entityName}", method = RequestMethod.POST)
public Object save(@PathVariable String entityName, String entityJson,HttpServletRequest request) {
this.getService().setEntityName(entityName);
System.err.println("============================");
System.err.println(request.hashCode());
System.err.println(this.request.hashCode());
System.err.println(this.request.getParameter("entityJson"));
System.err.println(this.request.getClass().getName());
System.err.println(request.getClass().getName());
System.err.println("============================");
return getService().save(entityJson);
}
this.request是通过@Autowired注入的,打印结果到显示this.request始终是一个对象,但是它的获取结果却始终都是正确的,因为它并不是一个对象而是一个代理,也就是说它是线程安全的.但是作为参数传进来的request就不是线程安全的,如果你把它保存在一个成员变量里,后果是很严重的,因为使用过期的request会导致现有request参数的丢失,具体原因还不太清楚,感觉应该是request这个对象里使用缓存之类的东西造成的.
一个request引发的bug的更多相关文章
- 一个排序引发的BUG
你好呀,我是why. 前两天在 Git 上闲逛的时候又不知不觉逛到 Dubbo 那里去了. 看了一下最近一个月的数据,社区活跃度还是很高的: 然后看了一下最新的 issue,大家提问都很积极. 其中看 ...
- 一个空格引发的bug
好久没写博客了. 我们的一个项目用的thinkphp框架,当在debug模式下面运行很正常,但切换到生产模式时,刷新页面第一次可以正常显示,刷新第二次会出现错误如下: Fatal error: Cal ...
- 一个 passive 引发的bug
不是什么很难的东西,权且做个记录. 首先说下背景,目前的项目中,需要同时绑定 wheel 和 scroll 事件. 绑定 wheel,目的是开发 ctrl + wheel 缩放页面功能,此功能与浏览器 ...
- 一个字体引发的bug
delphi 7 中默认字体样式为‘MS Sans Serif’,一般情况下子级控件会继承父级一些属性,其中包括字体(包括字体大小,字体样式,颜色等)属性.如果动态创建控件且需要修改字体颜色或者大小时 ...
- Spring 循环引用(一)一个循环依赖引发的 BUG
Spring 循环引用(一)一个循环依赖引发的 BUG Spring 系列目录(https://www.cnblogs.com/binarylei/p/10198698.html) Spring 循环 ...
- 由一个emoji引发的思考
由一个emoji引发的思考 从毕业以来,基本就一直在做移动端,但是一直就关于移动端的开发,各种适配问题的解决,在日常搬砖中处理了就过了,也没有把东西都沉淀下来,觉得甚是寒颜.现就一个小bug,让我们来 ...
- 安卓微信overflow-x overflow-y引发的bug
今天xgo文章图片页上线用微信扫页面发现一个bug,页面可以双击放大缩小. 找了半天原因,发现是图片描述设置了overflow-y引发的bug. 建议在微信场景里满屏显示不能滚动的页面里慎用overf ...
- QByteArray引发的bug
QByteArray引发的bug 在接收UDP数据的函数里,有如下代码片段 if(0x10 == data.size() && 0xCA == (unsigned char)data. ...
- PHP 中一个 False 引发的问题,差点让公司损失一百万
PHP 中一个 False 引发的问题,差点让公司损失一百万 一.场景描述 上周我一个在金融公司的同学,他在线上写一个 Bug,差点造成公司损失百万.幸好他及时发现了这个问题并修复了.这是一个由 PH ...
随机推荐
- Mybatis逆向工程的配置
源码github下载地址:https://github.com/wcyong/mybatisGeneratorCustom.git 参考文章:https://www.cnblogs.com/whgk/ ...
- 单机安装EFK(一)
官方文档:https://www.elastic.co/guide/en/elasticsearch/reference/current/getting-started-install.html#ge ...
- h5交互动画如何制作
最近几年随着h5的兴起,复杂的h5动画,甚至是交互动画类型的产品不断涌现,尤其在课件产品方面,很多公司都有相关需求,最近很多h5开发工程师想了解相关方面的技术. 针对h5,如果是简单的动画效果,可以考 ...
- Guava - Ordering
guava中Ordering类是对Compartor接口的实现,但它也只是一个抽象类. 当调用Ordering.natural()方法时,它就会返回一个NaturalOrdering的对象,Natur ...
- 阿里云CentOS7服务器利用LVM分区挂载磁盘全记录
1.进入服务器后,首先利用fdisk -l来观察磁盘信息,可以看出红线标注处,有两块硬盘信息,分别是40G和300G 2.同时你也可以观察到分区信息,40G的硬盘已经分了一个区vda1,大小(Bloc ...
- ES - Dynamic templates 动态模板
1.ES Mapping 在lucene中,索引中每个字段都需要指定很多属性,例如:是否分词.采用哪个分词器.是否存储等. 在ES中,其实索引中每个字段也需要指定这些属性,我们有时候并没有对这些属性进 ...
- 【TFS 2010配置】总是提示:Error [ System Checks ] TF255466
服务器环境: Windows Server 2008 软件环境: 安装了360杀毒软件 以下为解决方案: 在验证是否可以安装 SharePoint 时的提示,Error [ System Checks ...
- 二、初步认识springBoot的pom.xml
1. 大体结构 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www. ...
- 知识点:tuple 元素真的不可变吗
tuple 元素真的不可变吗 有一种有序列表叫元组:tuple. tuple和list非常类似,但是tuple一旦初始化就不能修改,比如同样是列出单位或同学的名字: >>> clas ...
- Java子类访问父类的私有成员变量
/**子类会继承父类所有的属性和方法. * 但是根据不同的权限标识符,子类不可见父类的私有变量,但可以通过父类的公共方法访问私有变量 * 所以对于重名变量,子类和父类都各有一份. * 对于子类和父类中 ...