Bootstrap

can not be cast to javax.servlet.Filter等问题的解决方法

问题1:can not be cast to javax.servlet.Filter

  一位从测试转开发的同事首次更新代码,并编译在本地启动web项目时,报如下错误:

Exception starting filter encodingFilter
java.lang.ClassCastException:com.gaochao.platform.web.context.filter.ContextFilter2 can not be cast to javax.servlet.Filter

  根据这一错误,在网上查找资料一般认为是tomcat/lib下的jar包跟webapps目录里的应用程序中WEB-INF/lib目录下有相同的包,存在版本上的冲突,解决方案就是为依赖加上一个标签<scope>

1
2
3
4
5
6
7
8
9
10
11
12
< dependency >
                 < groupId >javax.servlet</ groupId >
                 < artifactId >servlet-api</ artifactId >
                 < version >${servlet-version}</ version >
                 < scope >provided</ scope >
             </ dependency >
             < dependency >
                 < groupId >javax.servlet</ groupId >
                 < artifactId >jsp-api</ artifactId >
                 < version >${jsp-version}</ version >
                 < scope >provided</ scope >
             </ dependency >

  顺着这个思路,我查找了关于<scope>标签的用法,如下:

* compile,缺省值,适用于所有阶段,会随着项目一起发布。 

* provided,类似compile,期望JDK、容器或使用者会提供这个依赖。如servlet.jar。 

* runtime,只在运行时使用,如JDBC驱动,适用运行和测试阶段。 

 * test,只在测试时使用,用于编译和运行测试代码。不会随项目发布。 

 * system,类似provided,需要显式提供包含依赖的jarMaven不会在Repository中查找它。

  但是,我们的代码里确认是有这个标签,且配置也没有错误,确实是provided。在已经打好的war包里查询,路径\oa-deploy\target\oa-deploy-0.0.1-SNAPSHOT\WEB-INF\lib中也确认没有servlet的jar包,也符合期望JDK、容器或使用者会提供这个依赖的解释。可见问题还不是出在这个地方,进一步搜索是不是还有其他解决思路。经过进一步查询资料,发现在http://jira.codehaus.org/有一个编号为MOJO-1076的bug,其bug描述与我们的错误基本一致,另外一名用户为其提供的解决思路也是在dependency中加入<scope>属性,提报bug的用户最后加备注如下:

My issue was introduced by gwt-user.jar that contains javax.servlet package.

Setting it as provided solved the issue.


  我的问题是引入gwt-user.jar,而该包中包含servlet,将该包(也可能是该包中依赖servlet)的scope改为provided即ok了。目前我们的项目里引入百数十个包,里面是不是包含servlet查找起来将是较大的工程。另外,除了这名同事以外,其他同事的tomcat启动是不是问题的。所以以上的描述只是解决类似问题的一个思路,但并不是我们问题产生的原因。

  再进一步查找资料,还有前辈提供的一种方案,用以解决不同依赖中包含版本冲突的servlet的问题。在其描述中,类似本题目中的问题是由tomcat6-maven-plugin和paoding-rose两个工程的maven依赖引起,这两个依赖都依赖了servlet-api包,而且两个包的scope都设置成了运行时可用,其中tomcat6-maven-plugin为runtime,paoding-rose为compile该方案提供的方法是使用<exclusions>元素实现。

  如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
< dependency >  
         < groupId >net.paoding</ groupId >  
         < artifactId >paoding-rose</ artifactId >  
         < version >1.0-SNAPSHOT</ version >  
             < exclusions >  
             < exclusion >  
                 < groupId >javax.servlet</ groupId >  
                 < artifactId >servlet-api</ artifactId >  
             </ exclusion >  
         </ exclusions >  
     </ dependency >      
     < dependency >  
         < groupId >javax.servlet</ groupId >  
         < artifactId >servlet-api</ artifactId >  
         < version >2.3</ version >  
         < scope >provided</ scope >  
     </ dependency >  
   </ dependencies >  
         </ dependencies >

  以上是三种通过互联网查询的方案,未解决问题;又通过卸载jdktomcatmaven并重装等等。最终发现采用jetty可以启动项目。最后的解决方案,即为:重装机器,重新部署环境。

