待续,待续,明天再来
编写文档时间:2012-5-28
1、spring下载地址:
Spring Framework 3.1.0.RELEASE is the current production release (requires Java 1.5+)
http://www.springsource.org/download/community
2、hibernate下载地址:
Hibernate ORM 4.1.2 Release
3、tomcat7.0下载地址
http://tomcat.apache.org/download-70.cgi(根据不同的系统来选择不同包来下载)
我的是window7 64位系统,我选择了64-bit Windows zip (pgp, md5),没有选择server,如果你用server版本也可以:),对于两者区别,自己下下玩玩就知道了。
4、mysql下载地址
http://www.mysql.com/downloads/mysql/
我下载版本:mysql-5.5.24-winx64.msi
5、新建一个动态网页项目(我是使用eclipse javaee ide)
6、修改web.xml文件
我们知道tomcat解析web.xml并加载类的时候,他加载顺序是:listener-filter-servlet-other
第一步:我们把spring的bean的注册工作放在listener,优先启动(这里包括数据源模块的启动)
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5"> <display-name>spring-mvc</display-name> <!--配置欢迎界面 --> <welcome-file-list> <welcome-file>index.html</welcome-file> <welcome-file>index.htm</welcome-file> <welcome-file>index.jsp</welcome-file> <welcome-file>default.html</welcome-file> <welcome-file>default.htm</welcome-file> <welcome-file>default.jsp</welcome-file> </welcome-file-list> <!--配置listener --> <!--在这里可以配置spring的监听器,启动的时候需要把spring中的bean都注册到spring容器中 --> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <!--配置filter对编码进行转换 --> <!--配置servlet --> </web-app>
所以你首先需要到Spring Framework 3.1.0.RELEASE里面找到“org.springframework.web-3.1.0.RELEASE.jar”放到lib底下
第二步:添加编码转换,并拦截所有的url地址
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5"> <display-name>spring-mvc</display-name> <!--配置欢迎界面 --> <welcome-file-list> <welcome-file>index.html</welcome-file> <welcome-file>index.htm</welcome-file> <welcome-file>index.jsp</welcome-file> <welcome-file>default.html</welcome-file> <welcome-file>default.htm</welcome-file> <welcome-file>default.jsp</welcome-file> </welcome-file-list> <!--配置listener --> <!--在这里可以配置spring的监听器,启动的时候需要把spring中的bean都注册到spring容器中 --> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <!--配置filter对编码进行转换 --> <filter> <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class> <filter-name>encodingFilter</filter-name> <init-param> <param-name>encoding</param-name> <param-value>UTF-8</param-value> </init-param> <init-param> <param-name>forceEncoding</param-name> <param-value>true</param-value><!-- 强制进行转码 --> </init-param> </filter> <filter-mapping> <filter-name>encodingFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <!--配置servlet --> </web-app>
第三步:添加spring中C(控制器),来对url进行拦截,并转发给不同的control处理
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5"> <display-name>spring-mvc</display-name> <!--配置欢迎界面 --> <welcome-file-list> <welcome-file>index.html</welcome-file> <welcome-file>index.htm</welcome-file> <welcome-file>index.jsp</welcome-file> <welcome-file>default.html</welcome-file> <welcome-file>default.htm</welcome-file> <welcome-file>default.jsp</welcome-file> </welcome-file-list> <!--配置listener --> <!--在这里可以配置spring的监听器,启动的时候需要把spring中的bean都注册到spring容器中 --> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <!--配置filter对编码进行转换 --> <filter> <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class> <filter-name>encodingFilter</filter-name> <init-param> <param-name>encoding</param-name> <param-value>UTF-8</param-value> </init-param> <init-param> <param-name>forceEncoding</param-name> <param-value>true</param-value><!-- 强制进行转码 --> </init-param> </filter> <filter-mapping> <filter-name>encodingFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <!--配置servlet --> <!--我们希望spring的控制器比其他servlet优先启动,所以你需要设置load-on-startup 这个东西:值越小越先启动(0-5),没有或者为负数的时候,servlet被选用的时候才加载--> <servlet> <servlet-name>controller</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <load-on-startup>2</load-on-startup> </servlet> <servlet-mapping> <servlet-name>controller</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> </web-app>
这里你发现,org.springframework.web.servlet.DispatcherServlet这个类在spring包中的:org.springframework.web.servlet-3.1.0.RELEASE.jar中,所以你需要把他导入到lib下
===================web.xml配置文件大功告成==================
第四步,你试着启动下:),你发现他出错了:
五月 29, 2012 11:35:04 下午 org.apache.catalina.core.AprLifecycleListener init
信息: The APR based Apache Tomcat Native library which allows optimal performance in production environments was not found on the java.library.path: F:\Program Files\Java\jdk1.7.0\bin;C:\Windows\Sun\Java\bin;C:\Windows\system32;C:\Windows;F:\Program Files\Java\jdk1.7.0\jre\bin;F:\Program Files (x86)\PHP\;C:\Program Files (x86)\NVIDIA Corporation\PhysX\Common;C:\Program Files\Common Files\Microsoft Shared\Windows Live;C:\Program Files (x86)\Common Files\Microsoft Shared\Windows Live;C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v1.0\;C:\Program Files (x86)\Windows Live\Shared;D:\res\java\jar\apache-ant-1.8.2-bin\apache-ant-1.8.2\bin;.
五月 29, 2012 11:35:04 下午 org.apache.tomcat.util.digester.SetPropertiesRule begin
警告: [SetPropertiesRule]{Server/Service/Engine/Host/Context} Setting property 'source' to 'org.eclipse.jst.jee.server:spring-mvc' did not find a matching property.
五月 29, 2012 11:35:05 下午 org.apache.coyote.AbstractProtocol init
信息: Initializing ProtocolHandler ["http-bio-8080"]
五月 29, 2012 11:35:05 下午 org.apache.coyote.AbstractProtocol init
信息: Initializing ProtocolHandler ["ajp-bio-8009"]
五月 29, 2012 11:35:05 下午 org.apache.catalina.startup.Catalina load
信息: Initialization processed in 855 ms
五月 29, 2012 11:35:05 下午 org.apache.catalina.core.StandardService startInternal
信息: Starting service Catalina
五月 29, 2012 11:35:05 下午 org.apache.catalina.core.StandardEngine startInternal
信息: Starting Servlet Engine: Apache Tomcat/7.0.27
五月 29, 2012 11:35:05 下午 org.apache.catalina.core.ContainerBase startInternal
严重: A child container failed during start
java.util.concurrent.ExecutionException: org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Catalina].StandardHost[localhost].StandardContext[/spring-mvc]]
at java.util.concurrent.FutureTask$Sync.innerGet(FutureTask.java:252)
at java.util.concurrent.FutureTask.get(FutureTask.java:111)
at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:1128)
at org.apache.catalina.core.StandardHost.startInternal(StandardHost.java:782)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1566)
at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1556)
at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:334)
at java.util.concurrent.FutureTask.run(FutureTask.java:166)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603)
at java.lang.Thread.run(Thread.java:722)
Caused by: org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Catalina].StandardHost[localhost].StandardContext[/spring-mvc]]
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:154)
... 7 more
Caused by: java.lang.NoClassDefFoundError: org/springframework/context/ApplicationContextException
at java.lang.Class.getDeclaredFields0(Native Method)
at java.lang.Class.privateGetDeclaredFields(Class.java:2308)
at java.lang.Class.getDeclaredFields(Class.java:1760)
at org.apache.catalina.startup.WebAnnotationSet.getDeclaredFields(WebAnnotationSet.java:452)
at org.apache.catalina.startup.WebAnnotationSet.loadFieldsAnnotation(WebAnnotationSet.java:257)
at org.apache.catalina.startup.WebAnnotationSet.loadApplicationListenerAnnotations(WebAnnotationSet.java:88)
at org.apache.catalina.startup.WebAnnotationSet.loadApplicationAnnotations(WebAnnotationSet.java:64)
at org.apache.catalina.startup.ContextConfig.applicationAnnotationsConfig(ContextConfig.java:381)
at org.apache.catalina.startup.ContextConfig.configureStart(ContextConfig.java:858)
at org.apache.catalina.startup.ContextConfig.lifecycleEvent(ContextConfig.java:345)
at org.apache.catalina.util.LifecycleSupport.fireLifecycleEvent(LifecycleSupport.java:119)
at org.apache.catalina.util.LifecycleBase.fireLifecycleEvent(LifecycleBase.java:90)
at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5161)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
... 7 more
Caused by: java.lang.ClassNotFoundException: org.springframework.context.ApplicationContextException
at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1711)
at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1556)
... 21 more
五月 29, 2012 11:35:05 下午 org.apache.catalina.core.ContainerBase startInternal
严重: A child container failed during start
java.util.concurrent.ExecutionException: org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Catalina].StandardHost[localhost]]
at java.util.concurrent.FutureTask$Sync.innerGet(FutureTask.java:252)
at java.util.concurrent.FutureTask.get(FutureTask.java:111)
at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:1128)
at org.apache.catalina.core.StandardEngine.startInternal(StandardEngine.java:302)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
at org.apache.catalina.core.StandardService.startInternal(StandardService.java:443)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
at org.apache.catalina.core.StandardServer.startInternal(StandardServer.java:732)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
at org.apache.catalina.startup.Catalina.start(Catalina.java:675)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:601)
at org.apache.catalina.startup.Bootstrap.start(Bootstrap.java:322)
at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:450)
Caused by: org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Catalina].StandardHost[localhost]]
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:154)
at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1566)
at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1556)
at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:334)
at java.util.concurrent.FutureTask.run(FutureTask.java:166)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603)
at java.lang.Thread.run(Thread.java:722)
Caused by: org.apache.catalina.LifecycleException: A child container failed during start
at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:1136)
at org.apache.catalina.core.StandardHost.startInternal(StandardHost.java:782)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
... 7 more
五月 29, 2012 11:35:05 下午 org.apache.catalina.startup.Catalina start
严重: Catalina.start:
org.apache.catalina.LifecycleException: Failed to start component [StandardServer[8005]]
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:154)
at org.apache.catalina.startup.Catalina.start(Catalina.java:675)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:601)
at org.apache.catalina.startup.Bootstrap.start(Bootstrap.java:322)
at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:450)
Caused by: org.apache.catalina.LifecycleException: Failed to start component [StandardService[Catalina]]
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:154)
at org.apache.catalina.core.StandardServer.startInternal(StandardServer.java:732)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
... 7 more
Caused by: org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Catalina]]
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:154)
at org.apache.catalina.core.StandardService.startInternal(StandardService.java:443)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
... 9 more
Caused by: org.apache.catalina.LifecycleException: A child container failed during start
at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:1136)
at org.apache.catalina.core.StandardEngine.startInternal(StandardEngine.java:302)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
... 11 more
五月 29, 2012 11:35:05 下午 org.apache.catalina.startup.Catalina start
信息: Server startup in 653 ms
第五步:发现错误,解决错误
Caused by: java.lang.NoClassDefFoundError: org/springframework/context/ApplicationContextException 这句话告诉我们,他找不到这个类,我们查看下spring jar包,发现他在:org.springframework.context-3.1.0.RELEASE.jar里面,于是,我加入到lib中,再次启动。
他继续报错:
五月 29, 2012 11:41:58 下午 org.apache.catalina.core.AprLifecycleListener init
信息: The APR based Apache Tomcat Native library which allows optimal performance in production environments was not found on the java.library.path: F:\Program Files\Java\jdk1.7.0\bin;C:\Windows\Sun\Java\bin;C:\Windows\system32;C:\Windows;F:\Program Files\Java\jdk1.7.0\jre\bin;F:\Program Files (x86)\PHP\;C:\Program Files (x86)\NVIDIA Corporation\PhysX\Common;C:\Program Files\Common Files\Microsoft Shared\Windows Live;C:\Program Files (x86)\Common Files\Microsoft Shared\Windows Live;C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v1.0\;C:\Program Files (x86)\Windows Live\Shared;D:\res\java\jar\apache-ant-1.8.2-bin\apache-ant-1.8.2\bin;.
五月 29, 2012 11:41:58 下午 org.apache.tomcat.util.digester.SetPropertiesRule begin
警告: [SetPropertiesRule]{Server/Service/Engine/Host/Context} Setting property 'source' to 'org.eclipse.jst.jee.server:spring-mvc' did not find a matching property.
五月 29, 2012 11:41:58 下午 org.apache.coyote.AbstractProtocol init
信息: Initializing ProtocolHandler ["http-bio-8080"]
五月 29, 2012 11:41:58 下午 org.apache.coyote.AbstractProtocol init
信息: Initializing ProtocolHandler ["ajp-bio-8009"]
五月 29, 2012 11:41:58 下午 org.apache.catalina.startup.Catalina load
信息: Initialization processed in 917 ms
五月 29, 2012 11:41:58 下午 org.apache.catalina.core.StandardService startInternal
信息: Starting service Catalina
五月 29, 2012 11:41:58 下午 org.apache.catalina.core.StandardEngine startInternal
信息: Starting Servlet Engine: Apache Tomcat/7.0.27
五月 29, 2012 11:41:59 下午 org.apache.catalina.core.ContainerBase startInternal
严重: A child container failed during start
java.util.concurrent.ExecutionException: org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Catalina].StandardHost[localhost].StandardContext[/spring-mvc]]
at java.util.concurrent.FutureTask$Sync.innerGet(FutureTask.java:252)
at java.util.concurrent.FutureTask.get(FutureTask.java:111)
at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:1128)
at org.apache.catalina.core.StandardHost.startInternal(StandardHost.java:782)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1566)
at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1556)
at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:334)
at java.util.concurrent.FutureTask.run(FutureTask.java:166)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603)
at java.lang.Thread.run(Thread.java:722)
Caused by: org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Catalina].StandardHost[localhost].StandardContext[/spring-mvc]]
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:154)
... 7 more
Caused by: java.lang.NoClassDefFoundError: org/springframework/core/env/EnvironmentCapable
at java.lang.ClassLoader.defineClass1(Native Method)
at java.lang.ClassLoader.defineClass(ClassLoader.java:791)
at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142)
at org.apache.catalina.loader.WebappClassLoader.findClassInternal(WebappClassLoader.java:2889)
at org.apache.catalina.loader.WebappClassLoader.findClass(WebappClassLoader.java:1170)
at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1678)
at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1556)
at java.lang.ClassLoader.defineClass1(Native Method)
at java.lang.ClassLoader.defineClass(ClassLoader.java:791)
at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142)
at org.apache.catalina.loader.WebappClassLoader.findClassInternal(WebappClassLoader.java:2889)
at org.apache.catalina.loader.WebappClassLoader.findClass(WebappClassLoader.java:1170)
at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1678)
at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1556)
at java.lang.Class.getDeclaredFields0(Native Method)
at java.lang.Class.privateGetDeclaredFields(Class.java:2308)
at java.lang.Class.getDeclaredFields(Class.java:1760)
at org.apache.catalina.startup.WebAnnotationSet.getDeclaredFields(WebAnnotationSet.java:452)
at org.apache.catalina.startup.WebAnnotationSet.loadFieldsAnnotation(WebAnnotationSet.java:257)
at org.apache.catalina.startup.WebAnnotationSet.loadApplicationListenerAnnotations(WebAnnotationSet.java:88)
at org.apache.catalina.startup.WebAnnotationSet.loadApplicationAnnotations(WebAnnotationSet.java:64)
at org.apache.catalina.startup.ContextConfig.applicationAnnotationsConfig(ContextConfig.java:381)
at org.apache.catalina.startup.ContextConfig.configureStart(ContextConfig.java:858)
at org.apache.catalina.startup.ContextConfig.lifecycleEvent(ContextConfig.java:345)
at org.apache.catalina.util.LifecycleSupport.fireLifecycleEvent(LifecycleSupport.java:119)
at org.apache.catalina.util.LifecycleBase.fireLifecycleEvent(LifecycleBase.java:90)
at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5161)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
... 7 more
Caused by: java.lang.ClassNotFoundException: org.springframework.core.env.EnvironmentCapable
at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1711)
at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1556)
... 35 more
五月 29, 2012 11:41:59 下午 org.apache.catalina.core.ContainerBase startInternal
严重: A child container failed during start
java.util.concurrent.ExecutionException: org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Catalina].StandardHost[localhost]]
at java.util.concurrent.FutureTask$Sync.innerGet(FutureTask.java:252)
at java.util.concurrent.FutureTask.get(FutureTask.java:111)
at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:1128)
at org.apache.catalina.core.StandardEngine.startInternal(StandardEngine.java:302)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
at org.apache.catalina.core.StandardService.startInternal(StandardService.java:443)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
at org.apache.catalina.core.StandardServer.startInternal(StandardServer.java:732)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
at org.apache.catalina.startup.Catalina.start(Catalina.java:675)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:601)
at org.apache.catalina.startup.Bootstrap.start(Bootstrap.java:322)
at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:450)
Caused by: org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Catalina].StandardHost[localhost]]
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:154)
at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1566)
at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1556)
at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:334)
at java.util.concurrent.FutureTask.run(FutureTask.java:166)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603)
at java.lang.Thread.run(Thread.java:722)
Caused by: org.apache.catalina.LifecycleException: A child container failed during start
at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:1136)
at org.apache.catalina.core.StandardHost.startInternal(StandardHost.java:782)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
... 7 more
五月 29, 2012 11:41:59 下午 org.apache.catalina.startup.Catalina start
严重: Catalina.start:
org.apache.catalina.LifecycleException: Failed to start component [StandardServer[8005]]
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:154)
at org.apache.catalina.startup.Catalina.start(Catalina.java:675)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:601)
at org.apache.catalina.startup.Bootstrap.start(Bootstrap.java:322)
at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:450)
Caused by: org.apache.catalina.LifecycleException: Failed to start component [StandardService[Catalina]]
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:154)
at org.apache.catalina.core.StandardServer.startInternal(StandardServer.java:732)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
... 7 more
Caused by: org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Catalina]]
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:154)
at org.apache.catalina.core.StandardService.startInternal(StandardService.java:443)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
... 9 more
Caused by: org.apache.catalina.LifecycleException: A child container failed during start
at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:1136)
at org.apache.catalina.core.StandardEngine.startInternal(StandardEngine.java:302)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
... 11 more
五月 29, 2012 11:41:59 下午 org.apache.catalina.startup.Catalina start
信息: Server startup in 404 ms
发现错误:Caused by: java.lang.NoClassDefFoundError: org/springframework/core/env/EnvironmentCapable
我们继续到spring jar中去查找,继续报错,说少了org.springframework.core-3.1.0.RELEASE这个jar中,于是我把他导入到lib中。继续重启tomcat。
继续报错:
五月 29, 2012 11:44:59 下午 org.apache.catalina.core.AprLifecycleListener init
信息: The APR based Apache Tomcat Native library which allows optimal performance in production environments was not found on the java.library.path: F:\Program Files\Java\jdk1.7.0\bin;C:\Windows\Sun\Java\bin;C:\Windows\system32;C:\Windows;F:\Program Files\Java\jdk1.7.0\jre\bin;F:\Program Files (x86)\PHP\;C:\Program Files (x86)\NVIDIA Corporation\PhysX\Common;C:\Program Files\Common Files\Microsoft Shared\Windows Live;C:\Program Files (x86)\Common Files\Microsoft Shared\Windows Live;C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v1.0\;C:\Program Files (x86)\Windows Live\Shared;D:\res\java\jar\apache-ant-1.8.2-bin\apache-ant-1.8.2\bin;.
五月 29, 2012 11:44:59 下午 org.apache.tomcat.util.digester.SetPropertiesRule begin
警告: [SetPropertiesRule]{Server/Service/Engine/Host/Context} Setting property 'source' to 'org.eclipse.jst.jee.server:spring-mvc' did not find a matching property.
五月 29, 2012 11:44:59 下午 org.apache.coyote.AbstractProtocol init
信息: Initializing ProtocolHandler ["http-bio-8080"]
五月 29, 2012 11:44:59 下午 org.apache.coyote.AbstractProtocol init
信息: Initializing ProtocolHandler ["ajp-bio-8009"]
五月 29, 2012 11:44:59 下午 org.apache.catalina.startup.Catalina load
信息: Initialization processed in 996 ms
五月 29, 2012 11:44:59 下午 org.apache.catalina.core.StandardService startInternal
信息: Starting service Catalina
五月 29, 2012 11:44:59 下午 org.apache.catalina.core.StandardEngine startInternal
信息: Starting Servlet Engine: Apache Tomcat/7.0.27
五月 29, 2012 11:45:00 下午 org.apache.catalina.core.ContainerBase startInternal
严重: A child container failed during start
java.util.concurrent.ExecutionException: org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Catalina].StandardHost[localhost].StandardContext[/spring-mvc]]
at java.util.concurrent.FutureTask$Sync.innerGet(FutureTask.java:252)
at java.util.concurrent.FutureTask.get(FutureTask.java:111)
at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:1128)
at org.apache.catalina.core.StandardHost.startInternal(StandardHost.java:782)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1566)
at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1556)
at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:334)
at java.util.concurrent.FutureTask.run(FutureTask.java:166)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603)
at java.lang.Thread.run(Thread.java:722)
Caused by: org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Catalina].StandardHost[localhost].StandardContext[/spring-mvc]]
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:154)
... 7 more
Caused by: java.lang.NoClassDefFoundError: org/springframework/beans/factory/ListableBeanFactory
at java.lang.ClassLoader.defineClass1(Native Method)
at java.lang.ClassLoader.defineClass(ClassLoader.java:791)
at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142)
at org.apache.catalina.loader.WebappClassLoader.findClassInternal(WebappClassLoader.java:2889)
at org.apache.catalina.loader.WebappClassLoader.findClass(WebappClassLoader.java:1170)
at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1678)
at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1556)
at java.lang.ClassLoader.defineClass1(Native Method)
at java.lang.ClassLoader.defineClass(ClassLoader.java:791)
at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142)
at org.apache.catalina.loader.WebappClassLoader.findClassInternal(WebappClassLoader.java:2889)
at org.apache.catalina.loader.WebappClassLoader.findClass(WebappClassLoader.java:1170)
at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1678)
at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1556)
at java.lang.Class.getDeclaredFields0(Native Method)
at java.lang.Class.privateGetDeclaredFields(Class.java:2308)
at java.lang.Class.getDeclaredFields(Class.java:1760)
at org.apache.catalina.startup.WebAnnotationSet.getDeclaredFields(WebAnnotationSet.java:452)
at org.apache.catalina.startup.WebAnnotationSet.loadFieldsAnnotation(WebAnnotationSet.java:257)
at org.apache.catalina.startup.WebAnnotationSet.loadApplicationListenerAnnotations(WebAnnotationSet.java:88)
at org.apache.catalina.startup.WebAnnotationSet.loadApplicationAnnotations(WebAnnotationSet.java:64)
at org.apache.catalina.startup.ContextConfig.applicationAnnotationsConfig(ContextConfig.java:381)
at org.apache.catalina.startup.ContextConfig.configureStart(ContextConfig.java:858)
at org.apache.catalina.startup.ContextConfig.lifecycleEvent(ContextConfig.java:345)
at org.apache.catalina.util.LifecycleSupport.fireLifecycleEvent(LifecycleSupport.java:119)
at org.apache.catalina.util.LifecycleBase.fireLifecycleEvent(LifecycleBase.java:90)
at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5161)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
... 7 more
Caused by: java.lang.ClassNotFoundException: org.springframework.beans.factory.ListableBeanFactory
at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1711)
at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1556)
... 35 more
五月 29, 2012 11:45:00 下午 org.apache.catalina.core.ContainerBase startInternal
严重: A child container failed during start
java.util.concurrent.ExecutionException: org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Catalina].StandardHost[localhost]]
at java.util.concurrent.FutureTask$Sync.innerGet(FutureTask.java:252)
at java.util.concurrent.FutureTask.get(FutureTask.java:111)
at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:1128)
at org.apache.catalina.core.StandardEngine.startInternal(StandardEngine.java:302)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
at org.apache.catalina.core.StandardService.startInternal(StandardService.java:443)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
at org.apache.catalina.core.StandardServer.startInternal(StandardServer.java:732)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
at org.apache.catalina.startup.Catalina.start(Catalina.java:675)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:601)
at org.apache.catalina.startup.Bootstrap.start(Bootstrap.java:322)
at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:450)
Caused by: org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Catalina].StandardHost[localhost]]
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:154)
at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1566)
at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1556)
at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:334)
at java.util.concurrent.FutureTask.run(FutureTask.java:166)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603)
at java.lang.Thread.run(Thread.java:722)
Caused by: org.apache.catalina.LifecycleException: A child container failed during start
at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:1136)
at org.apache.catalina.core.StandardHost.startInternal(StandardHost.java:782)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
... 7 more
五月 29, 2012 11:45:00 下午 org.apache.catalina.startup.Catalina start
严重: Catalina.start:
org.apache.catalina.LifecycleException: Failed to start component [StandardServer[8005]]
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:154)
at org.apache.catalina.startup.Catalina.start(Catalina.java:675)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:601)
at org.apache.catalina.startup.Bootstrap.start(Bootstrap.java:322)
at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:450)
Caused by: org.apache.catalina.LifecycleException: Failed to start component [StandardService[Catalina]]
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:154)
at org.apache.catalina.core.StandardServer.startInternal(StandardServer.java:732)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
... 7 more
Caused by: org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Catalina]]
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:154)
at org.apache.catalina.core.StandardService.startInternal(StandardService.java:443)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
... 9 more
Caused by: org.apache.catalina.LifecycleException: A child container failed during start
at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:1136)
at org.apache.catalina.core.StandardEngine.startInternal(StandardEngine.java:302)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
... 11 more
五月 29, 2012 11:45:00 下午 org.apache.catalina.startup.Catalina start
信息: Server startup in 413 ms
同上方法:他说这个找不到 org/springframework/beans/factory/ListableBeanFactory ,我把org.springframework.beans-3.1.0.RELEASE.jar包导入
接着他继续报错:Caused by: java.lang.NoClassDefFoundError: org/apache/commons/logging/Log;
于是乎,我继续导入jar包,(其实这个包是spring core那个jar包依赖与他的,你再env/AbstractEnvironment.java这个类中就有),于是我又去上网找了这个jar包
地址:http://commons.apache.org/logging/download_logging.cgi
我下载的版本是:commons-logging-1.1.1-bin.zip,解压开,我们需要里面的commons-logging-1.1.1.jar
把他放入lib中,重新启动,发现错误:
java.lang.NoClassDefFoundError: org/springframework/asm/ClassVisitor
Caused by: java.lang.ClassNotFoundException: org.springframework.asm.ClassVisitor
java.lang.NoClassDefFoundError: org/apache/log4j/LogManager
Caused by: java.lang.ClassNotFoundException: org.apache.log4j.LogManager
我把org.springframework.asm-3.1.0.RELEASE.jar 导入,
到http://logging.apache.org/log4j/1.2/download.html下载:log4j-1.2.17.zip
重新启动tomcat:继续报错
Caused by: java.io.FileNotFoundException: Could not open ServletContext resource [/WEB-INF/applicationContext.xml] 说找不到这个文件。
第六步:他报错这么久了,我们试图跟踪下代码
1、首先从listener下手,服务器会加载监听器也就是web.xml里面的listener类:org.springframework.web.context.ContextLoaderListener
既然他是listener,服务器监听的时候,会调用contextInitialized方法:
/**
* Initialize the root web application context.
*/
public void contextInitialized(ServletContextEvent event) {
this.contextLoader = createContextLoader();
if (this.contextLoader == null) {
this.contextLoader = this;
}
this.contextLoader.initWebApplicationContext(event.getServletContext());
}
我们可以看出他会使用initWebApplicationContext方法,对根上下文进行载入和初始化
2、继续跟踪到ContextLoader类中的initWebApplicationContext()方法
public WebApplicationContext initWebApplicationContext(ServletContext servletContext) {
if (servletContext.getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE) != null) {
throw new IllegalStateException(
"Cannot initialize context because there is already a root application context present - " +
"check whether you have multiple ContextLoader* definitions in your web.xml!");
}
Log logger = LogFactory.getLog(ContextLoader.class);
servletContext.log("Initializing Spring root WebApplicationContext");
if (logger.isInfoEnabled()) {
logger.info("Root WebApplicationContext: initialization started");
}
long startTime = System.currentTimeMillis();
try {
// Store context in local instance variable, to guarantee that
// it is available on ServletContext shutdown.
if (this.context == null) {
this.context = createWebApplicationContext(servletContext);
}
if (this.context instanceof ConfigurableWebApplicationContext) {
configureAndRefreshWebApplicationContext((ConfigurableWebApplicationContext)this.context, servletContext);
}
servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, this.context);
ClassLoader ccl = Thread.currentThread().getContextClassLoader();
if (ccl == ContextLoader.class.getClassLoader()) {
currentContext = this.context;
}
else if (ccl != null) {
currentContextPerThread.put(ccl, this.context);
}
if (logger.isDebugEnabled()) {
logger.debug("Published root WebApplicationContext as ServletContext attribute with name [" +
WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE + "]");
}
if (logger.isInfoEnabled()) {
long elapsedTime = System.currentTimeMillis() - startTime;
logger.info("Root WebApplicationContext: initialization completed in " + elapsedTime + " ms");
}
return this.context;
}
catch (RuntimeException ex) {
logger.error("Context initialization failed", ex);
servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, ex);
throw ex;
}
catch (Error err) {
logger.error("Context initialization failed", err);
servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, err);
throw err;
}
}
你设置断点,他会执行
servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, this.context);
将WebApplicationContext作为一个属性设置到servletContext,我们知道servletContext是web的上下文,可理解为web的一个存储数据的地方,可以从他的实例获取静态的html啊,图片啊等资源。
当然,你就可以通过servletContext来获取spring的applicationContext了。
还有,上面代码:
if中的configureAndRefreshWebApplicationContext((ConfigurableWebApplicationContext)this.context, servletContext);这行代码
protected void configureAndRefreshWebApplicationContext(ConfigurableWebApplicationContext wac, ServletContext sc) {
if (ObjectUtils.identityToString(wac).equals(wac.getId())) {
// The application context id is still set to its original default value
// -> assign a more useful id based on available information
String idParam = sc.getInitParameter(CONTEXT_ID_PARAM);
if (idParam != null) {
wac.setId(idParam);
}
else {
// Generate default id...
if (sc.getMajorVersion() == 2 && sc.getMinorVersion() < 5) {
// Servlet <= 2.4: resort to name specified in web.xml, if any.
wac.setId(ConfigurableWebApplicationContext.APPLICATION_CONTEXT_ID_PREFIX +
ObjectUtils.getDisplayString(sc.getServletContextName()));
}
else {
wac.setId(ConfigurableWebApplicationContext.APPLICATION_CONTEXT_ID_PREFIX +
ObjectUtils.getDisplayString(sc.getContextPath()));
}
}
}
// Determine parent for root web application context, if any.
ApplicationContext parent = loadParentContext(sc);
wac.setParent(parent);
wac.setServletContext(sc);
String initParameter = sc.getInitParameter(CONFIG_LOCATION_PARAM);
if (initParameter != null) {
wac.setConfigLocation(initParameter);
}
customizeContext(sc, wac);
wac.refresh();
}
你看到没有ApplicationContext parent = loadParentContext(sc);他得到了一个ApplicationContext,这个就是我们spring的上下文,我们很多工作都是从它开始,从它获取。
最重要的一个丹麦:wac.refresh();完成了对applicationContext的初始化,注册啊,封装bean的工作。
我们来解析refresh()
3、AbstractApplicationContext中refresh()
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// Prepare this context for refreshing.
prepareRefresh();
// Tell the subclass to refresh the internal bean factory.
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// Prepare the bean factory for use in this context.
prepareBeanFactory(beanFactory);
try {
// Allows post-processing of the bean factory in context subclasses.
postProcessBeanFactory(beanFactory);
// Invoke factory processors registered as beans in the context.
invokeBeanFactoryPostProcessors(beanFactory);
// Register bean processors that intercept bean creation.
registerBeanPostProcessors(beanFactory);
// Initialize message source for this context.
initMessageSource();
// Initialize event multicaster for this context.
initApplicationEventMulticaster();
// Initialize other special beans in specific context subclasses.
onRefresh();
// Check for listener beans and register them.
registerListeners();
// Instantiate all remaining (non-lazy-init) singletons.
finishBeanFactoryInitialization(beanFactory);
// Last step: publish corresponding event.
finishRefresh();
}
catch (BeansException ex) {
// Destroy already created singletons to avoid dangling resources.
destroyBeans();
// Reset 'active' flag.
cancelRefresh(ex);
// Propagate exception to caller.
throw ex;
}
}
}
这个方法这个网址说的很好:http://www.ibm.com/developerworks/cn/java/j-lo-spring-principle/ 你可以搜索:“如何创建 BeanFactory 工厂”。直接定位到想看的地方。
代码1:ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
refreshBeanFactory();
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
if (logger.isDebugEnabled()) {
logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory);
}
return beanFactory;
}
这里有一个refreshBeanFactory();
代码2:refreshBeanFactory();
protected final void refreshBeanFactory() throws BeansException {
if (hasBeanFactory()) {
destroyBeans();
closeBeanFactory();
}
try {
DefaultListableBeanFactory beanFactory = createBeanFactory();
beanFactory.setSerializationId(getId());
customizeBeanFactory(beanFactory);
loadBeanDefinitions(beanFactory);
synchronized (this.beanFactoryMonitor) {
this.beanFactory = beanFactory;
}
}
catch (IOException ex) {
throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
}
}
这个方法实现了 AbstractApplicationContext 的抽象方法 refreshBeanFactory,这段代码清楚的说明了 BeanFactory 的创建过程,loadBeanDefinitions(beanFactory) 将找到答案,这个方法将开始加载、解析 Bean 的定义,也就是把用户定义的数据结构转化为 Ioc 容器中的特定数据结构。(抄自上面那个网址)
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
// Create a new XmlBeanDefinitionReader for the given BeanFactory.
XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
// Configure the bean definition reader with this context's
// resource loading environment.
beanDefinitionReader.setEnvironment(this.getEnvironment());
beanDefinitionReader.setResourceLoader(this);
beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));
// Allow a subclass to provide custom initialization of the reader,
// then proceed with actually loading the bean definitions.
initBeanDefinitionReader(beanDefinitionReader);
loadBeanDefinitions(beanDefinitionReader);
}
跟踪这句话: loadBeanDefinitions(beanDefinitionReader);
protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws IOException {
String[] configLocations = getConfigLocations();
if (configLocations != null) {
for (String configLocation : configLocations) {
reader.loadBeanDefinitions(configLocation);
}
}
}
这句话: reader.loadBeanDefinitions(configLocation);
这里的configLocation就是要读取xml文件。
在这个类里面有这个一个方法:
/**
* The default location for the root context is "/WEB-INF/applicationContext.xml",
* and "/WEB-INF/test-servlet.xml" for a context with the namespace "test-servlet"
* (like for a DispatcherServlet instance with the servlet-name "test").
*/
@Override
protected String[] getDefaultConfigLocations() {
if (getNamespace() != null) {
return new String[] {DEFAULT_CONFIG_LOCATION_PREFIX + getNamespace() + DEFAULT_CONFIG_LOCATION_SUFFIX};
}
else {
return new String[] {DEFAULT_CONFIG_LOCATION};
}
}
}
看看上面的说明,默认的是读取上面两个配置文件,看看applicatinContext.xml 出现了。具体细节可以继续跟踪下去
直到XmlBeanDefinitionReader底下:这个方法报错
/**
* Load bean definitions from the specified XML file.
* @param encodedResource the resource descriptor for the XML file,
* allowing to specify an encoding to use for parsing the file
* @return the number of bean definitions found
* @throws BeanDefinitionStoreException in case of loading or parsing errors
*/
public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException {
Assert.notNull(encodedResource, "EncodedResource must not be null");
if (logger.isInfoEnabled()) {
logger.info("Loading XML bean definitions from " + encodedResource.getResource());
}
Set<EncodedResource> currentResources = this.resourcesCurrentlyBeingLoaded.get();
if (currentResources == null) {
currentResources = new HashSet<EncodedResource>(4);
this.resourcesCurrentlyBeingLoaded.set(currentResources);
}
if (!currentResources.add(encodedResource)) {
throw new BeanDefinitionStoreException(
"Detected cyclic loading of " + encodedResource + " - check your import definitions!");
}
try {
InputStream inputStream = encodedResource.getResource().getInputStream();
try {
InputSource inputSource = new InputSource(inputStream);
if (encodedResource.getEncoding() != null) {
inputSource.setEncoding(encodedResource.getEncoding());
}
return doLoadBeanDefinitions(inputSource, encodedResource.getResource());
}
finally {
inputStream.close();
}
}
catch (IOException ex) {
throw new BeanDefinitionStoreException(
"IOException parsing XML document from " + encodedResource.getResource(), ex);
}
finally {
currentResources.remove(encodedResource);
if (currentResources.isEmpty()) {
this.resourcesCurrentlyBeingLoaded.remove();
}
}
}
说明他找不到这个xml文件。。。
XmlBeanDefinitionReader这个类继承AbstractBeanDefinitionReader,而AbstractBeanDefinitionReader又实现了接口BeanDefinitionReader,这个接口的作用要求不同的实现类来读取不同的配置文件,像这里XmlBeanDefinitionReader就是要读取xml文件了,如果要读取Properties文件,就需要实现能够读取properties根式的类:org\springframework\beans\factory\support包底下:PropertiesBeanDefinitionRead.java。
那么这些类的作用是什么?
1、读取不同格式的文件,并把文件内容映射到BeanDefinition中,然后把映射后的BeanDefinition注册到一个BeanDefinitionRegistry,之后BeanDefinitionRegistry完成了Bean的注册和加载。大部分工作在于解析文件、映射装配BeanDefinition之类的工作(这个由BeanDefinitionReader来做),BeanDefinitionRegistry只负责保管。
2、spring每一个被管理的bean对象,在容器中都有一个BeanDefinition的实例与之对应,该实例负责保存对象的所
有必要信息,包括对应的对象的class类型、是否抽象、构造方法参数以及其他属性。当客户端向BeanFactory请求对象的时候,BeanFactory会通过这些信息为客户端返回一个完备可用的对象实例。
3、BeanFactory跟我们打交道,你向它要什么它就给你什么,对于你要的东西在哪里,对于我们是透明的,这个放置哪里怎么放的问题BeanDefinitionRegistry帮她解决了。
对于读取xml文件工作大概是这样的:(这段话和代码参考自:《spring揭秘》)
package spring;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
public class Test {
public static void main(String[] args) {
//对我们客户端来说,我们只要与BeanFactory打交道
//这是beanFsctory的实现类,他间接的实现了BeanFactory,还实现了BeanDefinitionRegistry,所以他完成把bean注册到容器的工作,还提供beanfacotry实例
DefaultListableBeanFactory beanRegistry = new DefaultListableBeanFactory();
BeanFactory container = (BeanFactory)bindViaXMLFile(beanRegistry);
container.getBean("你想要的类的名称");//在xml文件配置的bean名称
}
public static BeanFactory bindViaXMLFile(BeanDefinitionRegistry registry) {
XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(registry);
reader.loadBeanDefinitions("你的applicationContext.xml文件");
//XmlBeanDefinitionReader读取了xml文件,并能解析,封装bean对象的class类型,构造方法等信息到一个BeanDefinition中
return (BeanFactory) registry;
}
}
第七步:配置applicationContext.xml文件
1、他就是上面的web.xml中listener——ContextLoaderListener这个类需要的。
2、上面说到把配置文件中的bean里面的信息注册到容器中,形如:
<bean id="User" class="org.test.User"/>//这样就可以了,
但是如果我需要很多个的话,配置文件会臃肿,下面我们使用annocation+classpath-scanning功能解决这个问题。
3、这时候请你打开spring的doc文档:spring-framework-3.1.0.RELEASE-with-docs\docs\spring-framework-reference\html\beans.html,这里面讲的很清楚。
4、我们来拷贝里面的xml配置文件吧,下面我们使用annocation+classpath-scanning,注意了classpath-scanning他会默认的使用一中命名规则来匹配,比如你的类名为UserGroup,他bean的定义名称为userGroup,相当于<bean id="userGroup" class=""UserGroup/>。对于依赖注入使用的注解有两个1、@Autowired和@Resource,两者的区别在于,一个是默认使用Type来匹配,一个是根据name来匹配。
@Autowired
private BeanFactory b;//他去注册的bean中找类型为BeanFactory的进行注入
@Resource
private BeanFactory c;//他去bean中查找id="beanFactory"的那个
@Autowired使用时候,如果在xml配置文件中如果有两个bean如下
<bean id="a" class="BeanFacotryA"/>
<bean id="c" class="BeanFacotryB"/>
BeanFacotryA和BeanFacotryB都实现了BeanFactory,那注入BeanFactory的时候,
他叫容器帮你注入a?还是c实例了?所以他需要一个@Qualifier配合,
@Autowired
@Qualifier("a")
private BeanFactory b;
我们的applicationContext.xml就是下面的
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd"> <context:component-scan base-package="spring"></context:component-scan> </beans>
对于下面这个:
<context:component-scan base-package="spring">他会去spring这个源码包底下去搜索有@compone的类,把他当做bean,注入到容器中。这个就厉害了,我们不需要在xml中一个一个去配置bean了。
第八步:重新启动服务器,你发现他继续报错,找不到applicationContext.xml。
注意了,我的applicationContext.xm放在classpath底下,所以他找不到,于是我在web.xml添加下面几行来告诉spring的那个listener去这个地方找applicationContext.xml
.......
</welcome-file-list>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
</context-param>
<!--配置listener -->
..............
..............
第九步:你重新启动他报错,“java.lang.NoClassDefFoundError: org/springframework/expression/PropertyAccessor”,我们引入org.springframework.expression-3.1.0.RELEASE.jar包
第十步:重新启动,又报错:Could not open ServletContext resource [/WEB-INF/controller-servlet.xml],这个文件配置了controller的转发的映射关系。我们到spring的doc目录底下去找找。spring-framework-3.1.0.RELEASE-with-docs/docs/spring-framework-reference/html/mvc.html#mvc-servlet这个网页里面看看。
controll-servlet.xml如下:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd"> <context:component-scan base-package="spring"/> </beans>
最后web.xml文件如下:
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5"> <display-name>spring-mvc</display-name> <!--配置欢迎界面 --> <welcome-file-list> <welcome-file>index.html</welcome-file> <welcome-file>index.htm</welcome-file> <welcome-file>index.jsp</welcome-file> <welcome-file>default.html</welcome-file> <welcome-file>default.htm</welcome-file> <welcome-file>default.jsp</welcome-file> </welcome-file-list> <context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:applicationContext.xml</param-value> </context-param> <!--配置listener --> <!--在这里可以配置spring的监听器,启动的时候需要把spring中的bean都注册到spring容器中 ,当然他需要读取一个配置文件applicationContext.xml --> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <!--配置log包 --> <listener> <listener-class>org.springframework.web.util.Log4jConfigListener</listener-class> </listener> <!--配置filter对编码进行转换 --> <filter> <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class> <filter-name>encodingFilter</filter-name> <init-param> <param-name>encoding</param-name> <param-value>UTF-8</param-value> </init-param> <init-param> <param-name>forceEncoding</param-name> <param-value>true</param-value><!-- 强制进行转码 --> </init-param> </filter> <filter-mapping> <filter-name>encodingFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <!--配置servlet --> <!--我们希望spring的控制器比其他servlet优先启动,所以你需要设置load-on-startup 这个东西:值越小越先启动(0-5),没有或者为负数的时候,servlet被选用的时候才加载--> <servlet> <servlet-name>controller</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <load-on-startup>2</load-on-startup> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:controller-servlet.xml</param-value> </init-param> </servlet> <servlet-mapping> <servlet-name>controller</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> </web-app>
启动服务器,终于不报错了。。
-=-=-=-=-=-=-=-=-=-=-=-=--=-=-spring mvc基本配置完成-=-=-=-=-=-=-=-=-=-=
配置日志,开发人员查看debug日志
1、我们发现我们启动tomcat的并没有打印出出spring包里面写的日志内容,日志内容对开发人员跟踪错误是有帮助的,所以我们先加入日志。
2、日志的三种选择:
1、从jdk1.4开始他有自带的logging这个日志类,用来记录日志。由于他的扩展性差、易用性差所以出现了Log4j控件
2、见上面的截图,有log4j这个jar包吧。
3、commons-logging,他是apache commons底下的一个类库,这个比较通用,他可以判断如果有Log4j,他就把日志输出功能交给Log4j去处理,如果没有Log4j功能,他就交给了jdk的日志功能去处理。
3、配置文件log4j.properties(默认名称)
log4j.rootLogger=INFO, stdout log4j.categroy.org.hibernate.SQL=DEBUG log4j.category.org.springframework=INFO log4j.appender.stdout=org.apache.log4j.ConsoleAppender log4j.appender.stdout.layout=org.apache.log4j.PatternLayout log4j.appender.stdout.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss,SSS} [%c]-[%p] %m%n
第一行,把Info的信息输出给stdout中
第二、三行,以log4j.category开头,后面跟着包名,就是配置包底下的日志输出,看上面有配置spring包底下的日志输出
第四行,输出到哪里?输出到控制台
第五行和第六航,输出的格式和布局
这个只是输出到控制台,对于tomcat底下跟踪日志,我们设置更高级别,并使用日志文件来输出,提供以后查看(以后再说。)
这时候你可以看到一系列的日志输出。
2012-06-02 15:02:58,866 [org.springframework.web.context.ContextLoader]-[INFO] Root WebApplicationContext: initialization started 2012-06-02 15:02:58,962 [org.springframework.web.context.support.XmlWebApplicationContext]-[INFO] Refreshing Root WebApplicationContext: startup date [Sat Jun 02 15:02:58 CST 2012]; root of context hierarchy 2012-06-02 15:02:59,024 [org.springframework.beans.factory.xml.XmlBeanDefinitionReader]-[INFO] Loading XML bean definitions from class path resource [applicationContext.xml] 2012-06-02 15:02:59,310 [org.springframework.beans.factory.config.PropertyPlaceholderConfigurer]-[INFO] Loading properties file from class path resource [hibernate.properties] 2012-06-02 15:02:59,326 [org.springframework.beans.factory.support.DefaultListableBeanFactory]-[INFO] Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@534a5d1b: defining beans [org.springframework.context.annotation.internalConfigurationAnnotationProcessor,org.springframework.context.annotation.internalAutowiredAnnotationProcessor,org.springframework.context.annotation.internalRequiredAnnotationProcessor,org.springframework.context.annotation.internalCommonAnnotationProcessor,org.springframework.beans.factory.config.PropertyPlaceholderConfigurer#0,dataSource,org.springframework.context.annotation.ConfigurationClassPostProcessor$ImportAwareBeanPostProcessor#0]; root of factory hierarchy 2012-06-02 15:02:59,340 [com.mchange.v2.log.MLog]-[INFO] MLog clients using log4j logging.
spring集成hibernate
1、spring对ORM解决方案主要有三个:统一了管理方式,无论你是使用JDBC还是ORM,我们都只要使用spring提供给我们的接口即可,对底层JDBC或者ORM是透明的;spring提供了统一的事务管理了,我们只要使用它的事务管理机制就可以了,不用在代码中写什么事务启动,事务回滚的代码;异常统一处理方式(不同的数据库报的异常不相同,如果把异常交给用户处理,他们会累死,所以spring对不同的异常他都进行了封装处理)
2、一般我们写hibernate,有几个步骤:
1、获得session
2、通过session获取事务开始,Transaction tx = session.beginTransaction();
3、写我们的业务逻辑代码(增删改查操作)
4、事务提交 tx.commit();
5、关闭session
6、如果有异常,需要进行回滚catch(异常) {回滚} finally{...}
在软件开发过程我们很强调把不变得东西给抽象出来,作为一个单独的处理代码。那么,哪里不变?是不是除了业务逻辑代码之外,其他代码都是一样的。所以我们考虑把其他的单独抽出来(这里可以使用设计模式中的模板方法)
有一个模板是这样的
模板方法(一个回调对象, session) {
1、获得session
2、利用回调对象,处理业务逻辑
3、处理异常
}
对于我们用户来说,只要写一个回调对象,处理业务逻辑即可。。异常代码、回滚代码都不用我们来写。
—————以上就是HibernateTemplate核心模板方法,这个类做了这一个封装抽象的工作。
我们发现上面模板方法已经对异常进行的处理,这个就是前面说的spring统一了异常处理。
这个模板提供了4组查询方法:
1、get模板办法——根据id到数据库查询对象,如果没有则方法null
2、load模板办法——根据id到数据库加载对象,如果没有则抛出异常,而不是null
3、find模板方法
4、iterate模板方法
对于get和load区别说一下:来自csdn
最大的区别:
1>load先到缓存中去查,如果没有则返回一个代理对象(不马上到DB中去找),等 后面
使用这个代理对象操作的时候,才到DB中。如还没有找到return Exception
2>get先到缓存中去查,(注意这里不是返回一个代理对象)如果没有就到DB中去查,还没有的话return null
总之,如果你确定DB中有这个对象就用load(),不确定就用get()(这样效率高)
3、hiberateTemplate如果获取session的?
Hiberante中获取session是根据SessionFactory来的,一切都是从sessionFactory开始,这个类他相当于一个数据源,所以我们的hiberanteTemplate一定需要必须需要用到他。
SessionFactory从哪里来?Spring提供了一个LocalSessionFacotryBean,你只要把数据源注入给他,调用他的getObject方法,就有sessionFactory对象了。
所以很经常见到配置文件:
<bean id="sessionFacotry" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
//上面这里就是数据源了
</bean>
当然你如果想要用注解的也有,AnnotationSessionFactoryBean,你可以service层使用注解注入。
4、下面我们来配置
在我们下载的
Hibernate ORM 4.1.2 Release这个jar中hibernate-release-4.1.2.Final\lib\optional\c3p0找到c3p0-0.9.1.jar,加入到lib底下。
applicationcontext.xml需要配置数据源以及占位符文件
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd"> <context:component-scan base-package="spring"></context:component-scan> <!--告诉spring去哪里获取占位符的配置文件 --> <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"> <property name="locations"> <list> <value>classpath:hibernate.properties</value> </list> </property> </bean> <!--配置数据源 --> <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close"> <property name="driverClass"><value>${db.driver}</value></property> <property name="jdbcUrl"><value>${db.url}</value></property> <property name="user"><value>${db.user}</value></property> <property name="password"><value>${db.password}</value></property> </bean> <!--数据源提供给spring的sessionFactory,这里我们要求是使用注解方式,所以spring要选择AnnotationSessionFactoryBean来获取sessionFactory 当然你如果要用xml的,使用LoaclSessionFactoryBean来配置,当然这里的AnnotationSessionFactoryBean是继承LoaclSessionFactoryBean --> <bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean"> <property name="dataSource" ref="dataSource"/> <!--让spring帮你扫描这个包底下的所有类,主要作用扫描跟数据库对应的实体类 --> <property name="packagesToScan" value="spring.model"/> <!--设置hibernate的属性 --> <property name="hibernateProperties"> <value> hibernate.dialect=org.hibernate.dialect.MySQLDialect hibernate.show_sql=true </value> </property> </bean> </beans>
占位符hibernate.properties文件,放在classpath目录下
db.driver=com.mysql.jdbc.Driver db.url=jdbc:mysql://127.0.0.1:3306?useUnicode=true&characterEncoding=utf-8 db.user=root db.password=root
上面报错了,需要引入:org.springframework.orm-3.1.0.RELEASE.jar(作为hibernate关联)、org.springframework.transaction-3.1.0.RELEASE.jar(事务、dao支持)、hibernate-core-4.1.2.Final.jar(hibernate的必须的)、hibernate-jpa-2.0-api-1.0.1.Final.jar(hibernate必须的)、jboss-transaction-api_1.1_spec-1.0.0.Final.jar(hibernate必须的)
这时候你启动下,发现报错:
java.lang.NoClassDefFoundError: Lorg/hibernate/cache/CacheProvider;
百度,google下:
有:写道
原先:<bean id="sessionFactory"
class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
改成:<bean id="sessionFactory"
class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
问题解决,发现可以正常使用了
所以我们更改下,applicationContext.xml的配置
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd"> <context:component-scan base-package="spring"></context:component-scan> <!--告诉spring去哪里获取占位符的配置文件 --> <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"> <property name="locations"> <list> <value>classpath:hibernate.properties</value> </list> </property> </bean> <!--配置数据源 --> <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close"> <property name="driverClass"><value>${db.driver}</value></property> <property name="jdbcUrl"><value>${db.url}</value></property> <property name="user"><value>${db.user}</value></property> <property name="password"><value>${db.password}</value></property> </bean> <!--数据源提供给spring的sessionFactory,这里我们要求是使用注解方式, 所以spring要选择AnnotationSessionFactoryBean来获取sessionFactory 当然你如果要用xml的,使用LoaclSessionFactoryBean来配置, 当然这里的AnnotationSessionFactoryBean是继承LoaclSessionFactoryBean 但是发现,hibernate4版本更改了,会报错误“java.lang.NoClassDefFoundError: Lorg/hibernate/cache/CacheProvider;” --> <!-- <bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean"> <property name="dataSource" ref="dataSource"/> 让spring帮你扫描这个包底下的所有类,主要作用扫描跟数据库对应的实体类 <property name="packagesToScan" value="spring.model"/> 设置hibernate的属性 <property name="hibernateProperties"> <value> hibernate.dialect=org.hibernate.dialect.MySQLDialect hibernate.show_sql=true </value> </property> </bean> --> <!--看看源码中的这段话,其实它更接近于annotation,你跟进代码,发现他是支持注解的 <p><b>NOTE:</b> This variant of LocalSessionFactoryBean requires Hibernate 4.0 * or higher. It is similar in role to the same-named class in the <code>orm.hibernate3</code> * package. However, in practice, it is closer to <code>AnnotationSessionFactoryBean</code> * since its core purpose is to bootstrap a <code>SessionFactory</code> from annotation scanning. --> <bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean"> <property name="dataSource" ref="dataSource"/> <!-- 让spring帮你扫描这个包底下的所有类,主要作用扫描跟数据库对应的实体类 --> <property name="packagesToScan" value="spring.model"/> <!-- 设置hibernate的属性 --> <property name="hibernateProperties"> <value> hibernate.dialect=org.hibernate.dialect.MySQLDialect hibernate.show_sql=true </value> </property> </bean> </beans>
我们发现,他还是报错,少了包,继续添加:
当然,上面jdbc.driver的jar包还没有加入。dom4j-1.6.1.jar(hibernate必须的)、hibernate-commons-annotations-4.0.1.Final(hibernate必须的)、jboss-logging-3.1.0.GA(hibernate必须的)antlr-2.7.7(hibernate必须的)
对了,我们的mysql jdbc的驱动还没加入了
http://dev.mysql.com/downloads/connector/j/5.1.html地址,下一个吧。(mysql-connector-java-5.1.20.zip),解压开mysql-connector-java-5.1.20-bin.jar,放入到lib底下。
重启一下,哈哈,发现没有问题,大功告成。
等等,我们还有哪些没配了?事务,事务,对了,还有事务没有配置。事务的配置,当你在进行配置事务的时候,发现自动提示标签,哦,,1、你忘记加入spring的重要的东西,AOP的jar包,还有/org.springframework.aspects-3.1.0.RELEASE。2、applicationContext.xml刚开始那段需要修改,需要引入标签头。这个在spring的文档中有。
applicationContext.xml里程碑
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd"> <context:component-scan base-package="spring"></context:component-scan> <!--告诉spring去哪里获取占位符的配置文件 --> <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"> <property name="locations"> <list> <value>classpath:hibernate.properties</value> </list> </property> </bean> <!--配置数据源 --> <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close"> <property name="driverClass"><value>${db.driver}</value></property> <property name="jdbcUrl"><value>${db.url}</value></property> <property name="user"><value>${db.user}</value></property> <property name="password"><value>${db.password}</value></property> </bean> <!--数据源提供给spring的sessionFactory,这里我们要求是使用注解方式, 所以spring要选择AnnotationSessionFactoryBean来获取sessionFactory 当然你如果要用xml的,使用LoaclSessionFactoryBean来配置, 当然这里的AnnotationSessionFactoryBean是继承LoaclSessionFactoryBean 但是发现,hibernate4版本更改了,会报错误“java.lang.NoClassDefFoundError: Lorg/hibernate/cache/CacheProvider;” --> <!-- <bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean"> <property name="dataSource" ref="dataSource"/> 让spring帮你扫描这个包底下的所有类,主要作用扫描跟数据库对应的实体类 <property name="packagesToScan" value="spring.model"/> 设置hibernate的属性 <property name="hibernateProperties"> <value> hibernate.dialect=org.hibernate.dialect.MySQLDialect hibernate.show_sql=true </value> </property> </bean> --> <!--看看源码中的这段话,其实它更接近于annotation,你跟进代码,发现他是支持注解的 <p><b>NOTE:</b> This variant of LocalSessionFactoryBean requires Hibernate 4.0 * or higher. It is similar in role to the same-named class in the <code>orm.hibernate3</code> * package. However, in practice, it is closer to <code>AnnotationSessionFactoryBean</code> * since its core purpose is to bootstrap a <code>SessionFactory</code> from annotation scanning. --> <bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean"> <property name="dataSource" ref="dataSource"/> <!-- 让spring帮你扫描这个包底下的所有类,主要作用扫描跟数据库对应的实体类 --> <property name="packagesToScan" value="spring.model"/> <!-- 设置hibernate的属性 --> <property name="hibernateProperties"> <value> hibernate.dialect=org.hibernate.dialect.MySQLDialect hibernate.show_sql=true </value> </property> </bean> <!--事务配置 --> <bean id="txManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager"> <property name="sessionFactory" ref="sessionFactory"></property> </bean> <aop:config> <aop:advisor pointcut="execution(* spring.service.*Service.*(..))" advice-ref="txAdvice"/> </aop:config> <tx:advice id="txAdvice" transaction-manager="txManager"> <tx:attributes> <tx:method name="get*" read-only="true"/> <tx:method name="query*" read-only="true"/> <tx:method name="find*" read-only="true"/> <tx:method name="load*" read-only="true"/> <tx:method name="*" rollback-for="Exception"/> </tx:attributes> </tx:advice> </beans>
把org.springframework.aop-3.1.0.RELEASE.jar、org.springframework.aspects-3.1.0.RELEASE.jar加入lib底下
启动发现你少了一包aopalliance.jar(spring的依赖包从3.0后就使用maven了,不包含在jar包中)
下载地址:http://sourceforge.net/projects/aopalliance/files/aopalliance/1.0/aopalliance.zip/download
还有,下载aspectj weaver.jar http://www.eclipse.org/downloads/download.php?file=/tools/aspectj/aspectj-1.6.12.jar
org.springframework.jdbc-3.1.0.RELEASE.jar把这里的三个都放入jar底下。
在启动下,发现没有问题,又一次的大功告成。。
此时的jar文件:
==================结束配置======================
可能我们需要使用jsp的标签库:jstl.jar和standard.jar
这里有下载的:http://archive.apache.org/dist/jakarta/
到此为止,上面的配置算是最简单的包了。
如果你需要用hibernate的验证框架:
WEB框架还需要做哪些了?
1、日志管理
之前已经给出了log相关操作,对于关键的业务跟踪需要在后台保存做日志记录,以便后续跟踪
部署的时候:需要去掉没有必要的日志打印,比如hibernate的日志输出,struts2的日志输出,都改成false
2、前台、后台数据校验
见我另一篇博文“数据校验:jquery前端验证和hibernate服务端验证”
3、业务逻辑测试
见我另一篇博文“spring测试“
4、异常统一处理
404、500错误要转到哪里,逻辑错误要转到哪个页面显示
比如我写的spring mvc:
public class BusinessException extends Exception {
private Throwable cause;
public BusinessException(String msg) {
super(msg);
}
public BusinessException(String msg, Throwable ex) {
super(msg);
this.cause = ex;
}
public Throwable getCause() {
return (this.cause == null ? this : this.cause);
}
public String getMessage() {
String message = super.getMessage();
Throwable cause = getCause();
if (cause != null) {
message = message + ";BusinessException Exception is " + cause;
}
return message;
}
public void printStackTrace(PrintStream ps) {
if (getCause() == null) {
super.printStackTrace(ps);
} else {
ps.println(this);
getCause().printStackTrace(ps);
}
}
public void printStackTrace(PrintWriter pw) {
if (getCause() == null) {
super.printStackTrace(pw);
} else {
pw.println(this);
getCause().printStackTrace(pw);
}
}
public void printStackTrace() {
printStackTrace(System.err);
}
}
public class ExceptionHandler implements HandlerExceptionResolver {
public ModelAndView resolveException(HttpServletRequest request,
HttpServletResponse response, Object handler, Exception ex) {
Map<String, Object> model = new HashMap<String, Object>();
model.put("ex", ex);
// 根据不同错误转向不同页面
if(ex instanceof BusinessException) {
return new ModelAndView("error-business", model);
}/*else if(ex instanceof ParameterException) {
return new ModelAndView("error-parameter", model);
} */
else {
return new ModelAndView("error", model);
}
}
}
5、拦截器
public class FromDupInterceptor implements HandlerInterceptor {
private Logger log = Logger.getLogger(FromDupInterceptor.class);
public void afterCompletion(HttpServletRequest arg0,
HttpServletResponse arg1, Object arg2, Exception arg3)
throws Exception {
log.info("==============执行顺序: afterCompletion================");
}
public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1,
Object arg2, ModelAndView arg3) throws Exception {
log.info("==============执行顺序: postHandle================");
}
public boolean preHandle(HttpServletRequest arg0, HttpServletResponse arg1,
Object arg2) throws Exception {
log.info("==============执行顺序: preHandle================");
return true;
}
}
<!--配置拦截器 -->
<mvc:interceptors>
<!-- 多个拦截器,顺序执行 -->
<mvc:interceptor>
<!--这里的path符号有/*, /**, *, ? 等,对于student.do?param=1从?开始不作为path -->
<mvc:mapping path="/student/save*" /><!-- 如果不配置或/*,将拦截所有的Controller -->
<bean class="spring.common.interceptor.FromDupInterceptor"></bean>
</mvc:interceptor>
</mvc:interceptors>
在springmvc的控制器配置文件中,你就可以这么配置拦截器,具体你在拦截器里面做什么,自己去做
6、避免重复提交
1、js方面:第一次提交表单的时候禁用提交按钮;利用onsubmit事件处理程序取消后续的表单提交操作
2、使用token
Hibernate——让我们来一起读读官方文档吧。
对于这块,标出我平时不大注意的问题!!
chapter1
对于java.uitl.Date,Hibernate不知道要要转那个,所有的时间信息都给你进行了timestamp转换。
<hibernate-mapping package="org.hibernate.tutorial.domain"> <class name="Event" table="EVENTS"> <id name="id" column="EVENT_ID"> <generator class="native"/> </id> <property name="date" type="timestamp" column="EVENT_DATE"/> <property name="title"/> </class> </hibernate-mapping>
2、写道
A org.hibernate.SessionFactory is used to obtain org.hibernate.Session instances. A org.hibernate.Session represents a single-threaded unit of work. The org.hibernate.SessionFactory is a thread-safe global object that is instantiated once.
session通过getCurrentSession被创建出来,并由hibernate帮忙绑定到当前线程上,一旦事务结束、提交、回滚,session就自动取消绑定,并关闭它,如果你重新调用getCurrentSession,他获取新的一个session。
3、比较下下面两段代码的区别,并说明结果:(实验验证通过)
Session session = HibernateUtil.getSessionFactory().getCurrentSession();
session.beginTransaction();
Person aPerson = (Person) session.load(Person.class, personId);
Event anEvent = (Event) session.load(Event.class, eventId);
aPerson.getEvents().add(anEvent);
session.getTransaction().commit();
}
上面这段由于session未关闭,且load出来的对象处于持久状态,你调用了.aPerson.getEvents().add方法,此持久态的对象发生变化,对于这种hibernate会自动更新数据库。
private void addPersonToEvent(Long personId, Long eventId) {
Session session = HibernateUtil.getSessionFactory().getCurrentSession();
session.beginTransaction();
Person aPerson = (Person) session
.createQuery("select p from Person p left join fetch p.events where p.id = :pid")
.setParameter("pid", personId)
.uniqueResult(); // Eager fetch the collection so we can use it detached
Event anEvent = (Event) session.load(Event.class, eventId);
session.getTransaction().commit();
// End of first unit of work
aPerson.getEvents().add(anEvent); // aPerson (and its collection) is detached
// Begin second unit of work
Session session2 = HibernateUtil.getSessionFactory().getCurrentSession();
session2.beginTransaction();
session2.update(aPerson); // Reattachment of aPerson
session2.getTransaction().commit();
}
由于在调用add方法之前session已经关闭,此时的对象是游离态,他如何改变都不会自动更新同步到数据库,只有手动使用update的方式,他才帮忙更新数据库
chapter 2
1、什么是sessionFactory?他是一切数据的开始,
2、它是一个永久的存储区,与单个数据库对应
3、维持二级缓存
4、生成session实例
5、是一个hibernate连接的客户端?//不知道怎么翻译了 A factory for, and pool of, JDBC connections 是连接池的一个工厂
A thread-safe, immutable cache of compiled mappings for a single database. A factory for org.hibernate.Session instances. A client of org.hibernate.connection.ConnectionProvider. Optionally maintains a second level cache of data that is reusable between transactions at a process or cluster level.
2、什么是Session?
2、生命周期短,是应用层和存储层的一个会话对象
3、封装了jdbc
4、是事务的工厂
5、维持着一级缓存(持久态对象和集合)
A single-threaded, short-lived object representing a conversation between the application and the persistent store. Wraps a JDBC java.sql.Connection. Factory for org.hibernate.Transaction. Maintains a first level cache of persistent the application's persistent objects and collections; this cache is used when navigating the object graph or looking up objects by identifier
chapter 3 这里讲解配置的
1、SessionFactory哪里来?他是通过Configuration来获取的,这个对象他可以读取xml的配置文件,来得到sessionFactory
You can obtain a org.hibernate.cfg.Configuration instance by instantiating it directly and specifying XML mapping documents. If the mapping files are in the classpath, use addResource(). For example:
Configuration cfg = new Configuration()
.addResource("Item.hbm.xml")
.addResource("Bid.hbm.xml");
Hibernate will then search for mapping files named /org/hibernate/auction/Item.hbm.xml
and/org/hibernate/auction/Bid.hbm.xml
in the classpath.
如何获取sessionFactory了?
SessionFactory sessions = cfg.buildSessionFactory();
第四章 持久类
1、所有的持久类都必须有默认的构造方法,有了它,hibernate才能使用反射机制来创建对象。意思是说需要注意的
public ClassA()//构造方法不能带有参数,有参数他会报错。。。
例如:
org.hibernate.InstantiationException: No default constructor for entity: spring.model.Student
2、尽量要把实例类添加equals方法和hashCode方法,因为hibernate会帮你在一个session scope根据数据库中的id来判断两个实力是否相等,这个对于set中的对象操作是很重要的。当存在多个session scope的操作时候,或者实例处于游离态的时候,hibernate不会帮你判断。。这时候你必须使用equals方法来判断了
总之一句话,对于model需要天假equals方法和hashCode方法。比较使用类的属性来判断
public class Cat {
...
public boolean equals(Object other) {
if (this == other) return true;
if ( !(other instanceof Cat) ) return false;
final Cat cat = (Cat) other;
if ( !cat.getLitterId().equals( getLitterId() ) ) return false;
if ( !cat.getMother().equals( getMother() ) ) return false;
return true;
}
public int hashCode() {
int result;
result = getMother().hashCode();
result = 29 * result + getLitterId();
return result;
}
}
intend to put instances of persistent classes in a Set (the recommended way to represent many-valued associations); and
intend to use reattachment of detached instances
Spring MVC那些事——基于注解
1、从tomcat的web.xml配置文件说起——控制器
<servlet>
<servlet-name>controller</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>2</load-on-startup>
</servlet>
我们在上面的配置文件中有上面这行org.springframework.web.servlet.DispatcherServlet。
a、它是什么?作用是什么?为什么tomcat要加载它?
解:因为我们要使用spring mvc框架,我们需要spring的(控制器C、视图V、逻辑层M),在MVC模型中,控制器是首当其冲的一个角色,一切从他开始。当然这里我们也不例外,我们可以把DispatcherServlet这个类看做一个控制器,他负责控制整个MVC的操作过程。
一个web链接过来交给tomcat,tomcat通过web.xml中的配置文件,如下:
<servlet>
<servlet-name>controller</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>2</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>controller</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
b、对于所有的链接都由这个控制器来处理,这个控制器接到链接之后他如何处理了?
解:一个http://www.****这样一个链接过来,他作为一个控制器,他就必须知道要找那个逻辑业务代码帮他处理。他就必须知道哪种地址能对应到哪个类(逻辑业务代码)来处理,必须要有一个“地址<--->类”对应的一张表来匹配,这个对应表的对应关系类似于map中进行的<key,value>,key代表连接、value代表这个链接被处理的那个类。这件事情是由HandleMapping这个类来管理对应关系,DispatcherServlet只是调用他就可以了。
我们知道DipatcherServlet调用HandleMapping来知道是哪一个类对这个链接进行处理,但是他并不知道精确到那个一方法,HandleMapping只精确到类,所以必须还要有一个类来帮忙对应到方法。这个类就是HandlerAdaptor
关于适配器:(看他的名字就知道是适配器,这里为什么需要用适配器了,我写出我个人看法,也不知道对不对:我们知道中国的电压是220V,美国的电压110V,你把支持110V的电脑从美国带回到国内,你一插上去,估计就立马冒火花了,因为他的电源超过他最大的范围。要处理这个问题,我们就想到了一个变压器(这个就是适配器,不改变电脑,不改变两地的电压,只是多增加一个变压器即可使用),这个变压器接受了220V,然后返回110V),这个就像HandlerAdaptor类一样,他可以接受不同的电压,返回一个可以给你使用的电压110V。
在逻辑业务类的方法,他可以返回四种类型:modelAndView、model、String、void。我们知道MVC,要把视图传给控制器DispatcherServlet(即调用完逻辑业务类后,要返回),我了个去了,你有4种返回值,我还不知道你什么时候会返回哪一个了。所以了,他就要求了,我只接受modelAndView这种返回值(110V电压),其他类型返回值(220V,110V,380V等),你自己看着办,于是就需要一个适配器,能够接受各种电压,并返回统一的110V(modelAndView类型)。
在HandlerAdaptor,他既然是适配器,他应该有一个接受各种电压的入口吧(也就是DipatcherServlet调用完HandleMapping返回给出的一个Handle逻辑类),在内部肯定有一个处理方法,返回一个统一的ModelAndView吧。
ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object Handle) throws Exception {
//1、看这里有Object Handle就是dispatcher调用HandleMapping之后的业务逻辑类给他。2、 ModleAndView也是在这里实例化的,所以我们在写业务逻辑层的时候,我们可以直接使用他。3、他返回一个统一的ModelAndView
}
c、把HandlerAdaptor替handle把ModelAndView传给了Dispatcher。Dispatcher利用这个ModleAndView返回到相应的页面(比如jsp页面)
问题1:我在Handle方法中返回的是void,即使你HandlerAdaptor帮我封装成ModleAndView,你怎么知道我返回到哪一个页面咯?我又不是返回string,直接在Handle方法里面返回一个页面的名称。
spring框架说,我来告诉你吧:你如果返回ModleMap或者void,我将会根据请求路径,按照默认规则提取相应的逻辑视图名来返回。
@RequestMapping("/a.action")
public ModelMap fafa() {
return ...ModelMap的实例
}
//他会返回名字叫做a的视图
d、我只返回了一个名称,你怎么知道是哪个文件夹下面,哪个后缀名的文件了?这件事情跟HandleMapping一样,要定位到具体精确的页面。HandleAdaptor返回了ModelAndView给Dispatcher之后,Dispatcher会调用一个ViewResolver来处理这个对应,你如果使用jsp作为视图的,他常用这个类:
<bean id="jspViewResolver"
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="viewClass"
value="org.springframework.web.servlet.view.JstlView" />
<property name="prefix" value="/" />
<property name="suffix" value=".jsp" />
</bean>
//这个也是spring默认的一个视图定位器
他的主要最用就是找视图了。
e、Dispatchet调用ViewResolver得到一个view实例的引用,然后把渲染的工作交给View实例。View就是把jsp模板和解析jstl数据表达式结合之后发给tomcat,tomcat把他发送给我们客户就可以了。。这里的jstl数据形如:${a.name},这样的,这个有view来处理。。
from:http://zhidao.baidu.com/question/3298976.html 各种版本说明