Spring MVC学习随笔-控制器(Controller)开发详解:接受客户端(Client)请求参数

学习视频:孙哥说SpringMVC:结合Thymeleaf,重塑你的MVC世界!|前所未有的Web开发探索之旅

第三章、SpringMVC控制器开发详解

3.1 核心要点

3.2 控制器接受客户端(client)请求参数详解

3.2.1 回顾:Web开发中如何接受Client请求参数

3.2.2 基于Servlet API接受Client请求参数

@Controller
@RequestMapping("/param")
public class ParamController {@RequestMapping("param1")public String param(HttpServletRequest request) {String name = request.getParameter("name");String password = request.getParameter("password");System.out.println("name = " + name);System.out.println("password = " + password);return  "param1";}
}
**注意:这种方式虽然最为直观,简单,但是代码冗余且与ServletAPI存在耦合,所以在SpringMVC开发中并不建议使用**

3.2.3 基于简单变量接受Client请求参数

  1. 所谓简单变量:指的就是8种基本类型+String这些类型的变量。把这些类型的变量,作为控制器方法的形参,用于接受client提交的数据。
  • 思路分析

  • 代码

    @Controller
    @RequestMapping("/param")
    public class ParamController {@RequestMapping("param2")public String param2(String name,String password) {System.out.println("name = " + name);System.out.println("password = " + password);return  "param1";}
    }
    
  • 细节分析

    • 常见类型自动转换

      @RequestMapping("param3")
      public String param3(String name,int age) {System.out.println("name = " + name);System.out.println("age = " + age);return  "param1";
      }SpringMVC底层针对age接受数据时会自动调用 int age = Integer.parseInt("10")
      
      1. 常见类型泛指:8种基本类型及其包装器,String等常见类型。
      2. Date日期等特殊类型,默认不支持,需要程序员自定义类型转换器【后续讲解】
    • 基本类型尽量使用包装器

      客户端请求:http://localhost:8989/param/param/param3?name=jack
      @Controller
      @RequestMapping("/param")
      public class ParamController {@RequestMapping("param3")public String param3(String name,int age) {System.out.println("name = " + name);System.out.println("age = " + age);return  "param1";}
      }
      程序报错:原因在于age没有提交内容,等同于null,而int是基本类型无法存储null值,所以报错
      改正方式:1.age参数使用包装器类型,可以存储null2.为age参数设置默认值,需要@RequestParam注解配合使用。
      

3.2.4 基于POJO类型接受Client请求参数

  • 什么是POJO
    1. POJO全称叫做 Plain Ordinary Java Object(简单的Java对象)
    2. POJO类型对象的特点是:
      1. 类型中如果存在成员变量,必须提供set get
      2. 提供默认无参构造
      3. 可以实现Serializable,也可以不实现
      4. 不实现容器或者框架所规定的接口
    3. 用户根据业务封装的实体,DTO这些类型就是POJO
  • 使用场景

