Spring MVC 实战:复杂类型接收表单字段

简介: 前言这是 Spring MVC 处理器方法参数实战的第二篇,我们来尝试使用复杂的成员变量类型来接收 form 表单字段。对于普通的 Java Web 项目,我们一般通过 ServletRequest#getParameter 方法来获取字符串类型的 form 表单字段值。

前言


这是 Spring MVC 处理器方法参数实战的第二篇,我们来尝试使用复杂的成员变量类型来接收 form 表单字段。


对于普通的 Java Web 项目,我们一般通过 ServletRequest#getParameter 方法来获取字符串类型的 form 表单字段值。


对于 Spring MVC 项目,直接将简单类型定义为处理器方法参数即可获取 form 表单字段值,如果表单字段比较多,还可以使用一个复杂类型来接收所有的表单字段值。


通常情况下,我们使用简单类型接收单个表单字段就足够了,然而在复杂的场景下,简单类型可能无法满足我们的需求。对于 application/json 类型的请求,我们可以定义任意复杂的类型来接收 json 格式的请求体,那么对于 form 类型的请求又该如何处理呢?


简单类型


先看看 Spring MVC 如何使用简单类型接收表单参数,假定我们要做一个注册功能,我们需要接收账号和密码,可以使用如下方式。


@RestController
public class UserController {
    @PostMapping("/register")
    public User register(@RequestParam("username") String username, @RequestParam("password") String password) {
        return null;
    }
}


如果表单字段比较多,我们可以把参数移到自定义的类型中。


@Data
public class User {
    private String username;
    private String password;
}
@RestController
public class UserController {
    @PostMapping("/register")
    public User register(User user) {
        return user;
    }
}


自定义类型


现在除了用户名和密码,我们还希望用户注册时能够提供所在省市,我们常规的思路是添加两个分别表示省份和城市的表单字段。


@Data
public class User {
    private String username;
    private String password;
    private String province;
    private String city;
}


省份和城市属于地址信息,可能我们希望定义到 Address 类中。


@Data
public class Address {
    private String province;
    private String city;
}
@Data
public class User {
    private String username;
    private String password;
    private Address address;
}


我们还希望使用 User 接收表单字段,但是表单字段只能传递字符串,该怎么办呢?

好在 Spring MVC 已经为我们考虑到了这种情况,使用 . 分隔成员变量作为表单字段名即可将表单字段值正确的绑定到自定义的成员变量类型中。PostMan 测试如下。


32.png


Spring MVC 成功解析出了表单 address.province 及 address.city 字段,并设置到 User 类型 address 成员变量中。


数组类型


除了自定义的类型,我们可能还有使用 List 或者数组接收表单字段的场景,例如在注册用户时我们希望用户提供兴趣爱好。修改 User 类型如下。


@Data
public class User {
    private String username;
    private String password;
    private Address address;
    private List<String> interests;
}


对于这种场景,我们可以使用类似 Java 数组的语法,成员变量后面添加 [index] 作为索引,其中索引值 index 为数字,也可以被单引号或双引号包括。PostMan 测试如下。


34.png



Spring 成功将表单字段解析到 List 中,对于数组同样适用,而且 Spring 还兼容了 [] 中的单引号或者双引号,索引从 0 开始,如果索引不连续中间的值则为 null。


Map 类型


