【SSM详细教程】-13-SpringMVC详解

 精品专题:

01.《C语言从不挂科到高绩点》课程详细笔记

https://blog.csdn.net/yueyehuguang/category_12753294.html?spm=1001.2014.3001.5482

02. 《SpringBoot详细教程》课程详细笔记

https://blog.csdn.net/yueyehuguang/category_12789841.html?spm=1001.2014.3001.5482

03.《SpringBoot电脑商城项目》课程详细笔记

https://blog.csdn.net/yueyehuguang/category_12752883.html?spm=1001.2014.3001.5482

04.《VUE3.0 核心教程》课程详细笔记 

https://blog.csdn.net/yueyehuguang/category_12769996.html?spm=1001.2014.3001.5482

05. 《SSM详细教程》课程详细笔记 

https://blog.csdn.net/yueyehuguang/category_12806942.html?spm=1001.2014.3001.5482

================================

||     持续分享系列教程,关注一下不迷路 ||

||                视频教程:墨轩大楼               ||

================================

4. SpringMvc详解

4.1. 请求路径映射

》》 当两个控制器中不同方法绑定了相同的请求路径时,会出现什么状况?

package com.moxuan.study.controller;import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;@Controller
public class UserController {@RequestMapping("/save")@ResponseBodypublic String saveUser(){System.out.println("user save....");return "{'msg':'攀哥保存了一个大宝贝儿'}";}
}===============================================================================
package com.moxuan.study.controller;import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;@Controller
public class AddressController {@RequestMapping("/save")@ResponseBodypublic String saveAddress(){System.out.println("Address save....");return "{'msg':'女朋友给攀哥寄了一个大宝贝儿'}";}}

运行起来之后,会出现如下异常:

从异常信息提示可以分析出原因:

UserController有一个saveUser方法,绑定了"/save"。那么它的访问路径为http://localhost/save

AddressController有一个saveAddress方法,也绑定了"/save".访问路径为http://localhost/save

当访问http://localhost/saved的时候,到底是访问UserController还是 AddressController?

》》 开发中潜在的问题

团队多人开发,每人设置不同的请求路径,冲突问题该如何解决?

解决思路:为不同模块设置模块名作为请求路径前置

  • 对于Address模块的save,将其访问路径设置http://localhost/address/save
  • 对于User模块的save,将其访问路径设置http://localhost/user/save
  • 这样在同一个模块中出现命名冲突的情况就比较少了。

修改方法如下:

在控制器上面通过@RequestMapping("命名空间")来设置映射路径,具体代码如下图所示:

package com.moxuan.study.controller;import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;@Controller
@RequestMapping("user")
public class UserController {@RequestMapping("/save")@ResponseBodypublic String saveUser(){System.out.println("user save....");return "{'msg':'攀哥保存了一个大宝贝儿'}";}}====================================================================================
package com.moxuan.study.controller;import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;@Controller
@RequestMapping("address")
public class AddressController {@RequestMapping("/save")@ResponseBodypublic String saveAddress(){System.out.println("Address save....");return "{'msg':'女朋友给攀哥寄了一个大宝贝儿'}";}}

》》 然后分别用postman测试,结果如下:

发送:http://localhost:8080/user/save

发送:http://localhost:8080/address/save

虽然有乱码,但是可以看到,此时两个请求地址都可以正常访问。这里的乱码问题实际上解决起来比较简单,只需要在请求后面添加 produces = "text/html;charset=UTF-8" 即可,具体代码如下:

@RequestMapping(value = "/save",produces = "text/html;charset=UTF-8")
@ResponseBody
public String saveUser(){System.out.println("user save....");return "{'msg':'攀哥保存了一个大宝贝儿'}";
}

再次发送请求时,即可看到正确效果:

》》 @Controller 用法

名称

@Controller

类型

类注解

位置

SpringMVC控制器类定义上方

作用

设定SpringMVC的核心控制器bean

》》@RequestMapping用法

名称

@RequestMapping

类型

类注解或方法注解

位置

SpringMVC控制器类或方法定义上方

作用

设置当前控制器方法请求访问路径

相关属性

value(默认),请求访问路径

》》 @ResponseBody用法

名称

@ResponseBody

类型

类注解或方法注解

位置

SpringMVC控制器类或方法定义上方

作用

设置当前控制器方法响应内容为当前返回值,无需解析

4.2. 参数传递

4.2.1. GET 请求传递一个参数

》》 发送请求与参数,格式如下:

http://localhost:8080/user/sayHello?name='攀哥'

》》编写控制器

