【Spring學習】SpringMVC demo搭建

前言:今天會經過IDEA創建一個SpringMVC的demo項目,在其中會涉及到一些基礎模塊和相關知識,而後結合這個具體的知識點,理解清楚SpringMVC的框架原理(以圖的形式展現),順藤摸瓜分析源碼html

1、新建項目java

經過File-New-Project,在下方頁面勾選:Spring MVC + Web Applicationweb

 

點擊Next填上:ProjectName和Project Location,以後會進入下載依賴包的過程:spring

 

完成以後,在窗口中打開的工程目錄以下:其中lib中所放的是依賴的jar包,src中根據本身的需求添加package+class,其中IDEA已經自動幫助在WEB-INF中默認配置了applicationContext.xml、dispatcher-servlet.xml、web.xmlapache

 

至此,基礎工程也包含IDEA自動配置的都已經建好spring-mvc

 

2、確認配置文件內容tomcat

梳理清楚WEB-INF下的三個xml文件的做用和其中所配置內容的具體含義mvc

 

直接經過官網介紹:https://docs.spring.io/spring/docs/current/spring-framework-reference/web.html 查看app

具體介紹以下: 框架

一、web.xml

做用:用來對DispatcherServlet進行註冊和初始化(web.xml configuration registers and initializes the DispatcherServlet)

內容示例:

 1 <?xml version="1.0" encoding="UTF-8"?>  2 <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"  3  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  4  xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"  5  version="3.1">  6 <context-param>  7 <param-name>contextConfigLocation</param-name>  8 <param-value>/WEB-INF/applicationContext.xml</param-value>  9 </context-param> 10 <listener> 11 <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> 12 </listener> 13 <servlet> 14 <servlet-name>dispatcher</servlet-name> 15 <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> 16 <load-on-startup>1</load-on-startup> 17 </servlet> 18 <servlet-mapping> 19 <servlet-name>dispatcher</servlet-name> 20 <url-pattern>*.form</url-pattern> 21 </servlet-mapping> 22 </web-app>

重點關注的內容,如圖中黃色底色的<context-param>的<param-value>部分,這個是WebApplicationContext的配置文件,如上所示就表明只配置了一個WebApplicationContext,通常狀況下是足夠的,也能夠有Context的層次結構:其中一個根WebApplicationContext在多個DispatcherServlet(或其餘servlet)實例之間共享,每一個實例都有本身的子WebApplicationContext配置:(注:以下圖爲從官網截圖內容)

 

二、applicationContext.xml

做用:這裏的名字就是上面黃色底色標註出的xml文件的路徑,這個WebApplicationContext具備指向ServletContext及其關聯的Servlet的連接;

內容:

 1 <?xml version="1.0" encoding="UTF-8"?>  2  3 <beans xmlns="http://www.springframework.org/schema/beans"  4  5  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  6  7  xmlns:context="http://www.springframework.org/schema/context"  8  9  xmlns:mvc="http://www.springframework.org/schema/mvc" 10 11  xsi:schemaLocation="http://www.springframework.org/schema/beans 12 13  http://www.springframework.org/schema/beans/spring-beans.xsd 14 15  http://www.springframework.org/schema/context 16 17  http://www.springframework.org/schema/context/spring-context.xsd 18 19  http://www.springframework.org/schema/mvc 20 21  http://www.springframework.org/schema/cache/spring-mvc.xsd"> 22 23 24 25 <context:component-scan base-package="cn.lx.controller" /> 26 27 <mvc:annotation-driven /> 28 29 30 31 <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver"> 32 33 <property name="prefix" value="/WEB-INF/"/> 34 35 <property name="suffix" value=".jsp"/> 36 37 </bean> 38 39 </beans>
備註:其中<context:component-scan base-package="cn.lx.controller" />
    <mvc:annotation-driven />以及下面的bean都是本身添加的
其中,context添加以後,上面的beans中的xmlns和xsi中都會添加上對應的項,mvc的也同樣;可是IDEA在自動補齊mvc的內容時會出現cache字樣,以下所示,致使出現bug,具體問題及bug解決方案在(三)中

 