问题2:MYSQL里的ISNULL、IFNULL、NULLIF

  在对工作流历史任务进行查询时,历史任务的审批人存储的用户表中的用户code,需要left join 用户表将对应的用户名称。如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<!-- 查询集合审批历史  -->
     < select  id = "queryByProcessExecutionIdForPage"  resultMap = "TaskResultMap"   parameterType = "String" >
         SELECT 
             task.processExecutionId,
             process.name as processDefineName,
             task.activityName,
             user.userName as createUserCode,
             task.status,
             task.description,
             task.finishTime,
             task.createTime
         FROM T_BPM_PROCESS_TASK task
         LEFT JOIN T_BPM_PROCESS_EXECUTION execution ON task.processExecutionId = execution.id
         LEFT JOIN t_bpm_process_define process ON execution.processDefineId = process.id
         LEFT JOIN T_SYS_USER user ON task.createUserCode = user.userCode
         WHERE task.processExecutionId = #{id}
         ORDER BY task.createTime DESC, task.finishTime DESC
     </ select >

  而在抢办,也就是jbpm4_taskassignee为空,而jbpm4_participation中的参与类型为Candidate时,即形成所有参与人共同参与,均为候选审批人,一人审批结束,则该任务办理通过。由于assignee为空,无法像普通任务那样直接关联查询,所以使用ISNULL函数,如下:

1
ISNULL ( user .userName, "抢办" as  createUserCode

  在执行该语句时,发现mysql并不支持ISNULL函数,sql中具有相似功能或相似写法的函数还有:IFNULL以及NULLIF。在链接所指的文章中有对以上三种函数的详细介绍,这里仅作简介。

1
IFNULL(expr1,expr2)

果expr1不是NULLIFNULL()返回expr1,否则它返回expr2IFNULL()返回一个数字或字符串值,取决于它被使用的上下文环境。

1
NULLIF (expr1,expr2)

  如果expr1= expr2  成立,那么返回值为NULL,否则返回值为 expr1。

  通过以上介绍,对于NULLIF为何如此命名感觉很奇怪,似乎与参数null与否无关。MYSQL中我们就可以使用IFNULL来代替IFNULL实现我们想要的功能,修改后如下:

1
ISNULL ( user .userName, "抢办" as  createUserCode

  修改后经测试,可以达到我们想要的结果。

问题3:MySQL关于txt格式字段的优化

  在新建工作中,会查询出所有流程定义的list,随着新的流程表单不断上线,打开所有流程列表的动作越来越耗时。在查询语句中使用的select * from字样,在流程定义所有的属性中包括了text格式的jpdlXml属性,该属性中存储了该流程的xml定义的文本。因为该查询只需列出流程的id、分类、名称,其他属性是不必须的,将jpdlXmlselect属性列表中移除,这也是sql优化的一个基础性的常识,不需要的字段就不要写进select。将jpdlXml移除后,耗时较长的问题并没有明显改善。我们继续向下阅读,发现还有另外一处,在查询出所有流程定义list后,会对该list进行筛选,之前的博文对这一处的逻辑进行过基于责任链模式的优化。其筛选逻辑中有这么一条——流程新发布或表单新保存后会更新流程/表单的某个字段,根据该字段决定新建工作中该流程是否可见。在此处代码里,会对所有流程定义list进行遍历,然后拿到流程对应的form,而查询该form时,也是使用的select *,而在form的定义表中,有两个字段是text类型的,分别为htmltemplate。我们再将这两个非必须字段移除,耗时问题明显改善,用户几无等待就可以看到所有流程的列表。

  这一问题给我们的提示就是,查询动作尽量不用*

问题4:tools.jar not found

  为解决问题2,我也尝试在我的笔记本里(已经有一个台式机和只有显示器连接云服务器的VDI盒子,因经常开会,新申请的笔记本电脑,用于远程连接台式机,一直没有安装开发环境),拉取新的代码,按照开发环境配置新的环境,包括jdk、tomcat等,在部署的时候,报出如下错误:

Fatal error compiling: tools.jar not found: C:\Program Files\Java\jre6\..\lib\tools.jar.

  网上一般对该问题的定义是eclipse中的jre配置jdk中的jre,而正确的配置应该是jdk。查找后发现并没有配置错。最后查看环境变量配置,Win+R打开cmd,输入 java -version,并没有输出版本信息,发现环境变量配置有误。

  修复完毕后,再次deploy没有再发现该问题。



     本文转自 gaochaojs 51CTO博客,原文链接:http://blog.51cto.com/jncumter/1619492,如需转载请自行联系原作者



悦读

道可道,非常道;名可名,非常名。 无名,天地之始,有名,万物之母。 故常无欲,以观其妙,常有欲,以观其徼。 此两者,同出而异名,同谓之玄,玄之又玄,众妙之门。

;