【SpringMVC框架】SpringMVC相关配置分析

本文深入剖析了SpringMVC框架的配置机制,包括前端控制器的工作流程、处理器与映射器的配置方式,以及注解与非注解配置的对比。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

SpringMVC相关配置分析

有关SpringMVC的基础知识及使用可以参考前两篇博客内容,这里简单介绍一下相关配置的源码分析以及具体实现方式。

前端控制器的源码分析

URL进入前端控制器的过程。

在这里插入图片描述

前端控制器的实现类为:org.springframework.web.servlet.DispatcherServlet

  • 在前端控制器类中会执行调用doService方法。
protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception {
    //省略无关代码
    try {
        doDispatch(request, response);
    } finally {
        //省略无关代码
    }
}

protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
    HttpServletRequest processedRequest = request;
    HandlerExecutionChain mappedHandler = null;
    boolean multipartRequestParsed = false;

    WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);

    try {
        ModelAndView mv = null;
        Exception dispatchException = null;

        try {
            //和大文件传输有关的协议校验
            processedRequest = checkMultipart(request);
            multipartRequestParsed = (processedRequest != request);

            //getHandler是前端控制器调用处理器映射器查找Handler
            // Determine handler for the current request.
            mappedHandler = getHandler(processedRequest);
            if (mappedHandler == null || mappedHandler.getHandler() == null) {
                noHandlerFound(processedRequest, response);
                return;
            }

            // Determine handler adapter for the current request.
            HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());

            // Process last-modified header, if supported by the handler.
            String method = request.getMethod();
            boolean isGet = "GET".equals(method);
            if (isGet || "HEAD".equals(method)) {
                long lastModified = ha.getLastModified(request, mappedHandler.getHandler());
                if (logger.isDebugEnabled()) {
                    logger.debug("Last-Modified value for [" + getRequestUri(request) + "] is: " + lastModified);
                }
                if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) {
                    return;
                }
            }

            if (!mappedHandler.applyPreHandle(processedRequest, response)) {
                return;
            }

            //调用处理器适配器执行Handler,得到执行结果ModelAndView ,
            // Actually invoke the handler.
            mv = ha.handle(processedRequest, response, mappedHandler.getHandler());

            if (asyncManager.isConcurrentHandlingStarted()) {
                return;
            }

            //视图解析,将model数据填充到request域
            applyDefaultViewName(request, mv);
            mappedHandler.applyPostHandle(processedRequest, response, mv);
        } catch (Exception ex) {
            dispatchException = ex;
        }
        processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
    } catch (Exception ex) {
        triggerAfterCompletion(processedRequest, response, mappedHandler, ex);
    } catch (Error err) {
        triggerAfterCompletionWithError(processedRequest, response, mappedHandler, err);
    } finally {
        if (asyncManager.isConcurrentHandlingStarted()) {
            // Instead of postHandle and afterCompletion
            if (mappedHandler != null) {
                mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);
            }
        } else {
            // Clean up any resources used by a multipart request.
            if (multipartRequestParsed) {
                cleanupMultipart(processedRequest);
            }
        }
    }
}

前端控制器和各组件的交互过程,是通过doService方法内部调用不同的方法和其他组件进行交互的。

处理器和映射器的配置

Spring MVC大部分使用都是全注解配置,但是全注解也是由非注解发展来的。下面以实际场景为例介绍一下其具体的实现方式。

  • Spring MVC的两种注解性:注解形式和非注解形式。
  • 场景需求:用户信息列表查询。
前期准备
  • 用户实体(User.java)
public class User {
    private int id; 
    private String userName;
    private String sex;
    private String address;
    
    //省略get/set方法
}
  • 视图JSP(UserList.jsp)
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
        <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
        <%@ taglib uri="http://java.sun.com/jsp/jstl/fmt"  prefix="fmt"%>
        <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">

<html>
<head>
	<meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
	<title>用户列表</title>
</head>
<body>
   <table border="1" align="center">
   	<h1 align="center"> 用户列表</h1>
   	  <tr>
   	  	<td>用户ID</td>
   	  	<td>用户姓名</td>
   	  	<td>用户性别</td>
   	  	<td>地址</td>
   	  </tr>

   	  <c:forEach items="${users}" var="user">
        <tr>
        	<th>${user.id}</th>
        	<th>${user.userName}</th>
        	<th>${user.sex}</th>
        	<th>${user.address}</th>
        </tr>
   	  </c:forEach>
   </table>
</body>
</html>
基于XML的形式配置处理器适配器等

在spring-mvc.xml文件中配置处理器(包含处理器映射器、处理器适配器、视图解析器)。

  • 配置处理器适配器