三、dispatcher-servlet.xml:

做用:dispatcher-servlet.xml與applicationContext.xml是孩子與父親的上下文的關係,在applicationContext.xml中能夠定義全局的Spring的特性,dispatcher-servlet.xml就是在Context Hierarchy中定義的子WebapplicationContext.xml的內容,在其中具體定義屬於當前Servlet的處理分發邏輯等

 

3、xml配置問題解決 && 模塊功能實現

在applicationContext.xml中添加<mvc:annotation-driven>出現了問題,一共兩個問題:

第一次是:輸入<mvc:annotation-driven/>的時候,IDEA會自動生成xmlns:mvc=」http://www.spingframework.org/schema/cache」,下面的xsi:schemaLocation=的內容也會增長:http://www.spingframework.org/schema/cache   http://www.spingframework.org/schema/cache/spring-cache.xsd

在自動生成這樣以後,運行的時候會出現錯誤提示:

21-Feb-2019 14:50:30.345 嚴重 [RMI TCP Connection(3)-127.0.0.1] org.springframework.web.context.ContextLoader.initWebApplicationContext Context initialization failed org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.cache.interceptor.CacheInterceptor#0': Cannot resolve reference to bean 'cacheManager' while setting bean property 'cacheManager'; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'cacheManager' available at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:359) at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveValueIfNecessary(BeanDefinitionValueResolver.java:108) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyPropertyValues(AbstractAutowireCapableBeanFactory.java:1537) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1284) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:553) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:483) at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:312) at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:308) at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197) at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:761) at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:867) at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:543) at org.springframework.web.context.ContextLoader.configureAndRefreshWebApplicationContext(ContextLoader.java:443) at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:325) at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:107) at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4668) at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5136) at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183) at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:713) at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:690) at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:695) at org.apache.catalina.startup.HostConfig.manageApp(HostConfig.java:1729) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) [2019-02-21 02:50:30,383] Artifact demo:war exploded: Error during artifact deployment. See server log for details. at org.apache.tomcat.util.modeler.BaseModelMBean.invoke(BaseModelMBean.java:289) at com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.invoke(DefaultMBeanServerInterceptor.java:819) at com.sun.jmx.mbeanserver.JmxMBeanServer.invoke(JmxMBeanServer.java:801) at org.apache.catalina.mbeans.MBeanFactory.createStandardContext(MBeanFactory.java:457) at org.apache.catalina.mbeans.MBeanFactory.createStandardContext(MBeanFactory.java:406) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at org.apache.tomcat.util.modeler.BaseModelMBean.invoke(BaseModelMBean.java:289) at com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.invoke(DefaultMBeanServerInterceptor.java:819) at com.sun.jmx.mbeanserver.JmxMBeanServer.invoke(JmxMBeanServer.java:801) at javax.management.remote.rmi.RMIConnectionImpl.doOperation(RMIConnectionImpl.java:1468) at javax.management.remote.rmi.RMIConnectionImpl.access$300(RMIConnectionImpl.java:76) at javax.management.remote.rmi.RMIConnectionImpl$PrivilegedOperation.run(RMIConnectionImpl.java:1309) at javax.management.remote.rmi.RMIConnectionImpl.doPrivilegedOperation(RMIConnectionImpl.java:1401) at javax.management.remote.rmi.RMIConnectionImpl.invoke(RMIConnectionImpl.java:829) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:324) at sun.rmi.transport.Transport$1.run(Transport.java:200) at sun.rmi.transport.Transport$1.run(Transport.java:197) at java.security.AccessController.doPrivileged(Native Method) at sun.rmi.transport.Transport.serviceCall(Transport.java:196) at sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:568) at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:826) at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.lambda$run$0(TCPTransport.java:683) at java.security.AccessController.doPrivileged(Native Method) at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:682) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) at java.lang.Thread.run(Thread.java:745) Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'cacheManager' available at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeanDefinition(DefaultListableBeanFactory.java:687) at org.springframework.beans.factory.support.AbstractBeanFactory.getMergedLocalBeanDefinition(AbstractBeanFactory.java:1213) at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:284) at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197) at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:351) ... 60 more