@RequestMapping(value="/sayHello",produces = "text/html;charset=UTF-8")
@ResponseBody
public String sayHello(String name){System.out.println(name);return "{'msg': '"+name+"你好呀'}";
}

》》 运行效果

4.2.2. GET请求传递多个参数

》》 请求地址

http://localhost:8080/user/sayHello?name=攀哥&age=18

》》 编写控制器

@RequestMapping(value="/sayHello",produces = "text/html;charset=UTF-8")
@ResponseBody
public String sayHello(String name,int age){System.out.println("我叫"+name+",今年"+age+"岁");return "{'msg': '"+name+"你好呀,你好年轻呀,才"+age+"岁'}";
}

》》测试结果:

由此可以看出,当我们需要传递参数的时候,只需要在控制器的方法中添加与需要传递的参数同名的参数即可。

4.2.3. POST请求传递参数

》》 发送请求的方式,控制器方法不变

4.2.4. POST请求乱码问题

上面的案例中,纵使我们按照解决get请求乱码问题一样添加了produces,也是没有效果,如果是Post请求的话,我们需要在web.xml中配置过滤器,具体配置方法如下:

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

》》重启服务,运行效果如下:

4.3. 请求参数传递

在前面的案例中我们可以使用GET和POST来发送请求和数据,所携带的数据都是比较简单的,接下来,我们在这个基础上研究一下复杂的参数传递。

4.3.1. 普通参数

前面的案例中我们传递的就是普通参数,前面的案例中我们传递时,请求参数的名字和控制器方法中的参数名字相同,可以直接传递,但是如果不相同会出现什么样状况?

@RequestMapping(value="/showCommParam", produces = "text/html;charset=utf-8")
@ResponseBody
public String showParam(String friendName,String sex,Integer age){System.out.println("我是攀哥的"+sex+"朋友,我叫"+name+"今年"+age+"岁");return "我是攀哥的"+sex+"朋友,我叫"+name+"今年"+age+"岁";
}

》》发送请求:

》》 请求结果:

》》 解决方案:

可以在控制器方法参数名之前使用@RequestParam 指定这个参数是用来接收哪个请求参数的,比如:

@RequestMapping(value="/showCommParam", produces = "text/html;charset=utf-8")
@ResponseBody
public String showParam(@RequestParam("name") String friendName, String sex, Integer age){System.out.println("我是攀哥的"+sex+"朋友,我叫"+friendName+"今年"+age+"岁");return "我是攀哥的"+sex+"朋友,我叫"+friendName+"今年"+age+"岁";
}

》》运行结果:

注意:写上@RequestParam注解框架就不需要自己去解析注入,能提升框架处理性能。

4.3.2. 实体类对象Pojo数据

普通参数类型一般处理的是参数个数比较少的请求,如果参数比较多,后台接收参数的时候就比较复杂,这个时候我们可以考虑使用Pojo类型参数。

注意:Pojo参数,请求参数名与对象的属性名相同,这样请求参数的数据会自动注入道对象属性中,接下来我们看看案例:

》》 POJO实体类Friend

@Data  // 自动添加getter和setter方法,toString方法
@NoArgsConstructor  // 自动添加无参构造器
@AllArgsConstructor // 自动添加全参构造器
public class Friend {private String name;private String sex;private int age;
}

》》 后台接收参数:

@RequestMapping(value="/showPoJoParam", produces = "text/html;charset=utf-8")
@ResponseBody
public String showPoJoParam(Friend friend){System.out.println(friend);return "我是攀哥的"+friend.getSex()+"朋友,我叫"+friend.getName()+"今年"+friend.getAge()+"岁";
}

》》发送请求:

4.3.3. 嵌套POJO类型参数

实际项目中,往往PoJo对象中会嵌套其他PoJo对象,比如:朋友会有地址,地址会有省份,城市等等,具体如下:

》》 地址POJO类Address

@Data
@AllArgsConstructor
@NoArgsConstructor
public class Address {private String province;private String city;
}

》》朋友POJO类Friend

@Data  // 自动添加getter和setter方法,toString方法
@NoArgsConstructor  // 自动添加无参构造器
@AllArgsConstructor // 自动添加全参构造器
public class Friend {private String name;private String sex;private int age;private Address address;
}

注意:Friend类中我们添加了地址Address对象

》》 控制器接收请求参数

@RequestMapping(value="/showInnerPoJo", produces = "text/html;charset=utf-8")
@ResponseBody
public String showInnerPoJo(Friend friend){System.out.println(friend);return "我是攀哥的"+friend.getSex()+"朋友," +"我叫"+friend.getName()+"今年"+friend.getAge()+"岁," +"我住在"+friend.getAddress().getProvince()+"省," +friend.getAddress().getCity()+"市";
}

