SpringMVC简介
一、总述

二、快速入门
2.1概述

下面直接动手吧:
2.2实现
1、导入坐标:
java
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.3.7</version>
</dependency>
注意改为war包
java
<groupId>com.itheima</groupId>
<artifactId>spring_webmvc_test02</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>war</packaging>
2、在web.xml配置前端控制器
这里直接所有一起配了,注释里面有详细解释了,就不再过多赘述了。
java
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
version="3.1">
<!--配置前端控制器-->
<servlet>
<servlet-name>DispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!-- 设置启动时加载-->
<load-on-startup>2</load-on-startup>
</servlet>
<!-- 配置前端控制器的映射,让前端找得到-->
<servlet-mapping>
<servlet-name>DispatcherServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
3、配置Controlle控制器
同时使用注解交由SpringMVC容器进行管理
java
package com.itheima.controller;
import com.itheima.service.QuickService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
//定义成为Bean
@Controller
public class QuickController2 {
//这是映射地址
@RequestMapping("/quick")
public void quick(){
System.out.println("quick is running");
}
}
既然是使用注解交由SpringMVC容器进行管理,那么就必定要在SpringMVC的配置文件配置注解扫描了:
java
<?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"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
">
<!-- 配置组件扫描扫描到我们的控制器-->
<context:component-scan base-package="com.itheima.controller"></context:component-scan>
</beans>
那么如何让web.xm与SpringMVC的配置文件连接起来呢,当然还要进行配置一下,最后是这样的:
java
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
version="3.1">
<!--配置前端控制器-->
<servlet>
<servlet-name>DispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!-- 配置一下我们Spring配置文件的路径-->
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring-mvc2.xml</param-value>
</init-param>
<!-- 设置启动时加载-->
<load-on-startup>2</load-on-startup>
</servlet>
<!-- 配置前端控制器的映射-->
<servlet-mapping>
<servlet-name>DispatcherServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
测试一下访问QuickController2的quick方法:

控制台成功打印,没有问题。
但是我们可以看到前端报的是500的错误:

这是因为Controller是控制器,本来应该返回的是视图名称,但是什么返回的是空,所以报的是500,现在我们来返回一个视图试一下:
java
package com.itheima.controller;
import com.itheima.service.QuickService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
//定义成为Bean
@Controller
public class QuickController2 {
//这是映射地址
@RequestMapping("/quick")
public String quick()
{
System.out.println("quick is running");
return "/index.jsp";
}
}
这是要返回的jsp视图:
java
<%--
Created by IntelliJ IDEA.
User: haohao
Date: 2022/12/1
Time: 16:04
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<h1>Hello SpringMVC!</h1>
</body>
</html>

结论得证。
三、在SpringMVC中注入Spring中配置的Bean
先进行Spring的Bean的配置,这里为了测试使用简单的Bean:
java
package com.itheima.service;
public interface QuickService {
}
java
package com.itheima.service.impl;
import com.itheima.service.QuickService;
import org.springframework.stereotype.Service;
@Service
public class QuickServiceImpl implements QuickService {
}
在Spring的配置文件中配置组件扫描:
java
<?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.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
">
<!--组件扫描-->
<context:component-scan base-package="com.itheima.service"/>
</beans>
在web.xml中配置监听器且加载Spring的配置文件:
java
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
version="3.1">
<!--配置监听器-->
<!-- 配置参数-->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!--配置前端控制器-->
<servlet>
<servlet-name>DispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!-- 配置一下我们Spring配置文件的路径-->
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring-mvc2.xml</param-value>
</init-param>
<!-- 设置启动时加载-->
<load-on-startup>2</load-on-startup>
</servlet>
<!-- 配置前端控制器的映射-->
<servlet-mapping>
<servlet-name>DispatcherServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
在Controller中注入Spring中配置的Bean:
java
package com.itheima.controller;
import com.itheima.service.QuickService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
//定义成为Bean
@Controller
public class QuickController2 {
// 注入配置好的Service
// @Autowired
// private QuickService quickService;
//这是映射地址
@RequestMapping("/quick")
public String quick()
{
System.out.println("quick is running");
return "/index.jsp";
}
}
四、SpringMVC加载组件的策略


