Spring之旅 - 记录学习 Spring 框架的过程和经验(十三)SpringMVC快速入门、请求处理

前言

本博客的目的是帮助初学者快速入门 Spring MVC,通过简单的示例和详细的说明,介绍 Spring MVC 的基本概念、核心组件以及如何快速构建一个简单的 Web 应用程序。我们将逐步引导您完成从环境配置到请求处理的整个过程,确保您能够掌握 Spring MVC 的关键技能。


SpringMVC简介

SpringMVC是一个基于Spring开发的MVC轻量级框架,pring3.0后发布的组件,SpringMVC和Spring可以无缝整合,使用DispatcherServlet作为前端控制器,且内部提供了处理器映射器、处理器适配器、视图解析器等组件,可以简化JavaBean封装,Json转化、文件上传等操作。

SpringMVC快速入门

导入maven坐标

xml 复制代码
		<dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>5.3.7</version>
        </dependency>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>4.0.1</version>
        </dependency>

配置前端控制器DispatcherServlet

创建web.xml文件,内容如下:

xml 复制代码
<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">

    <!--配置前端控制器DispatcherServlet-->
    <servlet>
        <servlet-name>DispatcherServlet</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:spring-mvc.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>

< servlet>:定义一个 servlet 的配置。

< servlet-name>:DispatcherServlet 的名称,后续在 servlet-mapping 中引用。

< servlet-class>:指定使用的 servlet 类,这里是 Spring MVC 的核心类 DispatcherServlet,负责处理所有的 HTTP 请求。

< init-param>:用于为 servlet 提供初始化参数。

< param-name>:参数名,这里是 contextConfigLocation,它告诉 DispatcherServlet 加载哪个上下文配置文件。

< param-value>:参数值,这里指定的是 spring-mvc.xml 文件,表示在类路径下查找该文件。此文件通常包含 Spring MVC 的 bean 定义,包括控制器、视图解析器等。

< load-on-startup>:指示 servlet 容器在启动时加载这个 servlet,数字越小,优先级越高。这里设置为 2,意味着这个 servlet 会在其他值更小的 servlet 之前被加载(如果有的话)

< servlet-mapping>:定义哪些 URL 请求由该 servlet 处理。

< url-pattern>:/ 表示所有的请求都会被转发到这个 DispatcherServlet,这使得 Spring MVC 可以处理项目中的所有请求。

java 复制代码
package com.itheima.controller;

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

@Controller
public class QuickController {

    @RequestMapping("/show")
    public void show(){
        System.out.println("show running.......");
    }
}

@Controller:这个注解告诉 Spring 框架,将 QuickController 类标识为一个 Spring MVC 控制器。Spring 会自动检测并注册这个控制器,以便能够处理来自客户端的请求。

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

</beans>

运行代码,访问http://localhost:8080/spring_webmvc_war/show

Controller中访问容器中的Bean

java 复制代码
@Controller
public class QuickController {
    //直接注入service使用
    @Autowired
    private QuickService quickService;
    @RequestMapping("/show")
    public void show(){
        System.out.println("show running......."+quickService);

    }
}

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

</beans>

web.xml内容如下:

xml 复制代码
<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">

    <!--配置前端控制器DispatcherServlet-->
    <servlet>
        <servlet-name>DispatcherServlet</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:spring-mvc.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>
    <!--配置ContextLoaderListener-->
    <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>

</web-app>

运行结果如下:

SpringMVC关键组件浅析

上面已经完成的快速入门的操作,也在不知不觉中完成的Spring和SpringMVC的整合,我们只需要按照规则去定义Controller和业务方法就可以。但是在这个过程中,肯定是很多核心功能类参与到其中,这些核心功能类,一般称为组件。当请求到达服务器时,是哪个组件接收的请求,是哪个组件帮我们找到的Controller,是哪个组件帮我们调用的方法,又是哪个组件最终解析的视图?

