Spring MVC :从入门到精通(上)

一、Spring MVC概述

1.1为什么使用Spring MVC?

servlet案例:

java 复制代码
@WebServlet("/addUser") //1、该Servlet的URL映射为"/addUser"
public class AddUserServlet extends HttpServlet {

    private UserService userService = new UserServiceImpl();


    @Override
    protected void doPost(HttpServletRequest req, 
                     HttpServletResponse resp) throws ServletException, IOException {
        //2、接收前台传递的参数
        String username = req.getParameter("username");
        String password = req.getParameter("password");
        String sex = req.getParameter("sex");
        Integer age = Integer.parseInt(req.getParameter("age"));
        String address = req.getParameter("address");

        userService.addUser(username, password, sex, age, address);

        resp.sendRedirect("selectUser");
    }
}
  • servlet缺陷:

1.一个servlet实例只能处理一个请求

2.参数接收太麻烦

1.2 MVC 设计模式

MVC 是一种软件分层设计模式,将应用分为三层:

  • Model(模型层) :JavaBean,分为两类
    • 数据承载 Bean:如 pojo/User、Student(存储业务数据)
    • 业务处理 Bean:如 Service、Dao(处理业务逻辑 / 数据访问)
  • View(视图层):HTML/JSP 页面,负责交互和数据展示
  • Controller(控制层):Servlet,接收请求、响应浏览器

MVC 工作流程

View----->Controller----->Model

用户通过视图层发起请求 → 控制器接收请求 → 调用模型层处理数据 → 模型层返回结果给控制器 → 控制器选择视图渲染数据 → 响应给浏览器

MVC 和三层架构的关系

对比维度 三层架构 MVC
分层关系 典型上下依赖关系,上层依赖下层 相互协作关系,不存在上下层
划分依据 基于业务逻辑划分 基于页面划分

1.3 SpringMVC 介绍

  • SpringMVC 是 Spring 框架的核心模块,基于 MVC 设计模式的轻量级 Web 框架(本质等价于 Servlet)
  • 是 Java EE 项目表述层开发的首选方案,提供了完备的控制层解决方案

二、SpringMVC 入门案例

2.1 环境搭建

2.1.1 创建工程并添加 Web 支持
  1. 新建 Maven 工程,右键选择Add framework support...
  2. 勾选 Web Application,添加 Web 支持
  3. 将 web 目录拖拽到 main 目录下,重命名为 webapp(注意:先加框架支持,再设置打包方式)

注意:

  1. 先添加框架支持,再设置打包方式

  2. 将web目录要拖拽到main目录下,并改名为webapp

2.1.2 配置 pom.xml

xml

XML 复制代码
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.hg</groupId>
    <artifactId>SpringMVC_day01</artifactId>
    <version>1.0-SNAPSHOT</version>
    <!--打包方式-->
    <packaging>war</packaging>

    <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.2.8.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>5.2.8.RELEASE</version>
        </dependency>

        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>servlet-api</artifactId>
            <version>2.5</version>
            <scope>provided</scope>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <!-- 配置Tomcat插件 -->
            <plugin>
                <groupId>org.apache.tomcat.maven</groupId>
                <artifactId>tomcat7-maven-plugin</artifactId>
                <version>2.2</version>
                <configuration>
                    <!--端口号-->
                    <port>8080</port>
                    <!--项目名-->
                    <path>/</path>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

2.2 编写核心代码

2.2.1 前端页面(index.jsp)

jsp

复制代码
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
  <head>
    <title>SpringMVC入门</title>
  </head>
  <body>
  <a href="/hello">hello springmvc</a>
  </body>
</html>
2.2.2 控制器(HelloController)

java

复制代码
@Controller
public class HelloController {
    // 建立请求URL和方法的映射关系
    @RequestMapping("/hello")
    public ModelAndView hello() {
        // 封装模型数据和视图名称
        ModelAndView mv = new ModelAndView();
        // 等价于request.setAttribute("hello", "欢迎你 springmvc!!")
        mv.addObject("hello", "欢迎你 springmvc!!");
        // 设置逻辑视图名(由视图解析器拼接为物理路径)
        mv.setViewName("success");
        return mv;
    }
}
2.2.3 SpringMVC 配置文件(springmvc.xml)