以上錯誤中的cacheManager,我並無用到,可是很奇怪,爲何會拋出這個錯誤,搜索全局找跟cache相關的內容,發如今xml文件中出現了xmlns和schemaLocation中有cache的內容出現,基於此繼續追查(後面會補一篇xml解析和schema的內容),發現多是這裏配置的問題,並且由於實際上尚未走到具體邏輯中,是在啓動過程當中就已經拋出錯誤,出現cache的xmlns的內容以下:xmlns:mvc=http://www.springframework.org/schema/cache

而後找到這個mvc是在下面定義的:<mvc:annotation-driven />相匹配,從新輸入內容自動聯想發現:紅色框線內基本都是annotation-driven,只是來源不一樣,默認點擊enter會自動選擇cache的路徑,致使出現這個錯誤

接下來,對這個異常進行初步分析的過程(這裏不包含CacheManager運行原理和源碼解析,後面會有一篇文章進行介紹),查官網資料,https://docs.spring.io/spring-framework/docs/current/spring-framework-reference/integration.html#cache-plug

8.5章節中有以下內容描述:

The cache abstraction provides several storage integration options. To use them, you need to declare an appropriate CacheManager (an entity that controls and manages Cache instances and that can be used to retrieve these for storage).

以後官網詳細的基於不一樣方式的cache須要配置的xml內容作了demo樣例,也查詢了一些其餘文檔,本地添加bean的聲明以後,異常消失:

 

至此,這個基於自動補齊的<annotation-driven>的問題解決,但實際上,我須要的是:mvc的namespace和對應的xsd,修改程序將:namespace和schemaLocations中的cache都改爲mvc:

 

在applicationContext.xml中繼續添加bean配置:

<bean id="viewResolver" class="org.springframework.web.servlet.view.ResourceBundleViewResolver"> <property name="prefix" value="/WEB-INF/"/> <property name="suffix" value=".jsp"/> </bean>
在src下建包名/類,testController.java的實現,以下:
@Controller public class TestController { @RequestMapping("/test.form") public void execute(){ return ; } }

 

test.jsp的內容以下:

<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>test</title> </head> <body> Hello Spring MVC Test </body> </html>
 
4、運行
點擊run以後會提示進行Edit Configurations,進入頁面,將相應內容填入(須要啓動TomcatServer並設置路徑)

設置Demployment:

 

以後點擊run按鈕,運行提示ClassNotFound:

嚴重 [RMI TCP Connection(3)-127.0.0.1] org.apache.catalina.core.StandardContext.listenerStart Error configuring application listener of class [org.springframework.web.context.ContextLoaderListener] java.lang.ClassNotFoundException: org.springframework.web.context.ContextLoaderListener at org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1363) at org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1186) at org.apache.catalina.core.DefaultInstanceManager.loadClass(DefaultInstanceManager.java:540) at org.apache.catalina.core.DefaultInstanceManager.loadClassMaybePrivileged(DefaultInstanceManager.java:521) at org.apache.catalina.core.DefaultInstanceManager.newInstance(DefaultInstanceManager.java:150) at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4590)
 
但工程的lib目錄下的jar都引入了,那就是Tomcat運行的時候加載不到這個jar包的緣由,經過File-Project Structure打開進入到工程設置頁面,以下圖所示,將右側點擊以後選擇Put into output Root,

 以後查看左側output root的按鈕,能夠看到:WEB-INF下有SpringMVC的jar包:

以上問題都解決之後,就可以運行成功整個項目了~
備註:在運行過程當中,下方窗口中出現運行日誌會有中文亂碼的狀況:能夠參考該篇文章:https://blog.csdn.net/qq_41264674/article/details/80945140
相關文章
相關標籤/搜索