》》 发送请求:

4.3.4. 数组类型参数

举个简单例子,如果前端需要做用户批量删除或者获取用户的爱好,这些情况下选择的大多是多条数据,那如果遇到这种情况应该如何发送数据和接受数据呢?

注意: 数组参数,请求参数名与控制器方法参数名相同且请求参数为多个,可以定义数组来接收请求参数。

@RequestMapping(value="/showMyLove", produces = "text/html;charset=utf-8")
@ResponseBody
public String showMyLove(String[] loves){return "给大家介绍一下我的老婆们:"+ Arrays.toString(loves);}

》》发送请求:

由结果可以看出,同名请求参数可以直接映射到对应的控制器方法的数组参数中。

4.3.5. 集合类型参数

既然数组可以接收多个参数,那么集合是否以可以呢?我们修改一下代码看看:

@RequestMapping(value="/showMyLoveList", produces = "text/html;charset=utf-8")
@ResponseBody
public String showMyLoveList(List<String> loves){return "给大家介绍一下我的老婆们:"+ loves;}

》》 发送请求

结果会发现报错了,报错的原因是,SpringMVC将List看作是一个PoJo对象来处理,将其创建一个对象并准备把前端的数据封装到对象中,但是List是一个接口无法创建对象,所以会报错:

解决办法就是在集合前面添加@RequestParam来解决。

@RequestMapping(value="/showMyLoveList", produces = "text/html;charset=utf-8")
@ResponseBody
public String showMyLoveList(@RequestParam List<String> loves){return "给大家介绍一下我的老婆们:"+ loves;
}

有的同学可能会想,既然List不能直接用,能不能使用ArrayList呢?这个卖点关子,童靴们自己尝试一下吧。关于RequestParam具体使用方法如下:

名称

@RequestParam

类型

形参注解

位置

SpringMVC控制器方法形参定义前面

作用

绑定请求参数与处理器方法形参间的关系

相关参数

required:是否为必传参数 defaultValue:参数默认值

4.4. JSON数据传输参数

现在流行前后端分离开发模式,而往往在前后端传输数据的时候,会使用JSON。所以接下来我们研究一下当前端发送的是JSON数据时,后端该如何接收?

对于JSON数据类型,我们常见格式有以下几种:

》》JSON 普通数组

["value1","value2","value3",......]

》》JSON 对象

{"key1":"value1","key2":"value2","key3":"value3",.......}

》》JSON 对象数组

[{key1:value1,...},{key2:value2,...}]

SpringMVC 默认的是以jackson来处理JSON的转换,所以我们需要在pom.xml中引入jackson依赖,依赖如下:

<dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-annotations</artifactId><version>2.10.2</version>
</dependency>
<dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-databind</artifactId><version>2.10.2</version>
</dependency>
<dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-core</artifactId><version>2.10.2</version>
</dependency>

在SpringMVC中,解析JSON请求数据需要使用到HttpMessageConverter。

SpringMVC默认提供了多个HttpMessageConverter实现,其中包括MappingJackson2HttpMessageConverter,它可以将JSON数据转换为Java对象。

要使用MappingJackson2HttpMessageConverter,需要在SpringMVC配置文件中进行配置。可以通过以下方式配置:

<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"><property name="messageConverters"><list><bean class="org.springframework.http.converter.StringHttpMessageConverter"/><bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter"/></list></property>
</bean>
4.4.1. 发送普通JSON数组

》》 发送请求

注意发送请求之前一定要按照如下方式在Headers中设置Content-Type,将其设置为application/json

如下图所示依次选择Body,raw, JSON 编写JSON格式的字符串

》》 代码

@RequestMapping(value="/showJsonParam", produces = "text/html;charset=utf-8")
@ResponseBody
public String showJsonParam(@RequestBody String loves){// 解析JSON格式的字符串List<String > mys = (List<String>) JSON.parse(loves);for (String myLove:mys){System.out.println(myLove);}System.out.println(mys);return loves.toString();
}

》》运行结果:

4.4.2. 传输JSON对象数据 

》》 发送如下请求

》》 控制器代码如下:

@RequestMapping(value="/showJsonFriend", produces = "text/html;charset=utf-8")
@ResponseBody
public String showJsonFriend(@RequestBody Friend friend){System.out.println(friend);return friend.toString();
}

》》运行结果:

从效果可以看出,当json格式中的数据key和对象中的属性同名时,json数据会自动注入到对象的属性中去。

