SSH整合,照着视频敲的,不知为何会报错,经历了快两周的折磨给解决了。记录下来给后面需要帮助的人,也算极好的了。
Struts Problem Report
Struts has detected an unhandled exception:
Messages: |
|
File: | org/apache/catalina/loader/WebappClassLoaderBase.java |
Line number: | 1,333 |
Stacktraces
com.opensymphony.xwork2.DefaultActionInvocation.createAction(DefaultActionInvocation.java:317) com.opensymphony.xwork2.DefaultActionInvocation.init(DefaultActionInvocation.java:398) com.opensymphony.xwork2.DefaultActionProxy.prepare(DefaultActionProxy.java:194) org.apache.struts2.impl.StrutsActionProxy.prepare(StrutsActionProxy.java:63) org.apache.struts2.impl.StrutsActionProxyFactory.createActionProxy(StrutsActionProxyFactory.java:37) com.opensymphony.xwork2.DefaultActionProxyFactory.createActionProxy(DefaultActionProxyFactory.java:58) org.apache.struts2.dispatcher.Dispatcher.serviceAction(Dispatcher.java:565) org.apache.struts2.dispatcher.ng.ExecuteOperations.executeAction(ExecuteOperations.java:81) org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter.doFilter(StrutsPrepareAndExecuteFilter.java:99) org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:240) org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207) org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:212) org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:106) org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:502) org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:141) org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79) org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:616) org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:88) org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:528) org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1100) org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:687) org.apache.tomcat.util.net.AprEndpoint$SocketProcessor.doRun(AprEndpoint.java:2508) org.apache.tomcat.util.net.AprEndpoint$SocketProcessor.run(AprEndpoint.java:2497) java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) java.lang.Thread.run(Thread.java:745)
org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1333) org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1167) com.opensymphony.xwork2.util.ClassLoaderUtil.loadClass(ClassLoaderUtil.java:152) com.opensymphony.xwork2.ObjectFactory.getClassInstance(ObjectFactory.java:135) com.opensymphony.xwork2.spring.SpringObjectFactory.getClassInstance(SpringObjectFactory.java:246) com.opensymphony.xwork2.spring.SpringObjectFactory.buildBean(SpringObjectFactory.java:163) com.opensymphony.xwork2.ObjectFactory.buildBean(ObjectFactory.java:178) com.opensymphony.xwork2.factory.DefaultActionFactory.buildAction(DefaultActionFactory.java:22) com.opensymphony.xwork2.ObjectFactory.buildAction(ObjectFactory.java:148) com.opensymphony.xwork2.DefaultActionInvocation.createAction(DefaultActionInvocation.java:298) com.opensymphony.xwork2.DefaultActionInvocation.init(DefaultActionInvocation.java:398) com.opensymphony.xwork2.DefaultActionProxy.prepare(DefaultActionProxy.java:194) org.apache.struts2.impl.StrutsActionProxy.prepare(StrutsActionProxy.java:63) org.apache.struts2.impl.StrutsActionProxyFactory.createActionProxy(StrutsActionProxyFactory.java:37) com.opensymphony.xwork2.DefaultActionProxyFactory.createActionProxy(DefaultActionProxyFactory.java:58) org.apache.struts2.dispatcher.Dispatcher.serviceAction(Dispatcher.java:565) org.apache.struts2.dispatcher.ng.ExecuteOperations.executeAction(ExecuteOperations.java:81) org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter.doFilter(StrutsPrepareAndExecuteFilter.java:99) org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:240) org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207) org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:212) org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:106) org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:502) org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:141) org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79) org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:616) org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:88) org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:528) org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1100) org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:687) org.apache.tomcat.util.net.AprEndpoint$SocketProcessor.doRun(AprEndpoint.java:2508) org.apache.tomcat.util.net.AprEndpoint$SocketProcessor.run(AprEndpoint.java:2497) java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) java.lang.Thread.run(Thread.java:745)
工程目录结构如下:
applicationContext-hibernate.xml:
1 <?xml version="1.0" encoding="UTF-8"?> 2 <beans xmlns="http://www.springframework.org/schema/beans" 3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 4 xmlns:aop="http://www.springframework.org/schema/aop" 5 xmlns:context="http://www.springframework.org/schema/context" 6 xmlns:tx="http://www.springframework.org/schema/tx" 7 xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd 8 http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd 9 http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd 10 http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd"> 11 12 <!-- 导入资源文件 --> 13 <context:property-placeholder location="classpath:db.properties"/> 14 15 <!-- 配置 C3P0 数据源 --> 16 <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"> 17 <property name="user" value="${jdbc.user}"></property> 18 <property name="password" value="${jdbc.password}"></property> 19 <property name="driverClass" value="${jdbc.driverClass}"></property> 20 <property name="jdbcUrl" value="${jdbc.jdbcUrl}"></property> 21 22 <property name="initialPoolSize" value="${jdbc.initPoolSize}"></property> 23 <property name="maxPoolSize" value="${jdbc.maxPoolSize}"></property> 24 </bean> 25 26 <!-- 配置 SessionFactory --> 27 <bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean"> 28 <property name="dataSource" ref="dataSource"></property> 29 <property name="configLocation" value="classpath:hibernate.cfg.xml"></property> 30 <property name="mappingLocations" value="classpath:com/tt/ssh/entities/*.hbm.xml"></property> 31 </bean> 32 33 34 <!-- 配置 Spring 的声明式事务 --> 35 <!-- 1. 配置 hibernate 的事务管理器 --> 36 <bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager"> 37 <property name="sessionFactory" ref="sessionFactory"></property> 38 </bean> 39 40 <!-- 2. 配置事务属性 --> 41 <tx:advice id="txAdvice" transaction-manager="transactionManager"> 42 <tx:attributes> 43 <tx:method name="get*" read-only="true"/> 44 <tx:method name="lastNameIsValid" read-only="true"/> 45 <tx:method name="*"/> 46 </tx:attributes> 47 </tx:advice> 48 49 <!-- 3. 配置事务切入点, 再把事务属性和事务切入点关联起来 --> 50 <aop:config> 51 <aop:pointcut expression="execution(* com.tt.ssh.service.*.*(..))" id="txPointcut"/> 52 <aop:advisor advice-ref="txAdvice" pointcut-ref="txPointcut"/> 53 </aop:config> 54 55 </beans>
applicationContext-beans.xml
1 <?xml version="1.0" encoding="UTF-8"?> 2 <beans xmlns="http://www.springframework.org/schema/beans" 3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 4 xmlns:context="http://www.springframework.org/schema/context" 5 xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd 6 http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd"> 7 8 9 10 <bean id="employeeDao" class="com.tt.ssh.dao.EmployeeDao"> 11 <property name="sessionFactory" ref="sessionFactory"></property> 12 </bean> 13 14 <bean id="employeeService" class="com.tt.ssh.service.EmployeeService"> 15 <property name="employeeDao" ref="employeeDao"></property> 16 </bean> 17 18 <bean id="employeeAction" class="com.tt.ssh.actions.EmployeeAction" scope="prototype"> 19 <property name="employeeService" ref="employeeService"></property> 20 </bean> 21 22 23 </beans>
Struts.xml:
1 <?xml version="1.0" encoding="UTF-8" ?> 2 <!DOCTYPE struts PUBLIC 3 "-//Apache Software Foundation//DTD Struts Configuration 2.3//EN" 4 "http://struts.apache.org/dtds/struts-2.3.dtd"> 5 6 <struts> 7 8 <constant name="struts.enable.DynamicMethodInvocation" value="false" /> 9 <constant name="struts.devMode" value="true" /> 10 <constant name="struts.objectFactory" value="spring"></constant> 11 12 <package name="default" namespace="/" extends="struts-default"> 13 <action name="emp-*" class="employeeAction" method="{1}"> 14 <result name="list">/emp-list.jsp</result> 15 </action> 16 17 </package> 18 19 </struts>
web.xml:
1 <?xml version="1.0" encoding="UTF-8"?> 2 <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 3 xmlns="http://java.sun.com/xml/ns/javaee" 4 xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" 5 id="WebApp_ID" version="2.5"> 6 7 <context-param> 8 <param-name>contextConfigLocation</param-name> 9 <param-value> 10 classpath:applicationContext-*.xml 11 </param-value> 12 </context-param> 13 14 <listener> 15 <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> 16 </listener> 17 18 <!-- 配置 Struts2 的 Filter --> 19 <filter> 20 <filter-name>struts2</filter-name> 21 <filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class> 22 </filter> 23 24 <filter-mapping> 25 <filter-name>struts2</filter-name> 26 <url-pattern>/*</url-pattern> 27 </filter-mapping> 28 29 </web-app>
db.properties:
1 jdbc.user=root 2 jdbc.password=1234 3 jdbc.driverClass=com.mysql.jdbc.Driver 4 jdbc.jdbcUrl=jdbc:mysql://localhost:3306/spring_struts_hibernate 5 6 jdbc.initPoolSize=5 7 jdbc.maxPoolSize=10
index.jsp:
1 <%@ page language="java" contentType="text/html; charset=UTF-8" 2 pageEncoding="UTF-8"%> 3 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> 4 <html> 5 <head> 6 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> 7 <title>Insert title here</title> 8 </head> 9 <body> 10 <a href="emp-list.action">List All Employee</a> 11 </body> 12 </html>
运行index.jsp,点击超链接就会出现如上错误。
解决办法:
1.新建一个JUnit测试单元:SpringTest.java,从两个applicationContext.xml文件中获取IOC容器即ApplicationContext对象,然后利用ApplicationContext对象获取employeeAction的bean对象,发现获取不到。再往前进一步获取employeeService、employeeDao发现都获取不到。也就是说,从employeeDao就已经出了问题。这说明employeeDao的bean配置出了问题。
于是回到employeeDao的bean的配置文件:applicationContext-beans.xml,看到定义employeeDao处提示文件中的黄色感叹号,提示说无法识别出引用的sessionFactory。而sessionFactory的bean是在applicationContext-hibernate.xml中定义的。
这意味着applicationContext-beans.xml无法识别到applicationContext-hibernate.xml文件,不是在web.xml中将两个applicationContex.xml文件定义了的吗?
这就是问题的核心了:虽然IOC容器里都导入了这两个applicationContex.xml文件,但是这涉及到的是一个applicationContex.xml文件引用另一个applicationContex.xml文件的问题。需要在applicationContext-beans.xml中导入applicationContext-hibernate.xml文件:
(关于ApplicationContext请参考我的另一篇博客:http://www.cnblogs.com/TTTTT/p/6675557.html)
2.还有个问题我经常犯,就是在applicationContext.xml中定义pointCut时经常将execution错写成execute。
3.struts.xml里定义的action的name一定要和jsp里的action的名称要保持一致,不要弄错成struts.xml的action的class了,这一点我也经常容易犯。
最后强调一下:如果按照以上方法将错误的地方全部修改正确之后,在JUnit测试单元里能获取到action的bean就说明action实例化成功。如果此时运行jsp仍然报错提示无法实例化action,可能是运行环境或者是eclipse的bug,解决办法是按照正确的代码重新建一个工程或者将这个工程复制一份重命名再运行就Ok了。