Spring MVC处理流程及配置文件和注解说明(附:示例及启动日志)

Spring MVC的请求处理流程,配置文件中字段说明,示例演示说明@Controller和@RequestMapping注解的使用。

1.Spring MVC请求处理流程图

(图片及步骤来自:https://www.cnblogs.com/ysocean/p/7375405.html)

第一步:用户发送请求到前端控制器(DispatcherServlet)。

第二步:前端控制器请求 HandlerMapping 查找 Handler,可以根据 xml 配置、注解进行查找。

第三步: 处理器映射器 HandlerMapping 向前端控制器返回 Handler

第四步:前端控制器调用处理器适配器去执行 Handler

第五步:处理器适配器执行 Handler

第六步:Handler 执行完成后给适配器返回 ModelAndView

第七步:处理器适配器向前端控制器返回 ModelAndView

    ModelAndView 是SpringMVC 框架的一个底层对象,包括 Model 和 View

第八步:前端控制器请求试图解析器去进行视图解析

    根据逻辑视图名来解析真正的视图。

第九步:试图解析器向前端控制器返回 view

第十步:前端控制器进行视图渲染

    就是将模型数据(在 ModelAndView 对象中)填充到 request 域

第十一步:前端控制器向用户响应结果

上图中一些组件的解释:

1)前端控制器DispatcherServlet(不需要程序员开发)。

  作用:接收请求,响应结果,相当于转发器,中央处理器。有了DispatcherServlet减少了其它组件之间的耦合度。

2)处理器映射器HandlerMapping(不需要程序员开发)。

  作用:根据请求的url查找Handler。

3)处理器适配器HandlerAdapter(不需要程序员开发)。

  作用:按照特定规则(HandlerAdapter要求的规则)去执行Handler。

4)处理器Handler(或者Controller,需要程序员开发)。

  注意:编写Handler时按照HandlerAdapter的要求去做,这样适配器才可以去正确执行Handler。

5)视图解析器ViewResolver(不需要程序员开发)。

  作用:进行视图解析,根据逻辑视图名解析成真正的视图(view)

6)视图View(需要程序员开发jsp)。

  注意:View是一个接口,实现类支持不同的View类型(jsp、freemarker、pdf…)

ps:不需要程序员开发的,做一下配置即可,相关配置如下。

2. Spring MVC相关组件的配置

1).配置web.xml中的前端控制器(DispatcherServlet)

<?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"
     xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
     http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0">

  <display-name>DisposalSludgeSystem</display-name>

  <!-- 配置前端控制器DispatcherServlet -->
  <servlet>
    <servlet-name>mvc-dispatcher</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>  
    <!--如果不配置 contextConfigLocation,那么默认加载的是/WEB-INF/<servlet-name>-servlet.xml,在这里即为mvc-dispatcher-servlet.xml--> 
    <init-param>
       <param-name>contextConfigLocation</param-name>
       <param-value>classpath:spring/spring-*.xml</param-value>
    </init-param>
  </servlet>

  <servlet-mapping>
    <servlet-name>mvc-dispatcher</servlet-name>
    <!--第一种配置:*.do,还可以写*.action等等,表示以.do结尾的或者以.action结尾的URL都由前端控制器DispatcherServlet来解析。
   第二种配置:/,表示所有访问的URL都由DispatcherServlet来解析-->
    <url-pattern>*.do</url-pattern> <!--或者配置成 <url-pattern>/</url-pattern>-->
  </servlet-mapping>
</web-app>

2).配置spring-web.xml(或springmvc.xml)中的 处理器适配器(HandlerAdapter)(本例中没有配置)

<!-- 配置处理器适配器第一种方法,所有适配器都得实现 HandlerAdapter接口 -->
<bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter" />
<!-- 配置处理器适配器第二种方法,所有适配器都得实现 HandlerAdapter接口 ,这样配置所有Handler都得实现 HttpRequestHandler接口-->
<bean class="org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter" />

3).配置spring-web.xml(或springmvc.xml)中的处理器映射器(HandlerMapping)(本例中没有配置)

第一种方法:

<!-- 配置Handler -->   
<bean name="/Anmy.do" class="com.ys.controller.HelloController2" />

<!-- 配置处理器映射器,将bean的name作为url进行查找,需要在配置Handler时指定bean name(就是url)-->
<bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping" />

这样配置的话,那么请求的 URL,必须为 http://localhost:8080/项目名/Anmy.do

第二种方法:

<!-- 配置Handler -->   
<bean id="Anmy1" class="com.ys.controller.HelloController" />
<bean id="Anmy2" class="com.ys.controller.HelloController" />

<!-- 第二种方法:简单URL配置处理器映射器 -->
<bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
    <property name="mappings">
        <props>
            <prop key="/Anmy1.do">Anmy1</prop>
            <prop key="/Anmy2.do">Anmy2</prop>
        </props>
    </property>
</bean>

这种配置请求的 URL可以为 http://localhost:8080/项目名/Anmy1.do,或者http://localhost:8080/项目名/Anmy2.do

