- 🤪个人主页:i笨笨i
- 🐽版权:本文由【i笨笨i】原创,需要转载联系博主
- 🎉欢迎关注、点赞、收藏(一键三连)和订阅专栏哦!
- 一个系列哟
- 初识SpringMVC【第一章】
三、请求与响应
3.1、请求映射路径
//BookController类
@Controller
public class BookController {
@RequestMapping("/save")
@ResponseBody
public String save(){
System.out.println("book save ...");
return "{'module':'book save'}";
}
}
//UserController类
@Controller
public class UserController {
@RequestMapping("/save")
@ResponseBody
public String save(){
System.out.println("user save ...");
return "{'module':'user save'}";
}
@RequestMapping("/delete")
@ResponseBody
public String delete(){
System.out.println("user delete ...");
return "{'module':'user delete'}";
}
}
我们可以发现BookController类和UserController类都有
@RequestMapping("/save")
的 /save路径,即路径重复。❓团队多人开发,每个人设置不同的请求路径,冲突问题如何解决?
解决方法:设置模块名作为请求路径前缀
//BookController类
@Controller
@RequestMapping("/book")
public class BookController {
@RequestMapping("/save")
@ResponseBody
public String save(){
System.out.println("book save ...");
return "{'module':'book save'}";
}
}
//UserController类
@Controller
@RequestMapping("/user")
public class UserController {
@RequestMapping("/save")
@ResponseBody
public String save(){
System.out.println("user save ...");
return "{'module':'user save'}";
}
@RequestMapping("/delete")
@ResponseBody
public String delete(){
System.out.println("user delete ...");
return "{'module':'user delete'}";
}
//statement....
}
3.1.1、@RequestMapping注解
名称:
@RequestMapping
类型:方法注解,类注解
位置:SpringMVC控制器 方法/类 定义上方
作用:设置当前控制器方法请求访问路径,如果设置在类上统一设置当前控制器方法请求访问路径前缀
属性:value(默认):请求访问路径或访问路径前缀
- 范例
@Controller
@RequestMapping("/book")
public class BookController {
@RequestMapping("/save")
@ResponseBody
public String save(){
System.out.println("book save ...");
return "{'module':'book save'}";
}
}
3.1.2、请求方式
3.1.2.1、Get请求
- 普通参数:URL地址传参,地址参数名与形参变量名相同,定义形参即可介绍参数。
@Controller
public class UserController {
@RequestMapping("/commonParam")
@ResponseBody
public String commonParam(String name,int age){
System.out.println("普通参数传递 name ==> " + name+":"+age);
return "{'module':'common param'}";
}
}
3.1.2.2、Post请求
- 普通参数:form表单post请求传参,表单参数名与形参变量名相同,定义形参即可接收参数
@Controller
public class UserController {
@RequestMapping("/commonParam")
@ResponseBody
public String commonParam(String name,int age){
System.out.println("普通参数传递 name ==> " + name+":"+age);
return "{'module':'common param'}";
}
}
3.1.2.3、请求中文乱码处理
❓GET方式解决中文乱码问题
直接设置Tomcat目录下conf/server.xml找到标签,加入URIEncoding=“UTF-8”。
<Connector port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443"
URIEncoding="UTF-8"/>
❓POST方式解决中文乱码问题
- 为web容器添加过滤器并指定字符集,Spring-web包中提供了专用的字符过滤器
public class ServletContainersInitConfig extends AbstractAnnotationConfigDispatcherServletInitializer {
//其他方法省略
//乱码处理(配字符编码过滤器)
@Override
protected Filter[] getServletFilters() {
CharacterEncodingFilter filter = new CharacterEncodingFilter();
filter.setEncoding("UTF-8");
return new Filter[]{filter};
}
}
- 配置web.xml文件进行设置
<!-- 配置编码过滤器CharacterEncodingFilter,解决中文乱码问题 -->
<filter>
<filter-name>characterEncodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<!-- 设置CharacterEncodingFilter类中 encoding属性-->
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
<!--设置CharacterEncodingFilter的forceRequestEncoding和forceResponseEncoding属性(是boolean类型),
setForceEncoding方法可以同时设置两个属性。
-->
<init-param>
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<!-- 拦截哪些请求进行过滤 -->
<filter-mapping>
<filter-name>characterEncodingFilter</filter-name>
<!-- 拦截规则
<servlet-name>具体指定哪个servlet(已配置的servlet)
<url-pattern>根据URL请求进行匹配
-->
<servlet-name>springmvc</servlet-name>
</filter-mapping>
3.1.3、静态资源的访问
当页面中包含静态资源的时候我们能够正确的获取到吗?
3.1.3.1、存在问题
❓项目不能访问静态资源原因:配置
DisapatcherServlet
时<url-pattern>/</url-pattern>
或servlet容器启动的配置类内设置拦截路径 /
,DispatcherServlet 会将向静态资源的获取请求,例如.css、.js、.jpg、.png等资源的获取请求,当作是一个普通的 Controller 请求。中央调度器会调用处理器映射器为其查找相应的处理器。当然也是找不到的,所以在这种情况下,所有的静态资源获取请求也均会报 404 错误。解决方式:
- 使用<mvc:default-servlet-handler />并声明注解驱动
- 使用<mvc:resources />并声明注解驱动(推荐)
3.1.3.2、基于SpringMVC的XML配置文件
- 使用<mvc:default-servlet-handler />并声明注解驱动
- 使用<mvc:resources />并声明注解驱动(推荐)
注意事项:
mvc的命名空间的开启,xmlns:mvc的开启以及xsi:schemaLocation添加的内容。
<?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/context
https://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/mvc
https://www.springframework.org/schema/mvc/spring-mvc.xsd">
<context:component-scan base-package="com.item"/>
<!-- 配置访问静态资源 -->
<mvc:annotation-driven/>
<!--
方式二:
将映射的地址直接指向静态资源文件夹,SpringMVC将不会将此映射作为handler。
mapping="/images/**" 表示需要映射的URL地址
/images/**表示将images包下的所以路径所以资源映射到location
location="/images/" 表示映射到哪个位置,
/images/表示映射到images包下
-->
<mvc:resources mapping="/images/**" location="/images/"/>
<!--
方式一:
当SpringMVC 没有映射到某一个请求的时候,就会默认servlet处理
<mvc:default-servlet-handler/>
-->
</beans>
3.1.3.3、基于SpringMVC的纯注解驱动【拦截器】
静态资源在web目录下images包下的01.png文件
- 配置WebMvcConfigurationSupport类的实现类。(SpringMvcSupport)
在SpringMVC的配置类中加入
@EnableWebMvc
相当于XML方式中的<mvc:annotation-driven />,@ComponentScan
注解扫描此类使其加载,添加拦截器使用addResourceHandlers方法将=="/images/**"请求路径映射到/images/==目录下。
@Configuration
public class SpringMvcSupport extends WebMvcConfigurationSupport {
@Override
protected void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/images/**").addResourceLocations("/images/");
}
}
3.2、请求参数
- 参数种类
- 普通参数
- POJO类型参数
- 嵌套POJO类型参数
- 数组类型参数
- 集合类型参数
3.2.1、普通参数
URL地址传参,地址参数名与形参变量名相同,定义形参即可接收参数
//普通参数:请求参数名和形参不同
@RequestMapping("/commonParam")
@ResponseBody
public String commonParamDifferentName(String name, int age){
System.out.println("名字:"+userName+",年龄:"+age);
return "{'module':'common param different name'}";
}
URL地址传参,请求参数名与形参变量名不同,使用
@RequestParam
注解绑定关系
//普通参数:请求参数名和形参不同
@RequestMapping("/commonParamDifferentName")
@ResponseBody
public String commonParamDifferentName(
@RequestParam("name") String userName, int age){
System.out.println("名字:"+userName+",年龄:"+age);
return "{'module':'common param different name'}";
}
3.2.1.1、从GET请求路径上获取参数
在形参前使用
@PathVariable
注解,在@RequestMapping
注解映射的路径上有占位符并且有名称,在@PathVariable
注解里填写从路径上读取数据的名称,并且赋值给被注解的内容。
@RequestMapping("/user/{id}")
@ResponseBody
public String path01(@PathVariable("id") Integer id){
System.out.println(id);
return "{'module':'path'}";
}
3.2.1.2、@RequestParam注解
名称:
@RequestParam
类型:形参注解
位置:SpringMVC控制器方法形参定义前面
作用:绑定请求参数与处理器方法形参间的关系
参数:
- required:是否为必传参数
- defaultValue:参数默认值(重命名)
- 范例
//普通参数:请求参数名和形参不同
@RequestMapping("/commonParamDifferentName")
@ResponseBody
public String commonParamDifferentName(
@RequestParam("name") String userName, int age){
System.out.println("名字:"+userName+",年龄:"+age);
return "{'module':'common param different name'}";
}
3.2.2、POJO类型参数
POJO参数:请求参数名与形参对象属性名相同,定义POJO类型形参即可接收
- 请求参数与POJO类的属性名相同,则会自动封装成User对象
//POJO参数
@RequestMapping("/pojoParam")
@ResponseBody
public String pojoParam(User user) {
System.out.println("pojo参数:"+user);
return "{'module':'pojo param'}";
}
3.2.3、嵌套POJO类型参数
- 嵌套POJO参数:POJO对象中包含POJO对象
public class User {
private String name;
private int age;
private Address address;//引用类型
}
public class Address {
private String province;
private String city;
}
嵌套POJO参数:请求参数名与形参对象属性名相同,按照对象层次结构关系即可接收嵌套POJO属性参数。
//嵌套POJO
@RequestMapping("/pojoContainPojoParam")
@ResponseBody
public String pojoContainPojoParam(User user) {
System.out.println("嵌套pojo:"+user);
return "{'module':'pojo contain pojo param'}";
}
3.2.4、数组类型参数
请求参数名与形参对象属性名相同且请求参数多个,定义数组类型形参即可接收参数。相同的key则会向同一个数组里放。
//数组参数
@RequestMapping("/arrayParam")
@ResponseBody
public String arrayParam(String[] likes) {
System.out.println("数组参数:"+ Arrays.toString(likes));
return "{'module':'array param'}";
}
3.2.5、集合类型参数
集合保存普通参数:请求参数名与形参集合对象名相同且请求参数为多个,
@RequestParam
绑定参数关系。必须再集合参数前加上@RequestParam
注解,不然框架会认为likes是POJO对象,向其中注入属性而不是直接放入。
//集合参数
@RequestMapping("/listParam")
@ResponseBody
public String listParam(@RequestParam List<String> likes){
System.out.println("集合参数:"+likes);
return "{'module':'list param'}";
}
3.3、日期类型参数传递
-
日期类型数据基于系统不同格式也不尽相同
- 2088-08-18
- 2088/08/18(Date类的标准格式)
- 08/18/2088
-
接收形参时,根据不同的日期格式设置不同的接收方法
@RequestMapping("/dataParam")
@ResponseBody
public String dataParam(Date date,
@DateTimeFormat(pattern = "yyyy-MM-dd") Date date1,
@DateTimeFormat(pattern = "yyyy/MM/dd HH:mm:ss") Date date2) {
System.out.println("dataParam:"+date);
System.out.println("dataParam(yyyy-MM-dd):"+date1);
System.out.println("dataParam(yyyy/MM-dd HH:mm:ss):"+date2);
return "{'module':'data param'}";
}
3.3.1、@DateTimeFormat注解
名称:
@DateTimeFormat
类型:形参注解
位置:SpringMVC控制器方法形参前面
作用:设定日期时间型数据格式
属性:pattern:日期时间格式字符串
- 范例
@RequestMapping("/dataParam")
@ResponseBody
public String dataParam(Date date,
@DateTimeFormat(pattern = "yyyy-MM-dd") Date date1,
@DateTimeFormat(pattern = "yyyy/MM/dd HH:mm:ss") Date date2) {
System.out.println("dataParam:"+date);
System.out.println("dataParam(yyyy-MM-dd):"+date1);
System.out.println("dataParam(yyyy/MM-dd HH:mm:ss):"+date2);
return "{'module':'data param'}";
}
3.3.2、类型转换器(Converter)
- Converter接口
package org.springframework.core.convert.converter;
import org.springframework.lang.Nullable;
@FunctionalInterface
public interface Converter<S, T> {
@Nullable
T convert(S var1);
}
请求参数年龄数据(String->String)
日期格式转换(String->Date)
有些转换功能不是默认开启,需要加上
@EnableWebMvc
注解。(根据类型匹配对应的类型转换器)
3.4、响应json数据
- 传递json数据
- json数组
- json对象(POJO)
- json数组(POJO)
1️⃣添加json数据转换相关坐标
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.0</version>
</dependency>
2️⃣设置发送json数据(请求body中添加json数据)
选择Body,点击raw,再选JSON即可。
3️⃣开启自动转换json数据支持
@Configuration
@ComponentScan("com.item.controller")
@EnableWebMvc
public class SpringMvcConfig {
}
注意事项:
@EnableWebMvc
注解功能强大,盖注解整合了多个功能,此处仅使用其中一部分功能,即json数据进行自动转换。
4️⃣设置接收json数据
@RequestMapping("/listParamForJson")
@ResponseBody
public String listParamForJson(@RequestBody List<String> likes) {
System.out.println("集合参数:json格式"+likes);
return "{'module':'list common for json param'}";
}
以下三种方式发送数据:
- json数组
@RequestMapping("/listParamForJson")
@ResponseBody
public String listParamForJson(@RequestBody List<String> likes) {
System.out.println("集合参数:json格式"+likes);
return "{'module':'list common for json param'}";
}
- POJO参数:json数据与形参对象属性名相同,定义POJO类型形参即可接收参数
@RequestMapping("/pojoParamForJson")
@ResponseBody
public String pojoParamForJson(@RequestBody User user) {
System.out.println("pojoParamForJson:"+user);
return "{'module':'pojo for json param'}";
}
- POJO集合参数:json数组数据与集合泛型属性名相同,定义List类型形参即可接收参数
@RequestMapping("/listPojoParamForJson")
@ResponseBody
public String listPojoParamForJson(@RequestBody List<User> list){
System.out.println("listPojoParamForJson:"+list);
return "{'module':'lis pojo for json param'}";
}
3.4.1、@EnableWebMvc注解
名称:
@EnableWebMvc
类型:配置类注解
位置:SpringMVC配置类定义上方
作用:开启SpringMVC多项辅助功能
- 范例
@Configuration
@ComponentScan("com.item.controller")
@EnableWebMvc
public class SpringMvcConfig {
}
3.4.2、@RequestBody注解
名称:
@EnableWebMvc
类型:形参注解
位置:SpringMVC控制器方法形参定义前面
作用:将请求中请求体所包含的数据传递给请求参数,此注解一个处理器方法只能使用一次。
@RequestMapping("/listPojoParamForJson")
@ResponseBody
public String listPojoParamForJson(@RequestBody List<User> list){
System.out.println("listPojoParamForJson:"+list);
return "{'module':'lis pojo for json param'}";
}
3.4.3、@RequestBody与@RequestParam区别
-
区别
@RequestBody
用于接收json数据【application/json】@RequestParam
用于接收URL地址传参,表单传参【application/x-www-form-urlencoded】
-
应用
-
响应页面
-
响应数据
- 文本数据
- JSON数据
3.5.1、响应页面
- 页面
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<h2>Hello Spring MVC!</h2>
</body>
</html>
- 代码(Controller代码)
@RequestMapping("/toJumpPage")
public String toJumpPage(){
System.out.println("跳转页面");
return "page.jsp";
}
方法默认返回字符串,这个字符串代表需要访问的页面。
3.5.2、响应文本数据
@RequestMapping("/toText")
@ResponseBody
public String toText(){
System.out.println("返回纯文本数据");
return "response text";
}
此处要加上
@ResponseBody
注解,否则认为返回字符串是页面的名称。
3.5.3、响应json数据(对象转json)
@RequestMapping("/toJsonPOJO")
@ResponseBody
public User toJsonPOJO(){
//jackson-databind坐标帮忙转成json
System.out.println("返回json对象数据");
User user = new User();
user.setName("itcast");
user.setAge(15);
return user;
}
jackson-databind坐标帮忙转成json。此处要加上
@ResponseBody
注解,否则认为返回字符串是页面的名称。
3.5.4、响应json数据(对象集合转json数组)
@RequestMapping("/toJsonList")
@ResponseBody
public List<User> toJsonList(){
System.out.println("返回json集合数据");
User user1 = new User();
user1.setName("哈哈");
user1.setAge(15);
User user2 = new User();
user2.setName("啊啊");
user2.setAge(20);
List<User> userList = new ArrayList<>();
userList.add(user1);
userList.add(user2);
return userList;
}
此处要加上
@ResponseBody
注解,否则认为返回字符串是页面的名称。
3.5.5、@ResponseBody注解
名称:
@ResponseBody
类型:方法注解
位置:SpringMVC控制器方法定义上方
作用:
- 设置当前控制器方法响应内容为当前返回值,无需解析
- 设置当前控制器返回值作为响应体(此处是这个)
- 范例
@RequestMapping("/save")
@ResponseBody
public String save(){
System.out.println("返回纯文本数据");
return "{'info':'springmvc'}";
}
3.5.6、类型转换器(HttpMessageConverter)
HttpMessageConverter
此接口的子类实现了json转换为HTTP消息。框中的是具体实现类。