4.4.3. JSON对象数组

》》发送请求如下图所示:

》》控制器代码如下:

@RequestMapping(value="/showJsonManyFriend", produces = "text/html;charset=utf-8")
@ResponseBody
public String showJsonManyFriend(@RequestBody List<Friend> friends){for (Friend friend:friends){System.out.println(friend);}return friends.toString();
}

》》运行结果:

4.4.4. @RequestBody与@RequestParam区别
  • 区别
    • @RequestParam用于接收url地址传参,表单传参【application/x-www-form-urlencoded】
    • @RequestBody用于接收json数据【application/json】
  • 应用
    • 后期开发中,发送json格式数据为主,@RequestBody应用较广
    • 如果发送非json格式数据,选用@RequestParam接收请求参数

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

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

相关文章

设计模式4-工厂模式策略模式

目录 一 工厂模式 1.1 思想 1.2 案例 1.2.1 接口 1.2.2 实现类 1.2.3 工厂类 1.2.4 调用 二 策略模式 2.1 思想 2.2 案例 2.2.1 接口 2.2.2 实现类 2.2.3 策略类 2.2.4 调用 三 工厂模式策略模式 3.1 思想 3.2 案例 3.2.1 接口 3.2.2 实现类 3.2.3 定义F…

常见问题 | 数字签名如何保障电子商务交易安全?

如何解决电商交易中数据泄露、交易欺诈等问题&#xff1f; 数字签名是一种类似于电子“指纹”的安全技术&#xff0c;它在电子商务中扮演着至关重要的角色。随着电子商务的迅猛发展&#xff0c;网上交易的数量不断增加&#xff0c;确保交易的安全性和完整性成为了亟待解决的问题…

不适合的学习方法

文章目录 不适合的学习方法1. 纯粹死记硬背2. 过度依赖单一资料3. 线性学习4. 被动学习5. 一次性学习6. 忽视实践7. 缺乏目标导向8. 过度依赖技术9. 忽视个人学习风格10. 过于频繁的切换 结论 以下是关于不适合的学习方法的更详细描述&#xff0c;包括额外的内容和相关公式&…

HTML5 + CSS3 + JavaScript 编程语言学习教程

HTML5 CSS3 JavaScript 编程语言学习教程 欢迎来到这篇关于 HTML5、CSS3 和 JavaScript 的详细学习教程&#xff01;无论你是初学者还是有一定基础的开发者&#xff0c;这篇文章都将帮助你深入理解这三种技术的核心概念、语法和应用。 目录 HTML5 1.1 HTML5 简介1.2 HTML5 …

【安全性分析】正式安全分析与非正式安全分析

安全性分析-系列文章目录 第一章 【安全性分析】正式安全分析与非正式安全分析 第二章 【安全性分析】BAN逻辑 (BAN Logic) 文章目录 安全性分析-系列文章目录前言一、正式安全分析1. 理想化模型(如随机预言机模型)2. 标准模型(Standard Model)3. 形式化验证4. 数学证明二…

win11安装安卓apk原生应用,并设置网络代理

一、win11安装安卓apk原生应用&#xff0c;查看https://blog.csdn.net/qq_33704787/article/details/123658419https://blog.csdn.net/qq_33704787/article/details/123658419 主要是安装&#xff1a;Windows Subsystem for Android™ with Amazon Appstore 二、使用ABD工具设…

无人机救援系统基本组成

无人机救援系统基本组成 1. 源由2. 组成2.1 无人机载具2.1.1 多旋翼2.1.2 垂起固定翼2.1.3 智能避障2.1.4 物资投递 2.2 智能吊舱2.2.1 云台2.2.2 高清摄像2.2.3 红外热成像2.2.4 激光测距2.2.5 目标跟踪 2.3 通讯链路2.3.1 超长距离通信2.3.2 长距离通信2.3.3 中等距离通信 2.…

Flink CDC系列之:学习理解核心概念——Transform

Flink CDC系列之&#xff1a;学习理解核心概念——Transform Transform参数元数据字段函数比较函数逻辑函数字符串函数时间函数条件函数 示例添加计算列参考元数据列使用通配符投影所有字段添加过滤规则重新分配主键重新分配分区键指定表创建配置分类映射用户定义函数已知限制 …

每天五分钟深度学习pytorch:基于pytorch搭建普通全连接神经网络

本文重点 本文我们通过pytorch搭建普通的全连接神经网络,这里我们就不介绍什么是全连接神经网络了,如果不知道的可以看我的机器学习专栏,或者深度学习专栏,它们对全连接神经网络都进行了简单的介绍。 代码 import torch from torch import nn class ThreeNet(nn.Module)…