如果我们还想让用户添加自定义的字段该怎么办呢?假定我们想使用 `Map 接收,可以修改 User 类型如下。


@Data
public class User {
    private String username;
    private String password;
    private Address address;
    private List<String> interests;
    private Map<String,Object> extra;
}


此时可以表单字段名称可以同样可以使用数组类型的语法,成员变量名后跟 [key] 作为 Map 中的 key,[] 内部可以添加单引号或者双引号。使用 PostMan 测试如下。


35.png


服务端成功使用 Map 接收到了表单字段。


实现分析


简单对复杂类型接收表单字段的实现做一个分析。对于处理器方法参数解析,都是 HandlerMethodArgumentResolver 处理的,前面几篇文章也断断续续提到了这个接口,对于不带注解的复杂类型,Spring MVC 使用的实现是 ModelAttributeMethodProcessor,这个实现会将 request 表单字段绑定到方法参数中,主要就是用到了 Spring 数据绑定的特性。


目录
相关文章
|
1月前
|
XML Java 测试技术
Spring5入门到实战------17、Spring5新功能 --Nullable注解和函数式注册对象。整合JUnit5单元测试框架
这篇文章介绍了Spring5框架的三个新特性:支持@Nullable注解以明确方法返回、参数和属性值可以为空;引入函数式风格的GenericApplicationContext进行对象注册和管理;以及如何整合JUnit5进行单元测试,同时讨论了JUnit4与JUnit5的整合方法,并提出了关于配置文件加载的疑问。
Spring5入门到实战------17、Spring5新功能 --Nullable注解和函数式注册对象。整合JUnit5单元测试框架
|
1月前
|
Java
Spring5入门到实战------9、AOP基本概念、底层原理、JDK动态代理实现
这篇文章是Spring5框架的实战教程,深入讲解了AOP的基本概念、如何利用动态代理实现AOP,特别是通过JDK动态代理机制在不修改源代码的情况下为业务逻辑添加新功能,降低代码耦合度,并通过具体代码示例演示了JDK动态代理的实现过程。
Spring5入门到实战------9、AOP基本概念、底层原理、JDK动态代理实现
|
6天前
|
缓存 前端开发 Java
【Java面试题汇总】Spring,SpringBoot,SpringMVC,Mybatis,JavaWeb篇(2023版)
Soring Boot的起步依赖、启动流程、自动装配、常用的注解、Spring MVC的执行流程、对MVC的理解、RestFull风格、为什么service层要写接口、MyBatis的缓存机制、$和#有什么区别、resultType和resultMap区别、cookie和session的区别是什么?session的工作原理
【Java面试题汇总】Spring,SpringBoot,SpringMVC,Mybatis,JavaWeb篇(2023版)
|
30天前
|
Java 数据库连接 Spring
后端框架入门超详细 三部曲 Spring 、SpringMVC、Mybatis、SSM框架整合案例 【爆肝整理五万字】
文章是关于Spring、SpringMVC、Mybatis三个后端框架的超详细入门教程,包括基础知识讲解、代码案例及SSM框架整合的实战应用,旨在帮助读者全面理解并掌握这些框架的使用。
后端框架入门超详细 三部曲 Spring 、SpringMVC、Mybatis、SSM框架整合案例 【爆肝整理五万字】
|
1月前
|
NoSQL Java Redis
Redis6入门到实战------ 八、Redis与Spring Boot整合
这篇文章详细介绍了如何在Spring Boot项目中整合Redis,包括在`pom.xml`中添加依赖、配置`application.properties`文件、创建配置类以及编写测试类来验证Redis的连接和基本操作。
Redis6入门到实战------ 八、Redis与Spring Boot整合
|
1月前
|
XML JSON 数据库
SpringMVC入门到实战------七、RESTful的详细介绍和使用 具体代码案例分析(一)
这篇文章详细介绍了RESTful的概念、实现方式,以及如何在SpringMVC中使用HiddenHttpMethodFilter来处理PUT和DELETE请求,并通过具体代码案例分析了RESTful的使用。
SpringMVC入门到实战------七、RESTful的详细介绍和使用 具体代码案例分析(一)
|
1月前
|
前端开发 Java Spring
SpringMVC种通过追踪源码查看是哪种类型的视图渲染器(一般流程方法)
这篇文章通过示例代码展示了如何在Spring MVC中编写和注册拦截器,以及如何在拦截器的不同阶段添加业务逻辑。
SpringMVC种通过追踪源码查看是哪种类型的视图渲染器(一般流程方法)
|
1月前
|
SQL 数据库
Spring5入门到实战------13、使用JdbcTemplate操作数据库(批量增删改)。具体代码+讲解 【下篇】
这篇文章是Spring5框架的实战教程,深入讲解了如何使用JdbcTemplate进行数据库的批量操作,包括批量添加、批量修改和批量删除的具体代码实现和测试过程,并通过完整的项目案例展示了如何在实际开发中应用这些技术。
Spring5入门到实战------13、使用JdbcTemplate操作数据库(批量增删改)。具体代码+讲解 【下篇】
|
1月前
|
XML Java 数据格式
Spring5入门到实战------11、使用XML方式实现AOP切面编程。具体代码+讲解
这篇文章是Spring5框架的AOP切面编程教程,通过XML配置方式,详细讲解了如何创建被增强类和增强类,如何在Spring配置文件中定义切入点和切面,以及如何将增强逻辑应用到具体方法上。文章通过具体的代码示例和测试结果,展示了使用XML配置实现AOP的过程,并强调了虽然注解开发更为便捷,但掌握XML配置也是非常重要的。
Spring5入门到实战------11、使用XML方式实现AOP切面编程。具体代码+讲解
|
22天前
|
Java API UED
【实战秘籍】Spring Boot开发者的福音:掌握网络防抖动,告别无效请求,提升用户体验!
【8月更文挑战第29天】网络防抖动技术能有效处理频繁触发的事件或请求,避免资源浪费,提升系统响应速度与用户体验。本文介绍如何在Spring Boot中实现防抖动,并提供代码示例。通过使用ScheduledExecutorService,可轻松实现延迟执行功能,确保仅在用户停止输入后才触发操作,大幅减少服务器负载。此外,还可利用`@Async`注解简化异步处理逻辑。防抖动是优化应用性能的关键策略,有助于打造高效稳定的软件系统。
31 2