准备一个实体,成员变量名字要和表单的name对应,其次在控制器方法中,将POJO类作为形参类型定义在控制器方法参数中。
  • 代码

    // POJO
    public class User implements Serializable {private String name;private String password;private int age;// Controller
    @RequestMapping("param4")public String param4(User user) {System.out.println("user = " + user);return  "param1";}
    // 表单请求
    <form method="post" action="${pageContext.request.contextPath}/param/param4">UserName <input type="text" name="name"><br>Password <input type="text" name="password"><br>Age <input type="text" name="age"><br><input type="submit" value="reg">
    </form>
    **POJO的成员变量的名字要和请求参数的key或者表单name属性的值严格对应**
    
  • 注意1.提交的表单中的name和控制器方法的name同名,那么谁会获取到内容?

    http://localhost:8989/param/param/param4?name=小明&age=12&password=12
    @RequestMapping("param4")public String param4(**String name**,User user) {System.out.println("user = " + user);return  "param1";}
    **name形参与user对象的name属性都会获取对应的内容,这个特定在后续前后端分离中会使用。**
    
  • 注意2.

    1. 如果SpringMVC发现控制器形参类型,是8种基本类型+String的话,他会通过形参名与请求参数的key对象,接受数据
    2. 如果SpringMVC发现控制器形参类型,不是8种基本类型+String的话,他会通过形参类型的属性名与请求参数的key对象,接受数据
    3. 如果存在自定义类型转换器不适用于上述规律

3.2.5 接受一组简单变量的请求参数

  • 使用场景

  • 代码

    @RequestMapping("param5")
    public String param5(Integer[] ids) {for (Integer id : ids) {System.out.println("id = " + id);}return  "param1";
    }
    // checkbox表单
    <form method="post" action="${pageContext.request.contextPath}/param/param5"><input type="checkbox" name="ids" value="1"><br><input type="checkbox" name="ids" value="2"><br><input type="checkbox" name="ids" value="3"><br><input type="checkbox" name="ids" value="4"><br><input type="checkbox" name="ids" value="5"><br><input type="submit" value="reg">
    </form>
    
  • 细节分析 以List类举例

    @RequestMapping("param6")
    public String param6(ArrayList<Integer> ids) {for (Integer id : ids) {System.out.println("id = " + id);}return  "param1";
    }
    没有异常,但接收不到数据:SpringMVC会按照POJO的匹配方式,进行成员变量查找@RequestMapping("param6")public String param6(List<Integer> ids) {for (Integer id : ids) {System.out.println("id = " + id);}return  "param1";}
    抛出异常:SpringMVC无法提供具体的实现类、实例化形参
    

3.2.6 接收一组POJO类型对象的请求参数

  • 使用场景

按照POJO的匹配方式,对于非8种基本类型的方法形参,只有将List实例化作为成员变量封装在POJO类中,并将这个类作为形参才能正确接收数据。

  • 代码

    **// POJO类**
    public class UsersDTO {private List<User> users = new ArrayList<>();public List<User> getUsers() {return users;}public void setUsers(List<User> users) {this.users = users;}
    }
    **//Controller类**
    @RequestMapping("param7")public String param7(UsersDTO usersDTO) {List<User> users = usersDTO.getUsers();for (User user : users) {System.out.println("user = " + user);}return  "param1";}**//JSP页**
    <form method="post" action="${pageContext.request.contextPath}/param/param7">UserName <input type="text" name="users[0].name"><br>Password <input type="text" name="users[0].password"><br>Age <input type="text" name="users[0].age"><br><hr>UserName <input type="text" name="users[1].name"><br>Password <input type="text" name="users[1].password"><br>Age <input type="text" name="users[1].age"><br><input type="submit" value="submit">
    </form>
    

3.3 接收Client请求参数的总结

3.4@RequestParam注解

作用:用于修饰控制器方法的形参

@RequestMapping("param2")
public String param2(@RequestParam String name,@RequestParam String password)

3.4.1 @RequestParam注解详解

  • 解决请求参数与方法形参名字不一致的问题

    Http请求:http://localhost:8989/param/param1/param1?n=jack&p=1234
    @RequestMapping("/param1")
    public String param1(@RequestParam("n") String name, @RequestParam("p") String password) {System.out.println("name = " + name);System.out.println("password = " + password);return "param1";
    }
  • 注意

    1. @RequestParam注解简写形式:不书写value书写的内容,@RequestParam默认会把对应形参名作为value属性的值

    2. 使用了@RequestParam注解的形参,客户端必须传递数据,不能省略,否则报错。

    3. POJO类型的形参,不能与@RequestParam注解联用。会报400错误

    4. 典型的应用场景

      htpp请求:http://localhost:8989/param/paramController/param1?id≤10
      @RequestMapping("/param1")
      public String param1(@RequestParam("id<") Integer id) {
      }
      **当提交的数据参数名不符合java的变量命名规则时,可以采用这种方式**
      
  • @RequestParam的required属性

    required = true时:@RequestParam修饰的控制器方法参数,客户端必须提交数据,否则报错,默认值

    required = false时:@RequestParam修饰的控制器方法参数,客户端可以不提交数据,不会报错

    解决了使用@RequestParam注解时,客户端必须传递数据的问题。

  • @RequestParam的defaultValue属性

    • 客户端没有提交数据的时候,给对应的形参提供默认值

      http://localhost:8989/param/paramController/param1?name=jack
      @RequestMapping("/param4")public String param4(@RequestParam String name, @RequestParam(defaultValue="9999") String password) {System.out.println("name = " + name);System.out.println("password = " + password);return "param1";}
      注意:如果使用了defaultValue,则required属性也默认设置成了false
      
    • 解决控制器方法形参,使用包装器的问题

      @RequestMapping("param6")
      public String param6(@RequestParam(defaultValue = "0") int age) {System.out.println("age = " + age);return "param1";
      }
      
    • defaultValue典型的使用场景

      默认值操作,一个典型的应用场景是:分页首页查询,不传页号的设计

      http://localhost:8989/param/page/findall
      http://localhost:8989/param/page/findall?pageNum=2
      @RequestMapping("findall")
      public String findall(@RequestParam(defaultValue = "0") int pageNum) {}
      

3.5 中文请求参数的乱码问题

3.5.1 回顾JavaWeb开发中 中文乱码的解决方案

  • GET请求乱码的解决方案

  • POST请求乱码的解决方案

3.5.2 SpringMVC解决中文字符集乱码

  1. GET请求的中文乱码

    UTF-8字符集,Tomcat8已经内部处理,无需我们处理。GBK字符集或者Tomcat8以前版本,需要配置server.xml

  2. POST请求的中文乱码,SpringMVC提供了过滤器解决

    org.springframework.web.filter.CharacterEncodingFilter

  • web.xml配置(通过alt+insert插入)

    <filter><filter-name>encodingFilter</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>encodingFilter</filter-name><url-pattern>/*</url-pattern>
    </filter-mapping>
    

3.6 SpringMVC的类型转换器

3.6.1 SpringMVC中的内置类型转换器

  • 分析

  • 内置类型转换器的概念

    1. SpringMVC中提供了内置类型转换器,把客户端提交的字符串类型的请求参数,转换承控制器方法参数需要的数据类型

    2. SpringMVC并不是对于所有的类型,都提供了内置的类型转换器,他只是提供了常见类型的转换器

      比如:8种基本类型,常见的集合类型等

  • 原理分析

在SpringMVC启动时,会通过mvc:annotation-driven/把FormattingConversionServiceFactoryBean。引入到SpringMVC体系中。FormattingConversionServiceFactoryBean存储了SpringMVC种所有的内置类型转换器。后续client提交请求参数时,如果对于控制器方法形参不是字符串类型,那么FormattingConversionServiceFactoryBean就会调用对应的类型转换器,进行类型转换,最终完成控制器方法形参的赋值。

3.6.2 SpringMVC中自定义类型转换器

SpringMVC在接收客户端提交请求参数时,如果请求参数对应的控制器方法形参,是非常规数据类型,SpringMVC默认情况下无法进行类型转换。会抛出异常,程序员可以通过自定义类型转换器解决上述问题。例如:日期类型
  • 开发思路

  • 编码

    **// 实现Converter<S,T>接口**
    public class DateConverter implements Converter<String, Date> {@Overridepublic Date convert(String source) {Date date = null;SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");try {date = sdf.parse(source);} catch (ParseException e) {e.printStackTrace();}return date;}
    }
    // **配置类型转换器,让Spring进行对象的创建**
    <bean id="dateConverter" class="com.baizhi.DateConverter"/>
    // **进行类型转换器注册,让SpringMVC能够识别日期类型转换的类型转换器-->**
    <bean id="serviceFactoryBean" class="org.springframework.format.support.FormattingConversionServiceFactoryBean"><property name="converters"><set><ref bean="dateConverter"/></set></property></bean>
    // **最后一步**
    <mvc:annotation-driven conversion-service="serviceFactoryBean"/>// **上述第一步 第二步可以合二为一**
    <bean id="formattingConversionService" class="org.springframework.format.support.FormattingConversionServiceFactoryBean"><property name="converters"><set><bean id="converter" class="com.baizhi.DateConverter"/></set></property></bean>
    

3.7 接收其他请求数据

3.7.1 动态参数收集

  • 单值动态参数收集(一个key对应一个请求数据)

    http://localhost:8989/param/param2/param1?name=suns
    http://localhost:8989/param/param2/param1?age=10
    @RequestMapping("/param1")public String param1(@RequestParam Map<String, String> params) {Set<String> keys = params.keySet();for (String key : keys) {System.out.println("key = " + key+",value = "+params.get(key));}return "param1";}
    **注意:如果需要接收动态参数,必须保证Map的形参前面加入@RequestParam注解,否则接收不到数据**
    
  • 多值动态参数收集(一个key对应多个请求数据)

    http://localhost:8989/param/param2/param1?id=2&id=3&id=4**第一种解决思路:通过数组形参接收请求参数**
    @RequestMapping("param5")
    public String param5(Integer[] ids) {for (Integer id : ids) {System.out.println("id = " + id);}return  "param1";
    }
    存在的问题:请求参数的key发生改变就接收不到请求数据第二种解决思路:通过MultiValueMap<K,V> 接收请求参数
    @RequestMapping("/param2")public String param2(@RequestParam MultiValueMap<String, String> params) {Set<String> keys = params.keySet();for (String key : keys) {List<String> values = params.get(key);System.out.println("key = " + key);for (String value : values) {System.out.println("value = " + value);}}return "param1";}
    
  • 典型应用场景

3.7.2 接收cookie数据

  • 回顾Servlet中获取的方式

  • SpringMVC获取Cookie的方式

    测试Cookie 通过postman测试
    @RequestMapping("/param4")
    public String param4(@CookieValue("name") String value) {System.out.println("value = " + value);return "param1";
    }
    推荐使用@CookieValue获取cookie@RequestMapping("/param3")
    public String param3(HttpServletRequest request) {Cookie[] cookies = request.getCookies();for (Cookie cookie : cookies) {if ("name".equals(cookie.getName())) {System.out.println("cookie.getValue() = " + cookie.getValue());}}return "param1";
    }
    这种方式基于Servlet API存在耦合,不推荐使用。
    

3.7.3 接收请求头数据

  • 什么是请求头

  • 获取请求头的方式
    • Servlet中的获取方式

      核心代码
      String value = request.getHeader("key");
      
    • SpringMVC中的获取方式

      @RequestMapping("/param6")
      public String param6(@RequestHeader("Host") String host) {System.out.println("host = " + host);return "param1";
      }
      推荐使用@RequestHeader的方式获取请求头@RequestMapping("/param5")
      public String param5(HttpServletRequest request) {String host = request.getHeader("Host");System.out.println("host = " + host);return "param1";
      }
      这种方式存在与Servlet API的耦合问题,不建议后续使用
      

下一章:Spring MVC学习随笔-控制器(Controller)开发详解:调用业务对象、父子工厂拆分(applicationContext.xml、dispatcher.xml)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/192806.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Docker的数据持久化;Docker网络;Dockerfile编写

Docker的数据持久化&#xff1b;Docker网络&#xff1b;Dockerfile编写&#xff1b; 文章目录 Docker的数据持久化&#xff1b;Docker网络&#xff1b;Dockerfile编写&#xff1b;**Docker的数据持久化**1&#xff09;将本地目录映射到容器里2&#xff09;数据卷3&#xff09;将…

ARM架构安装RabbitMQ

1.查看centos内核版本 uname -a uname -r2.安装之前的准备工作 安装RabbitMQ必装Erlang(RabbitMQ官网添加链接描述) 2.1.Erlang简介 Erlang是一种通用的面向并发的编程语言&#xff0c;它由瑞典电信设备制造商爱立信所辖的CS-Lab开发&#xff0c;目的是创造一种可以应对…

Qt将打印信息输出到文件

将打印信息&#xff08;qDebug、qInfo、qWarning、qCritial等&#xff09;输出到指定文件来以实现简单的日志功能。 #include "mainwindow.h" #include <QApplication> #include <QLoggingCategory> #include <QMutex> #include <QDateTime>…

【Pytorch】Visualization of Feature Maps(4)——Saliency Maps

学习参考来自 Saliency Maps的原理与简单实现(使用Pytorch实现)https://github.com/wmn7/ML_Practice/tree/master/2019_07_08/Saliency%20Maps Saliency Maps 原理 《Deep Inside Convolutional Networks: Visualising Image Classification Models and Saliency Maps》&…

vue权限管理解决方案

一. 什么是权限管理 权限控制是确保用户只能访问其被授权的资源和执行其被授权的操作的重要方面。而前端权限归根结底是请求的发起权&#xff0c;请求的发起可能有下面两种形式触发 页面加载触发页面上的按钮点击触发 总体而言&#xff0c;权限控制可以从前端路由和视图两个…

深度学习记录--广播(Broadcasting)

什么是广播&#xff1f; 广播(Broadcasting)&#xff0c;在python中是一种矩阵初等运算的手段&#xff0c;用于将一个常数扩展成一个矩阵&#xff0c;使得运算可行 广播的作用 比如&#xff1a; 一个1*n的矩阵要和常数b相加&#xff0c;广播使得常数b扩展成一个1*n的矩阵 …

zemax之初级像差理论与像差校正——慧差

通过上节介绍&#xff0c;我们已经知道在轴上视场产生的球差是旋转对称的像差。在进行光学系统设计时&#xff0c;同时需要保证轴上物点和轴外物点的成像质量。轴外物点成像时会引入轴外像差&#xff0c;即轴外视场产生的慧差&#xff08;coma aberration&#xff09; 1.慧差概…

申请Azure学生订阅——人工验证

一&#xff1a;联系客服进行人工验证 点击 Services Hub 填写资料申请人工验证 点击 Azure - Sign up 进行学生验证 二&#xff1a;与客服的邮件沟通的记录 ​​​​一、结果&#xff08;输入客服给的验证码后&#xff0c;笔者便得到了学生订阅&#xff09;&#xff1a; 二…

k8s中批量处理Pod应用的Job和CronJob控制器、处理守护型pod的DaemonSet控制器介绍

目录 一.Job控制器 1.简介 2.Jobs较完整解释 3.示例演示 4.注意&#xff1a;如上例的话&#xff0c;执行“kubectl delete -f myJob.yaml”就可以将job删掉 二.CronJob&#xff08;简写为cj&#xff09; 1.简介 2.CronJob较完整解释 3.案例演示 4.如上例的话&#xf…

[原创][2]探究C#多线程开发细节-“线程的无顺序性“

[简介] 常用网名: 猪头三 出生日期: 1981.XX.XX QQ: 643439947 个人网站: 80x86汇编小站 https://www.x86asm.org 编程生涯: 2001年~至今[共22年] 职业生涯: 20年 开发语言: C/C、80x86ASM、PHP、Perl、Objective-C、Object Pascal、C#、Python 开发工具: Visual Studio、Delph…

golang Pool实战与底层实现

使用的go版本为 go1.21.2 首先我们写一个简单的Pool的使用代码 package mainimport "sync"var bytePool sync.Pool{New: func() interface{} {b : make([]byte, 1024)return &b}, }func main() {for j : 0; j < 10; j {obj : bytePool.Get().(*[]byte) // …

Java基础-----Date类及其相关类(一)

文章目录 1. Date类1.1 简介1.2 构造方法1.3 主要方法 2. DateFormat 类2.1 简介2.2 实例化方式一&#xff1a;通过静态方法的调用2.2 实例化方式二&#xff1a;通过创建子类对象 3. Calendar类4. GregorianCalendar 1. Date类 1.1 简介 java.util.Date:表示指定的时间信息&a…

vivado实现分析与收敛技巧7-布局规划

关于布局规划 布局规划有助于设计满足时序要求。当设计难以始终如一满足时序要求或者从未满足时序要求时 &#xff0c; AMD 建议您执行布局规划。如果您与设计团队协作并且协作过程中一致性至关重要&#xff0c; 那么布局规划同样可以发挥作用。布局规划可通过减少平均布线延…

Redis-安装、配置和修改配置文件、以及在Ubuntu和CentOS上设置Redis服务的开机启动和防火墙设置,以及客户端连接。

目录 1. Redis简介 2. 离线安装 2.1 准备工作 2.2 解压、安装 2.3 修改配置文件 2.4 redis服务与关闭 2.5 redis服务的开机启动 2.5.1 Ubuntu上的配置 2.5.2 centos上的配置 3. 在线安装 4. 设置防火墙 5. 客户端连接 1. Redis简介 Redis 是完全开源免费的&#x…

鼠标点击效果.html(网上收集6)

<!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><title>鼠标点击</title> </head><body> <script>(function () {var a_idx 0;window.onclick function (event) {var a new Array(…

【Python从入门到进阶】43.验证码识别工具结合requests的使用

接上篇《42、使用requests的Cookie登录古诗文网站》 上一篇我们介绍了如何利用requests的Cookie登录古诗文网。本篇我们来学习如何使用验证码识别工具进行登录验证的自动识别。 一、图片验证码识别过程及手段 上一篇我们通过requests的session方法&#xff0c;带着原网页登录…

人工智能 - 人脸识别:发展历史、技术全解与实战

目录 一、人脸识别技术的发展历程早期探索&#xff1a;20世纪60至80年代技术价值点&#xff1a; 自动化与算法化&#xff1a;20世纪90年代技术价值点&#xff1a; 深度学习的革命&#xff1a;21世纪初至今技术价值点&#xff1a; 二、几何特征方法详解与实战几何特征方法的原理…

python安装与配置:在centos上使用shell脚本一键安装

介绍 Python是一种功能强大且广泛使用的编程语言&#xff0c;但在某些情况下&#xff0c;您可能需要安装和配置特定版本的Python。本教程将向您展示如何使用一个Shell脚本自动完成这个过程&#xff0c;以便您可以快速开始使用Python 3。 使用shell自动化安装教程 1. 复制脚本…

51单片机项目(19)——基于51单片机的传送带产品计数器

1.功能描述 应用背景: 某生产线的传送带上不断地有产品单向传送&#xff0c;传送时会通过光电传感器产生方波信号&#xff0c;将该信号(可以采用方波发生器来模拟该信号)直接传送给51单片机&#xff0c;利用计数器0计量产品(方波信号)的个数&#xff0c;利用.定时器1产…

Python海绵宝宝

目录 系列文章 写在前面 海绵宝宝 写在后面 系列文章 序号文章目录直达链接表白系列1浪漫520表白代码https://want595.blog.csdn.net/article/details/1306668812满屏表白代码https://want595.blog.csdn.net/article/details/1297945183跳动的爱心https://want595.blog.cs…