故障诊断 | MTF-TLSSA-DarkNet-GRU-MSA迁移学习故障识别程序(t分布+莱维飞行改进麻雀优化)

故障诊断 | 故障诊断实例代码 目录 故障诊断 | 故障诊断实例代码效果一览基本介绍程序设计参考资料 效果一览 基本介绍 利用了迁移学习和多项技术改进&#xff0c;包括麻雀搜索法、DarkNet19、GRU、多头注意力机制等&#xff0c;以提高故障识别的准确性和效率 模型框架&#x…

【一起python】使用python实现学生管理系统

文章目录 &#x1f4dd;前言&#x1f320;主函数man&#x1f309;菜单menu&#x1f309;添加学生信息&#x1f309;展示目前学生信息&#x1f309;查找学生&#x1f309;删除同学信息&#x1f309;退出程序 &#x1f320;python完整代码&#x1f6a9;总结 &#x1f4dd;前言 &…

前缀和_560. 和为 K 的子数组

560. 和为 K 的子数组 #include <unordered_map> class Solution { public:int subarraySum(vector<int>& nums, int k) {int nnums.size();unordered_map<int,int> hs;int sum0,re0;hs[0]1;for(int i0;i<n;i){sumnums[i];if(hs.count(sum-k)) rehs[s…

(转载)Tools for Learning LLVM TableGen

前提 最近在学习有关llvm的东西&#xff0c;其中TableGen占了一部分&#xff0c;所以想特意学习下TableGen相关的语法。这里找到了LLVM官网的一篇介绍TableGen的博客&#xff0c;学习并使用机器翻译为中文。在文章的最后也添加了一些学习TableGen的资源。 原文地址&#xff1…

Python酷库之旅-第三方库Pandas(182)

目录 一、用法精讲 841、pandas.api.types.is_complex函数 841-1、语法 841-2、参数 841-3、功能 841-4、返回值 841-5、说明 841-6、用法 841-6-1、数据准备 841-6-2、代码示例 841-6-3、结果输出 842、pandas.api.types.is_float函数 842-1、语法 842-2、参数 …

CSS基础学习篇——选择器

学习文档连接&#xff1a;CSS层叠样式表 1.全局选择器&#xff1a;* * {margin: 0;padding: 0;font-size: 18px; }2.类&#xff08;clss&#xff09;选择器&#xff0c;以 . 开头 .container {display: flex;justify-content: space-around;align-items: center;width: 1200…

Marin说PCB之电源的Surface Current Density知多少?

小编我是一位资深的国漫迷&#xff0c;像什么仙逆&#xff0c;斗破&#xff0c;斗罗&#xff0c;完美世界&#xff0c;遮天&#xff0c;凡人修仙传&#xff0c;少年歌行等&#xff0c;为了可以看这些视频小编我不惜花费了攒了很多年的私房钱去开了这个三个平台的会员啊&#xf…

Oracle视频基础1.3.3练习

1.3.3 检查数据库启动情况 ps -ef | grep oracle启动数据库 sqlplus /nolog conn / as sysdba修改 fast_start_mttr_target 参数为初始值-50&#xff0c;缺省 scope 和 sid&#xff0c;查看修改结果 show parameter fast; alter system set parameter 250; show parameter fa…

CSS flex布局- 最后一个元素占满剩余可用高度转载

效果图 技术要点 height父元素必须有一个设定的高度flex-grow: 1 flex 盒子模型内的该元素将会占据父容器中剩余的空间F12检查最后一行的元素&#xff0c;高度就已经改变了&#xff1b;

基于vue框架的的驾校预约管理系统设计d5tq3(程序+源码+数据库+调试部署+开发环境)系统界面在最后面。

系统程序文件列表 项目功能&#xff1a;用户,驾校教练,车辆信息,报名信息,学员信息,考试预约,教学课程,教练评价,考试成绩,练车预约,报修申请,维修信息,课程类型,车辆类型 开题报告内容 基于Vue框架的驾校预约管理系统设计开题报告 一、项目背景与意义 随着驾驶培训行业的快…

shell脚本编写注意细节 ==、=等的区别

文章目录 和的使用主要区别小结 Shell脚本要注意的细节1. 变量引用和空格处理2. [[ ... ]] vs [ ... ]3. 使用-n和-z来检测变量是否为空4. 整数运算和浮点运算5. 避免使用反引号执行命令6. for循环中的命令替换7. 使用trap来清理临时文件8. 避免使用硬编码路径9. 使用-eq、-lt、…