SpringMVC的默认组件,SpringMVC在前端控制器DispatcherServet加载时,就会进行初始化操作,在进行初始化时,就会加载SpringMVC默认指定的一些组件,这些默认组件配置在DispatcherServlet.properties文件中,该文件存在与spring-webmvc-5.3.7jar包下的 org\springframework\web\servlet\DispatcherServlet.properties

SpringMVC的请求处理

请求映射路径的配置

配置映射路径,映射器处理器才能找到Controller的方法资源,目前主流映射路径配置方式就是@RequestMapping

@RequestMapping注解,主要使用在控制器的方法上,用于标识客户端访问资源路径,常用的属性有value、path、method、headers、params等。当@RequestMapping只有一个访问路径需要指定时,使用value属性、path属

性或省略value和path,当有多个属性时,value和path不能省略

java 复制代码
@RequestMapping(value = "/show")//使用value属性指定一个访问路径
public String show(){}
@RequestMapping(value = {"/show","/haohao","/abc"})//使用value属性指定多个访问路径
public String show(){}
@RequestMapping(path = "/show")//使用path属性指定一个访问路径
public String show(){}
@RequestMapping(path = {"/show","/haohao","/abc"})//使用path属性指定多个访问路径
public String show(){}
@RequestMapping("/show")//如果只设置访问路径时,value和path可以省略
public String show(){}
@RequestMapping({"/show","/haohao","/abc"})
public String show(){}

当@RequestMapping 需要限定访问方式时,可以通过method属性设置

java 复制代码
//请求地址是/show,且请求方式必须是POST才能匹配成功
@RequestMapping(value = "/show",method = RequestMethod.POST)
public String show(){}

@RequestMapping 在类上使用,@RequestMapping 、@GetMapping、@PostMapping还可以使用在

Controller类上,使用在类上后,该类所有方法都公用该@RequestMapping设置的属性,访问路径则为类上的映射

地址+方法上的映射地址,例如:

java 复制代码
@Controller
@RequestMapping("/user")
public class UserController implements ApplicationContextAware, ServletContextAware {
	 @GetMapping("/show")
	 public ModelAndView show(HttpServletResponse response) throws IOException, 
ModelAndViewDefiningException {
	 return null;
	 }
}

请求数据的接收

接收普通请求数据,当客户端提交的数据是普通键值对形式时,直接使用同名形参接收即可

java 复制代码
name=heima&age=18
java 复制代码
@GetMapping("/show")
public void Param(String name, int age){
	System.outhprintln (name+":"+age);
}

当不同名是我们使用@RequestParam注解

java 复制代码
	@GetMapping("/param1")
    public void Param1(@RequestParam("username") String name, String age){
        System.out.println(name+": "+age);
    }

当请求参数有特殊格式数据,如日期时

java 复制代码
name=heima&age=18&birthday=2026/01/01
java 复制代码
@GetMapping("/param")
public void show(String name,int age,Date birthday){
 System.out.println(name+":"+age+",生日:"+birthday);
}

Date可以正常接收,因为Spring内置的类型解析器,可以识别的日期格式是 yyyy/MM/dd,但是如果我们提交其他格式,例如:yyyy-MM-dd 时,类型转换会报错,如下:

java 复制代码
name=heima&age=18&birthday=2026-01-01

解决方案,使用@DateTimeFormat 指定日期格式

java 复制代码
@GetMapping("/param")
public void param(String name,int age,@DateTimeFormat(pattern = "yyyy-MM-dd") Date 
birthday){
 System.out.println(name+":"+age+",生日:"+birthday);
}

同时遇到同名的多个值时,可以用数组进行接收 。

java 复制代码
hobby=play&hobby=run&hobby=swim
java 复制代码
@GetMapping("/param")
    public void Param(String[] hobby){
        System.out.println("hobby: "hobby);
    }

接收数组或集合数据,客户端传递多个同名参数时,也可以使用单列集合接收,但是需要使用@RequestParam告知框架传递的参数是要同名设置的,不是对象属性设置的

