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了。