其实际上这些HandlerMapping、HandlerAdapter、ViewResolver存在于org\springframework\spring-webmvc\5.3.7\spring-webmvc-5.3.7.jar!\org\springframework\web\servlet\DispatcherServlet.properties的文件中:
java
# Default implementation classes for DispatcherServlet's strategy interfaces.
# Used as fallback when no matching beans are found in the DispatcherServlet context.
# Not meant to be customized by application developers.
org.springframework.web.servlet.LocaleResolver=org.springframework.web.servlet.i18n.AcceptHeaderLocaleResolver
org.springframework.web.servlet.ThemeResolver=org.springframework.web.servlet.theme.FixedThemeResolver
org.springframework.web.servlet.HandlerMapping=org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping,\
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping,\
org.springframework.web.servlet.function.support.RouterFunctionMapping
org.springframework.web.servlet.HandlerAdapter=org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter,\
org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter,\
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter,\
org.springframework.web.servlet.function.support.HandlerFunctionAdapter
org.springframework.web.servlet.HandlerExceptionResolver=org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver,\
org.springframework.web.servlet.mvc.annotation.ResponseStatusExceptionResolver,\
org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver
org.springframework.web.servlet.RequestToViewNameTranslator=org.springframework.web.servlet.view.DefaultRequestToViewNameTranslator
org.springframework.web.servlet.ViewResolver=org.springframework.web.servlet.view.InternalResourceViewResolver
org.springframework.web.servlet.FlashMapManager=org.springframework.web.servlet.support.SessionFlashMapManager
这里面有那么对应的实现,而这些实现会在DispatcherServlet前端控制器进行加载,里面哪些List就是有来存对应的实现的:
java
@Nullable
private MultipartResolver multipartResolver;
@Nullable
private LocaleResolver localeResolver;
@Nullable
private ThemeResolver themeResolver;
@Nullable
private List<HandlerMapping> handlerMappings;
@Nullable
private List<HandlerAdapter> handlerAdapters;
@Nullable
private List<HandlerExceptionResolver> handlerExceptionResolvers;
@Nullable
private RequestToViewNameTranslator viewNameTranslator;
@Nullable
private FlashMapManager flashMapManager;
@Nullable
private List<ViewResolver> viewResolvers;
且只有自己的Spring和SpringMVC容器里面没有配置相应的Bean前端控制器才会加载对应类型默认的实现:
java
private void initHandlerMappings(ApplicationContext context) {
this.handlerMappings = null;
if (this.detectAllHandlerMappings) {
Map<String, HandlerMapping> matchingBeans = BeanFactoryUtils.beansOfTypeIncludingAncestors(context, HandlerMapping.class, true, false);
if (!matchingBeans.isEmpty()) {
this.handlerMappings = new ArrayList(matchingBeans.values());
AnnotationAwareOrderComparator.sort(this.handlerMappings);
}
} else {
try {
HandlerMapping hm = (HandlerMapping)context.getBean("handlerMapping", HandlerMapping.class);
this.handlerMappings = Collections.singletonList(hm);
} catch (NoSuchBeanDefinitionException var4) {
}
}
if (this.handlerMappings == null) {
this.handlerMappings = this.<HandlerMapping>getDefaultStrategies(context, HandlerMapping.class);
if (this.logger.isTraceEnabled()) {
this.logger.trace("No HandlerMappings declared for servlet '" + this.getServletName() + "': using default strategies from DispatcherServlet.properties");
}
}
for(HandlerMapping mapping : this.handlerMappings) {
if (mapping.usesPathPatterns()) {
this.parseRequestPath = true;
break;
}
}
}


最终都放到对应的List当中了。
当我们在SpringMVC容器中配置了一个自己的HandlerMapping,那么前端控制器DispatcherServlet就不会再加载它默认的四个实现了,以为此时的matchingBeans不再等于空了,但是只是HandlerMapping不再加载默认的,如果HandlerAdapter等其他类型的没有自己配置的话,它依然还会加载。
<?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"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
">
<!-- 配置组件扫描扫描到我们的控制器-->
<context:component-scan base-package="com.itheima.controller"></context:component-scan>
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"></bean>
</beans>