4).Spring-web.xml中配置视图解析器(ViewResolver)

<!-- 定义视图解析器 进行jsp解析,默认使用jstl标签,classpath下得有jstl的包-->
<bean id="viewResolver"
     class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    <!--返回视图页面的前缀 -->
    <property name="prefix" value="/WEB-INF/jsp/"/>
    <!--返回页面的后缀,veiw层由jsp实现 -->
    <property name="suffix" value=".jsp"/>
</bean>

若采用这种方式配置:在 Handler 中只需要返回在 view 文件夹下的jsp 页面名就可以了。无需返回 路径+名称+’.jsp’

  • Spring-web.xml配置详解
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
      xmlns:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p"
      xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      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-4.2.xsd">

   <!--静态资源默认servlet配置,如果发现是静态资源的请求,就将该请求转由Web应用服务器默认的Servlet处理,如果不是静态资源的请求,才由DispatcherServlet继续处理。
功能:(1)加入对静态资源的处理:js,gif,png,css等 (2)允许使用"/"做整体映射(web.xml中serverlet-mapping部分的url-pattern是"/") -->
   <mvc:default-servlet-handler />

   <!-- 定义视图解析器 -->
   <bean id="viewResolver"
        class="org.springframework.web.servlet.view.InternalResourceViewResolver">
      <!--返回视图页面的前缀 -->
      <property name="prefix" value="/WEB-INF/jsp/" />
      <!--返回页面的后缀,veiw层由jsp实现 -->
      <property name="suffix" value=".jsp" />
   </bean>
  
   <!-- 注解处理器映射器-->
   <!-- <bean id="handlerMapping" class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"/> -->

   <!-- 注解处理器适配器-->
   <!-- <bean id="handlerAdapter" class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"/> -->

   <!-- 使用<mvc:annotation-driven/>可以代替上面的映射器和适配器;会自动注册RequestMappingHandlerMapping和   RequestMappingHandlerAdapter两个bean,这是SpringMVC为@Controllers分发请求所必须的,并提供了数据绑定支持、@NumberFormatannotation支持、@DateTimeFormat支持、@valid支持、读写XML的支持(JAXB)和JSON的支持(默认jackson)等功能。-->
   <mvc:annotation-driven />

    <!--单个配置Handler  -->
    <!-- <bean class="com.ys.controller.HelloController"></bean> —>
    <!-- 自动扫描controller包中基于注解类型实现的类,根据类自动生成bean,而不用在xml中手动d单个配置bean。即:批量配置Handler,指定扫描的包全称,不用再单个配置Handler -->
   <context:component-scan base-package="factory" />
</beans>

注:如果配置中少了上面一些配置,在 SpringMVC 运行之前,会首先加载 DispatcherServlet.properties(位置及内容如下)文件里面的内容

# 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.annotation.DefaultAnnotationHandlerMapping

org.springframework.web.servlet.HandlerAdapter=org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter,org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter,org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter

org.springframework.web.servlet.HandlerExceptionResolver=org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerExceptionResolver,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.properties也有会默认的配置。

  • 处理器适配器默认:org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter
  • 处理器映射器默认:org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping(将bean的name作为url进行查找,需要在配置Handler时指定bean name(即是url))
  • 视图解析器默认:org.springframework.web.servlet.view.InternalResourceViewResolver

3.示例解析

package factory.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

/**
 * Created by ZhangAnmy on 18/9/25.
 */

//使用@Controller注解表示这个类是一个Handler
@Controller
public class AnmyTestController {

    //@RequestMapping注解括号里面的内容表示访问的URL
    @RequestMapping("Anmy")
    public ModelAndView Anmy(){
        ModelAndView modelView = new ModelAndView();
        modelView.addObject("name","ZhangAnmy");//设置需要返回的值

        //配置返回的视图名,由于在spring-web.xml中配置了前缀和后缀,这里直接写视图名即可
        modelView.setViewName("index");
        //modelView.setViewName("/WEB-INF/jsp/index.jsp");
        return modelView;
    }
}

index.jsp内容(/WEB-INF/jsp/index.jsp)

<%--
  Created by IntelliJ IDEA.
  User: ZhangAnmy
  Date: 18/9/25
  Time: 16:54
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Anmy test page</title>
</head>
<body>
Welcome, ${name} ^_^^_^
</body>
</html>

启动项目,在浏览器中输入“localhost:8080/项目名/Anmy” 即可看到Handler中设置的name值 

以下为启动日志信息:红色部分可以看出系统的初始化过程及加载顺序

--------------------------------------------------------------------------------------------------

[2018-09-25 07:52:49,982] Artifact DisposalSludgeSystem:war exploded: Artifact is being deployed, please wait...

25-Sep-2018 19:52:55.018 信息 [RMI TCP Connection(2)-127.0.0.1] org.apache.jasper.servlet.TldScanner.scanJars At least one JAR was scanned for TLDs yet contained no TLDs. Enable debug logging for this logger for a complete list of JARs that were scanned but no TLDs were found in them. Skipping unneeded JARs during scanning can improve startup time and JSP compilation time.

