天天看點

【Spring學習】SpringMVC demo搭建

【Spring學習】SpringMVC demo搭建

前言:今天會通過IDEA建立一個SpringMVC的demo項目,在其中會涉及到一些基礎子產品和相關知識,然後結合這個具體的知識點,了解清楚SpringMVC的架構原理(以圖的形式展示),順藤摸瓜分析源碼

一、建立項目

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

【Spring學習】SpringMVC demo搭建

點選Next填上:ProjectName和Project Location,之後會進入下載下傳依賴包的過程:

【Spring學習】SpringMVC demo搭建

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

【Spring學習】SpringMVC demo搭建

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

二、确認配置檔案内容

梳理清楚WEB-INF下的三個xml檔案的作用和其中所配置内容的具體含義

直接通過官網介紹:https://docs.spring.io/spring/docs/current/spring-framework-reference/web.html 檢視

具體介紹如下: 

1、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配置:(注:如下圖為從官網截圖内容)

【Spring學習】SpringMVC demo搭建

2、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解決方案在(三)中      

3、dispatcher-servlet.xml:

作用:dispatcher-servlet.xml與applicationContext.xml是孩子與父親的上下文的關系,在applicationContext.xml中可以定義全局的Spring的特性,dispatcher-servlet.xml就是在Context Hierarchy中定義的子WebapplicationContext.xml的内容,在其中具體定義屬于目前Servlet的處理分發邏輯等

三、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的路徑,導緻出現這個錯誤

【Spring學習】SpringMVC demo搭建

接下來,對這個異常進行初步分析的過程(這裡不包含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的聲明之後,異常消失:

【Spring學習】SpringMVC demo搭建

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

【Spring學習】SpringMVC demo搭建

在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>      
四、運作      
點選run之後會提示進行Edit Configurations,進入頁面,将相應内容填入(需要啟動TomcatServer并設定路徑)      
【Spring學習】SpringMVC demo搭建
設定Demployment:      
【Spring學習】SpringMVC demo搭建

之後點選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,      
【Spring學習】SpringMVC demo搭建

 之後檢視左側output root的按鈕,可以看到:WEB-INF下有SpringMVC的jar包:

【Spring學習】SpringMVC demo搭建
以上問題都解決以後,就能夠運作成功整個項目了~      
備注:在運作過程中,下方視窗中出現運作日志會有中文亂碼的情況:可以參考該篇文章:https://blog.csdn.net/qq_41264674/article/details/80945140      

posted on 2019-02-22 11:32 可可_小蝦米 閱讀(...) 評論(...) 編輯 收藏

繼續閱讀