xml

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/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.hg"></context:component-scan>

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

    <!-- 开启SpringMVC注解支持: 配置HandlerMapping和HandlerAdapter-->
    <mvc:annotation-driven></mvc:annotation-driven>
</beans>

​
2.2.4 视图页面(success.jsp)

jsp

复制代码
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>成功页</title>
</head>
<body>
	<h2>${hello}</h2>
</body>
</html>
2.2.5 Web 配置文件(web.xml)

xml

复制代码
<?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_4_0.xsd"
         version="4.0">
    <!-- 配置前端控制器DispatcherServlet -->
    <servlet>
        <servlet-name>springmvc</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <!-- 指定SpringMVC配置文件路径 -->
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:springmvc.xml</param-value>
        </init-param>
        <!-- 容器启动时加载Servlet -->
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>springmvc</servlet-name>
        <!-- /:处理所有请求(排除JSP);/*:处理所有请求(包含JSP) -->
        <url-pattern>/</url-pattern>
    </servlet-mapping>
</web-app>

2.3 测试

启动 Tomcat,访问http://localhost:8080/hello,页面显示欢迎你 springmvc!!即为成功。

2.4 SpringMVC 核心组件

  1. DispatcherServlet(前端控制器):流程控制中心,调用其他组件处理请求,降低耦合
  2. HandlerMapping(处理器映射器):根据请求 URL 查找对应的 Handler(处理器)
  3. Handler(处理器):自定义的 Controller,处理具体业务逻辑
  4. HandlerAdapter(处理器适配器):适配并执行 Handler(适配器模式)
  5. ViewResolver(视图解析器):将逻辑视图名解析为物理视图地址
  6. View(视图):渲染模型数据,将结果响应给浏览器

2.5 SpringMVC 执行流程

DispatcherServlet(前端控制器):接受请求,加载springmvc.xml

HandlerMapping(处理器映射器):查找handler

HandlerAdapter(处理器适配器):调用handler

ViewResolver(视图解析器):拼接jsp的路径

View(视图渲染器):把数据填充到request,跳转页面

  • 用户发起请求到 DispatcherServlet
  • DispatcherServlet 请求 HandlerMapping 查找 Handler
  • HandlerMapping 返回 HandlerExecutionChain(包含 Handler + 拦截器)
  • DispatcherServlet 调用 HandlerAdapter 执行 Handler
  • HandlerAdapter 执行 Handler,返回 ModelAndView
  • DispatcherServlet 请求 ViewResolver 解析视图
  • ViewResolver 返回 View 对象
  • DispatcherServlet 渲染视图(将 Model 数据填充到 View)
  • DispatcherServlet 响应结果给用户

三、RequestMapping 注解

3.1 核心作用

建立请求 URL 和处理方法的映射关系(Map<url,方法>),可标注在类 / 方法上:

  • 类上:定义请求 URL 的第一级目录(窄化路径)
  • 方法上:建立url 和 方法 的映射关系

3.2 核心属性

  • value/path:指定请求 URL
  • method:指定请求方式(RequestMethod.GET/POST 等)

3.3 实战示例

3.3.1 窄化路径

java

复制代码
@Controller
@RequestMapping("/account") // 第一级目录
public class AccountController {
    @RequestMapping("/findAccount") // 第二级目录
    public ModelAndView findAccount() {
        ModelAndView mv = new ModelAndView();
        mv.addObject("msg", "欢迎你 springmvc");
        mv.setViewName("success");
        return mv;
    }
}

index.jsp

html 复制代码
<a href="/account/findAccount">窄化路径</a>
3.3.2 method属性指定请求方式

java

复制代码
@Controller
@RequestMapping("/account")
public class AccountController {
    // 仅允许POST请求
    @RequestMapping(value = "/findAccount1", method = RequestMethod.POST)
    public ModelAndView findAccount1() {
        ModelAndView mv = new ModelAndView();
        mv.addObject("msg", "欢迎你 springmvc");
        mv.setViewName("success");
        return mv;
    }
}

POST 请求测试:

复制代码
<form action="account/findAccount1" method="post">
  <input type="submit" value="POST请求测试">
</form>

四、Controller 方法返回值

4.1 返回 ModelAndView

封装模型数据 + 视图名称,示例见 2.2.2。

4.2 返回字符串

4.2.1 逻辑视图名

java

复制代码
@RequestMapping("/findAccount2")
public String findAccount2(Model model) {
    model.addAttribute("msg", "返回字符串视图名");
    return "success"; // 逻辑视图名,由视图解析器拼接路径
}
4.2.2 Redirect 重定向

java

复制代码
@RequestMapping("/findAccount3")
public String findAccount3() {
    // 重定向到另一个方法,浏览器地址栏变化,新请求
    return "redirect:/account/findAccount4";
}

@RequestMapping("/findAccount4")
public String findAccount4(Model model) {
    model.addAttribute("msg", "SpringMVC重定向");
    return "success";
}
4.2.3 Forward 转发

java

复制代码
@RequestMapping("/findAccount3")
public String findAccount3() {
    // 转发到另一个方法,地址栏不变,共用请求
    return "forward:/account/findAccount4";
}

五、请求参数接收

jsp--->参数--->controller

SpringMVC 通过方法形参接收参数,自动完成类型转换(特殊场景需自定义转换器)。

5.1 基本数据类型

java

复制代码
@RequestMapping("/findAccount5")
public String findAccount5(String username, Integer age, Model model){
    model.addAttribute("msg", username + " " + age);
    return "success";
}

index.jsp

html 复制代码
<a href="/account/findAccount5?username=eric&age=22">基本类型传参</a>

5.2 POJO 类型

5.2.1 定义 POJO

java

复制代码
public class Account implements Serializable {
    private Integer id;
    private String name;
    private Float money;
    private Address address; // 嵌套POJO
    // getter/setter/toString
}

public class Address implements Serializable {
    private String provinceName;
    private String cityName;
    // getter/setter/toString
}
5.2.2 接收 POJO 参数

java

复制代码
@RequestMapping("/saveAccount")
public String saveAccount(Account account, Model model){
    model.addAttribute("msg", account);
    return "success";
}

index.jsp

复制代码
<form action="account/saveAccount" method="post">
    账户名称:<input type="text" name="name"><br/>
    账户金额:<input type="text" name="money"><br/>
    省份:<input type="text" name="address.provinceName"><br/>
    城市:<input type="text" name="address.cityName"><br/>
    <input type="submit" value="保存">
</form>

5.3 RESTful 风格

5.3.1 核心思想

URL 定位资源,HTTP 动词描述操作:

  • GET:查询(/user/1)
  • POST:新增(/user)
  • PUT:修改(/user)
  • DELETE:删除(/user/1)
5.3.2 @PathVariable 注解

绑定 URL 占位符到方法形参:

java

复制代码
@RequestMapping("/findAccount7/{id}")
public String findAccount7(@PathVariable Integer id, Model model){
    model.addAttribute("msg", "RESTful传参:" + id);
    return "success";
}

index.jsp

html 复制代码
<a href="/account/findAccount7/123">RESTful传参</a>

5.4 解决参数乱码

5.4.1 POST 请求(编码过滤器)

在 web.xml 添加:

xml

复制代码
<filter>
  <filter-name>CharacterEncodingFilter</filter-name>
  <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
  <init-param>
    <param-name>encoding</param-name>
    <param-value>UTF-8</param-value>
  </init-param>
</filter>
<filter-mapping>
  <filter-name>CharacterEncodingFilter</filter-name>
  <url-pattern>/*</url-pattern>
</filter-mapping>
5.4.2 GET 请求(Tomcat 编码)

修改 pom.xml 的 Tomcat 插件:

xml

复制代码
<plugin>
    <groupId>org.apache.tomcat.maven</groupId>
    <artifactId>tomcat7-maven-plugin</artifactId>
    <version>2.2</version>
    <configuration>
        <port>8080</port>
        <path>/</path>
        <uriEncoding>UTF-8</uriEncoding> <!-- GET请求编码 -->
    </configuration>
</plugin>

5.5 自定义类型转换器

5.5.1 场景:日期类型转换

前端传递字符串日期(如 2024-01-01),后台用 Date 接收,需自定义转换器:

5.5.2 实现步骤
  1. 定义转换器类:

java

运行

复制代码
public class DateConverter implements Converter<String, Date> {
    @Override
    public Date convert(String source) {
        try {
            DateFormat format = new SimpleDateFormat("yyyy-MM-dd");
            return format.parse(source);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
}
  1. 配置转换器(springmvc.xml):

xml

复制代码
<mvc:annotation-driven conversion-service="conversionService"></mvc:annotation-driven>

<!-- 配置类型转换器工厂 -->
<bean id="conversionService"
      class="org.springframework.context.support.ConversionServiceFactoryBean">
    <property name="converters">
        <set>
            <bean class="com.hg.converter.DateConverter"></bean>
        </set>
    </property>
</bean>

5.6 ServletAPI 接收参数

直接将 HttpServletRequest/HttpServletResponse 作为方法形参:

java

运行

复制代码
@RequestMapping("/findAccount8")
public String findAccount8(HttpServletRequest request, HttpServletResponse response){
    String username = request.getParameter("username");
    String age = request.getParameter("age");
    request.setAttribute("msg", username + " " + age);
    return "success";
}

六、数据传递

6.1 ModelAndView 传递

java

运行

复制代码
@RequestMapping("/findAccount9")
public ModelAndView findAccount9(ModelAndView mv) {
    mv.addObject("msg", "ModelAndView传递数据");
    mv.setViewName("success");
    return mv;
}

6.2 Model 传递

java

运行

复制代码
@RequestMapping("/findAccount10")
public String findAccount10(Model model) {
    model.addAttribute("msg", "Model传递数据");
    return "success";
}

6.3 ServletAPI 传递

java

运行

复制代码
@RequestMapping("/findAccount11")
public String findAccount11(HttpServletRequest request){
    request.setAttribute("msg", "ServletAPI传递数据");
    return "success";
}

七、JSON 数据处理

7.1 添加依赖

SpringMVC 默认使用 Jackson 处理 JSON:

xml

复制代码
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.9.0</version>
</dependency>

7.2 核心注解

  • @RequestBody:接收前端 JSON 字符串,转为 Java 对象
  • @ResponseBody:将 Java 对象转为 JSON 字符串,响应给前端

7.3 实战案例

7.3.1 后端 Controller

java

运行

复制代码
@RequestMapping("/saveAccount2")
@ResponseBody // 响应JSON
public Map<String, Object> saveAccount2(@RequestBody Account account){
    Map<String, Object> map = new HashMap<>();
    map.put("status", 200);
    map.put("msg", account);
    return map;
}
7.3.2 前端 AJAX

html

预览

复制代码
<input type="button" value="测试JSON交互" onClick="testJson()"/>
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
<script type="text/javascript">
  function testJson(){
    axios.post('/account/saveAccount2',{"id":1,"name":"张二狗","money":999.0})
          .then(response => {
              if(response.data.status === 200){
                alert(response.data.msg.name);
              }
          })
          .catch(error => console.error('请求失败:', error));
  }
</script>

总结

本文从 SpringMVC 的核心概念出发,逐步讲解了环境搭建、入门案例、核心注解、参数接收、数据传递、JSON 交互等核心知识点。SpringMVC 作为轻量级 Web 框架,通过分层设计和注解化开发,大幅简化了控制层开发流程,是 Java Web 开发的必备技能。后续将继续讲解拦截器、文件上传、异常处理等高级特性,敬请关注!

相关推荐
阿杜杜不是阿木木1 小时前
从0到1构建像Claude Code那样的Agent(三):行动前先计划
java·服务器·windows·agent·ai编程·claudecode
StackNoOverflow1 小时前
Spring MVC核心知识点快速梳理
java·spring·mvc
步步为营DotNet1 小时前
使用.NET 11的Native AOT提升应用性能
java·前端·.net
jing-ya1 小时前
day 54 图论part6
java·开发语言·数据结构·算法·图论
深念Y1 小时前
Java并发集合:原理与使用场景速查
java·开发语言
恼书:-(空寄2 小时前
Spring Boot 实现事件监听(监听器+自定义事件)完整指南
java·spring boot·后端
我真会写代码2 小时前
深入解析Java ArrayList与HashMap扩容机制:原理、差异与实战避坑
java·数据结构·算法·集合
Victor3562 小时前
MongoDB(48)什么是主从复制?
后端
代码探秘者2 小时前
【大模型应用】3.分块入门
java·后端·python·spring