[2018-09-25 07:52:55,250] Artifact DisposalSludgeSystem:war exploded: Artifact is deployed successfully

[2018-09-25 07:52:55,250] Artifact DisposalSludgeSystem:war exploded: Deploy took 5,268 milliseconds

25-Sep-2018 19:52:56.377 信息 [http-nio-8080-exec-1] org.springframework.web.servlet.DispatcherServlet.initServletBean FrameworkServlet 'mvc-dispatcher': initialization started

25-Sep-2018 19:52:56.414 信息 [http-nio-8080-exec-1] org.springframework.web.context.support.XmlWebApplicationContext.prepareRefresh Refreshing WebApplicationContext for namespace 'mvc-dispatcher-servlet': startup date [Tue Sep 25 19:52:56 CST 2018]; root of context hierarchy

25-Sep-2018 19:52:56.486 信息 [http-nio-8080-exec-1] org.springframework.beans.factory.xml.XmlBeanDefinitionReader.loadBeanDefinitions Loading XML bean definitions from file [/Users/macbook/Documents/.../DisposalSludgeSystem/WEB-INF/classes/spring/spring-dao.xml] //spring-dao.xml中引入了database.properties,database.properties中配置了c3p0连接池及其相关属性

25-Sep-2018 19:52:57.038 信息 [http-nio-8080-exec-1] org.springframework.beans.factory.xml.XmlBeanDefinitionReader.loadBeanDefinitions Loading XML bean definitions from file [/Users/macbook/Documents/.../DisposalSludgeSystem/WEB-INF/classes/spring/spring-service.xml]

25-Sep-2018 19:52:57.212 信息 [http-nio-8080-exec-1] org.springframework.beans.factory.xml.XmlBeanDefinitionReader.loadBeanDefinitions Loading XML bean definitions from file [/Users/macbook/Documents/.../DisposalSludgeSystem/WEB-INF/classes/spring/spring-web.xml]

25-Sep-2018 19:52:58.368 信息 [http-nio-8080-exec-1] org.springframework.beans.factory.config.PropertyPlaceholderConfigurer.loadProperties Loading properties file from class path resource [spring/database.properties]

25-Sep-2018 19:52:58.500 信息 [http-nio-8080-exec-1] com.mchange.v2.log.MLog.<clinit> MLog clients using java 1.4+ standard logging.

25-Sep-2018 19:52:58.546 信息 [http-nio-8080-exec-1] com.mchange.v2.c3p0.C3P0Registry.banner Initializing c3p0-0.9.1.2 [built 21-May-2007 15:04:56; debug? true; trace: 10]

25-Sep-2018 19:52:59.553 信息 [ContainerBackgroundProcessor[StandardEngine[Catalina]]] org.apache.catalina.startup.HostConfig.deployDirectory Deploying web application directory [/Users/macbook/.../apache-tomcat-9.0.8/webapps/manager]

25-Sep-2018 19:52:59.598 信息 [ContainerBackgroundProcessor[StandardEngine[Catalina]]] org.apache.catalina.startup.HostConfig.deployDirectory Deployment of web application directory [/Users/macbook/.../apache-tomcat-9.0.8/webapps/manager] has finished in [43] ms

...

25-Sep-2018 19:53:11.723 信息 [http-nio-8080-exec-1] org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping.registerHandlerMethod Mapped "{[/Anmy]}" onto public org.springframework.web.servlet.ModelAndView factory.controller.AnmyTestController.Anmy()

...

25-Sep-2018 19:53:34.781 信息 [http-nio-8080-exec-1] org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.initControllerAdviceCache Looking for @ControllerAdvice: WebApplicationContext for namespace 'mvc-dispatcher-servlet': startup date [Tue Sep 25 19:52:56 CST 2018]; root of context hierarchy

25-Sep-2018 19:53:40.359 信息 [http-nio-8080-exec-1] org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.initControllerAdviceCache Looking for @ControllerAdvice: WebApplicationContext for namespace 'mvc-dispatcher-servlet': startup date [Tue Sep 25 19:52:56 CST 2018]; root of context hierarchy

25-Sep-2018 19:53:47.789 信息 [http-nio-8080-exec-1] org.springframework.web.servlet.handler.SimpleUrlHandlerMapping.registerHandler Mapped URL path [/**] onto handler 'org.springframework.web.servlet.resource.DefaultServletHttpRequestHandler#0'

25-Sep-2018 19:54:06.301 信息 [http-nio-8080-exec-1] org.springframework.web.servlet.DispatcherServlet.initServletBean FrameworkServlet 'mvc-dispatcher': initialization completed in 69923 ms

--------------------------------------------------------------------------------------------------

类DispatcherServlet继承自类FrameworkServlet,FrameworkServlet类中有initServletBean()方法进行初始化,加载配置文件等。源码如下图:

源码部分还待仔细研究分析,待后续补充完善,今天就到这吧^_^^_^

猜你喜欢

转载自blog.csdn.net/m0_37568814/article/details/82844503