java 复制代码
@GetMapping("/param")
    public void Param(@RequestParam List<String> hobby){
        System.out.println("hobby: "hobby);
    }

接收数组或集合数据,客户端传递多个不同命名参数时,也可以使用Map<String,Object> 进行接收,同样需要用@RequestParam 进行修饰

java 复制代码
name=heima&age=18
java 复制代码
@GetMapping("/param")
public void param(@RequestParam Map<String,Object> params){
	 params.forEach((key,value)->{
	 System.out.println(key+"="+value);
	 });
}

接收实体JavaBean属性数据,单个JavaBean数据:提交的参数名称只要与Java的属性名一致,就可以进行自动封装

java 复制代码
username=heima&age=18&hobbies=play&hobbies=swim
java 复制代码
public class User {
	private String username;
	private Integer age;
	private String[] hobbies;
	private Date birthday;
	private Address address;
	省略get和set方法...
}
java 复制代码
@GetMapping("/show")
public void show(User user){
	System.out.println(user);
}

接收Json数据格式数据,Json数据都是以请求体的方式提交的,且不是原始的键值对格式的,所以我们要使用@RequestBody注解整体接收该数据。

json 复制代码
{
    "username": "heima",
    "age": 18,
    "hobbies": ["swim", "play"],
    "birthday": "2026-01-01",
    "address": {
        "city": "henan",
        "area": "sanmenxia"
    }
}
java 复制代码
	@PostMapping("/show")
    public void show(@RequestBody String body){
        System.out.println(body);
    }

使用Json工具( jackson )将Json格式的字符串转化为JavaBean进行操作

xml 复制代码
<dependency>
	 <groupId>com.fasterxml.jackson.core</groupId>
	 <artifactId>jackson-databind</artifactId>
	 <version>2.9.0</version>
</dependency>
java 复制代码
		@PostMapping("/show")
    public String show(@RequestBody String body) throws IOException {
        ObjectMapper objectMapper = new ObjectMapper();
        User user = objectMapper.readValue(body, User.class);
        System.out.println(user);
        return "/index.jsp";
    }

配置RequestMappingHandlerAdapter,指定消息转换器,就不用手动转换json格式字符串了

xml 复制代码
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
	 <property name="messageConverters">
	 	<list>
	 		<bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter"/>
	 	</list>
	 </property>
</bean>
java 复制代码
	@PostMapping("/show")
    public String show(@RequestBody User user) {
        System.out.println(user);
        return "/index.jsp";
    }

总结

随着对 Spring MVC 的深入理解,您可以进一步探索其高级特性,如拦截器、参数转换、国际化等。希望本博客能够为您的学习之旅提供有价值的参考,祝您在 Spring MVC 的开发中取得成功!

相关推荐
桦说编程2 小时前
并发编程踩坑实录:这些原则,帮你少走80%的弯路
java·后端·性能优化
BHXDML2 小时前
JVM 深度理解 —— 程序的底层运行逻辑
java·开发语言·jvm
tkevinjd2 小时前
net1(Java中的网络编程、TCP的三次握手与四次挥手)
java
码头整点薯条2 小时前
基于Java实现的简易规则引擎(日常开发难点记录)
java·后端
曾浩轩2 小时前
跟着江协科技学STM32之4-5OLED模块教程OLED显示原理
科技·stm32·单片机·嵌入式硬件·学习
J2虾虾2 小时前
Java使用的可以使用的脚本执行引擎
java·开发语言·脚本执行
老马识途2.02 小时前
java处理接口返回的json数据步骤 包括重试处理,异常抛出,日志打印,注意事项
java·开发语言
d***81722 小时前
springboot 修复 Spring Framework 特定条件下目录遍历漏洞(CVE-2024-38819)
spring boot·后端·spring
2***d8852 小时前
Spring Boot中的404错误:原因、影响及处理策略
java·spring boot·后端