<!--配置处理器适配器:所有处理器都需要来实现HandlerAdapter的接口-->
<bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"/>
  • SimpleControllerHandlerAdapter源码中,可以看出适配器只能实现Controller接口的Handler,即开发Controller,才能由SimpleControllerHandlerAdapter适配器执行。

在这里插入图片描述

Handler实现

import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.ArrayList;

/**
 * Handler:基于XML配置实现
 * 需要实现org.springframework.web.servlet.mvc.Controller接口
 * 才能被适配器适配并执行
 */
public class ControllerXML implements Controller {
    @Override
    public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
        //这个是需要通过数据拿到结果,实现静态数据模拟实现
        ArrayList<User> list = new ArrayList <>();
        User user = new User();
        user.setId(1);
        user.setUserName("张三");
        user.setSex("男");
        user.setAddress("西安");
        list.add(user);

        User user1 = new User();
        user1.setId(2);
        user1.setUserName("小明");
        user1.setSex("男");
        user1.setAddress("陕西西安");
        list.add(user1);

        //返回ModelAndView结果
        ModelAndView modelAndView = new ModelAndView();
        //填充数据
        modelAndView.addObject("users",list);
        //指定视图
        modelAndView.setViewName("userList");
        return modelAndView;
    }
}

处理器配置

  • 将配置文件spring-mcv.xml需要加载到web.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"
       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/context http://www.springframework.org/schema/context/spring-context-4.1.xsd
        http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.1.xsd">

    <!--配置处理器映射器-->
    <bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/>

    <!--配置处理器适配器:所有处理器都需要来实现HandlerAdapter的接口-->
    <bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"/>

    <!--配置Handler实例,将Handler交给Spring 管理-->
    <bean name="/userlist" class="com.test.contrller.ControllerXML"/>

    <!--配置视图解析器-->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <!--配置前缀-->
        <property name="prefix" value="/WEB-INF/jsp/"/>
        <!--配置后缀-->
        <property name="suffix" value=".jsp"/>
    </bean>
</beans>

注意:在XML配置文件中处理器适配器和处理器映射器需要使用的两个框架类。
org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter
org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping

执行结果

在这里插入图片描述

基于注解的形式配置处理器适配器等

处理器映射器在spring3.1之前使用
org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping
处理器映射器在spring3.1之后使用
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping
处理器适配器在spring3.1之前使用
org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter
处理器适配器在spring3.1之后使用
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter

配置如下:

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

<!--配置处理器映射器-->
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"/>

<!--
 使用mvc:annotation-driven代替上面处理器映射器和处理器适配器的配置
 annotation-driven默认加载很多的参数绑定方法
 实际开发中都是使用mvc:annotation-driven
 处理器映射器,适配器采用Spring MVC提供的默认的处理器处理,不需要显性的配置
-->
<mvc:annotation-driven/>

Handler的实现

/*
 * 处理器
 * 基于注解实现的Handler
 */
@Controller
public class ControllerDemo {

    @RequestMapping("userList")
    public ModelAndView userList() {
        //这个是需要通过数据拿到结果,实现静态数据模拟实现
        ArrayList<User> list = new ArrayList<>();
        User user = new User();
        user.setId(1);
        user.setUserName("张三");
        user.setSex("男");
        user.setAddress("西安");
        list.add(user);

        User user1 = new User();
        user1.setId(2);
        user1.setUserName("小明");
        user1.setSex("男");
        user1.setAddress("陕西西安");
        list.add(user1);

        //返回ModelAndView结果
        ModelAndView modelAndView = new ModelAndView();
        //填充数据
        modelAndView.addObject("users", list);
        //指定视图
        modelAndView.setViewName("userList");
        return modelAndView;
    }
}

处理器配置

  • 将配置文件spring-mcv.xml需要加载到web.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"
       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/context http://www.springframework.org/schema/context/spring-context-4.1.xsd
        http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.1.xsd">

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

    <!--配置处理器映射器-->
    <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"/>

    <!--
    使用mvc:annotation-driven代替上面处理器映射器和处理器适配器的配置
    annotation-driven默认加载很多的参数绑定方法
    实际开发中都是使用mvc:annotation-driven
    处理器映射器,适配器采用Spring MVC提供的默认的处理器处理,不需要显性的配置
    -->
    <mvc:annotation-driven/>


    <!--配置Spring MVC的需要扫描注解的包路径-->
    <context:component-scan base-package="com.test.contrller"/>

    <mvc:annotation-driven/>

    <!--配置视图解析器-->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <!--配置前缀-->
        <property name="prefix" value="/WEB-INF/jsp/"/>
        <!--配置后缀-->
        <property name="suffix" value=".jsp"/>
    </bean>
</beans>

执行结果

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值