一、请求映射路径
当进行请求路径命名时,对于重名方法怎么解决路径冲突
创建一个Web的Maven项目,在pom.xml中添加相关依赖
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.example</groupId>
<artifactId>SpringMVC_03</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>war</packaging>
<name>SpringMVC_03 Maven Webapp</name>
<!-- FIXME change it to the project's website -->
<url>http://www.example.com</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>16</maven.compiler.source>
<maven.compiler.target>16</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.3.0</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<version>2.1</version>
<configuration>
<port>80</port>
<path>/</path>
</configuration>
</plugin>
</plugins>
</build>
</project>
创建相应配置类
SpringMVCConfig
@Configuration
@ComponentScan("com.controller")
public class SpringMVCConfig {
}
ServletContrainerInitConfig
public class ServletContainersInitConfig extends AbstractAnnotationConfigDispatcherServletInitializer {
@Override
protected Class<?>[] getRootConfigClasses() {
return new Class[0];
}
@Override
protected Class<?>[] getServletConfigClasses() {
return new Class[]{SpringMVCConfig.class};
}
@Override
protected String[] getServletMappings() {
return new String[]{"/"};
}
}
创建两个控制类
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
@Controller
public class BookController {
@RequestMapping("/save")
@ResponseBody
public String save(){
System.out.println("book save ...");
return "{'module':'book save'}";
}
}
删除WEB-INF下的web.xml文件,配置tomcat可见SpringMVC入门
项目结构如下
启动tomcat服务器,后台会如下错误
因为此时UserController有一个save方法,BookController也有一个save方法,访问路径都是http://localhost/save
对于这个问题,我们可以为不同模块设置模块名作为请求路径前置
对于Book模块的save,将其访问路径设置为http://localhost/book/save
对于User模块的save,将其访问路径设置http://localhost/user/save
- 方法一、修改每个方法上的路径配置
UserController
@Controller
public class UserController {
@RequestMapping("/user/save")
@ResponseBody
public String save(){
System.out.println("user save ...");
return "{'module':'user save'}";
}
@RequestMapping("/user/delete")
@ResponseBody
public String delete(){
System.out.println("user delete ...");
return "{'module':'user delete'}";
}
}
BookController
@Controller
public class BookController {
@RequestMapping("/book/save")
@ResponseBody
public String save(){
System.out.println("book save ...");
return "{'module':'book save'}";
}
}
此时便不存在路径重复的问题,但这种方法所有方法前面都要修改,耦合度太高,一般开发时采用下面一种方法
- 方法二、在类上添加@RequestMapping注解
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'}";
}
}
BookController
@Controller
@RequestMapping("/book")
public class BookController {
@RequestMapping("/save")
@ResponseBody
public String save(){
System.out.println("book save ...");
return "{'module':'book save'}";
}
}
在使用此种方法时,前端发送请求的时候,要和两个注解的value值相加匹配才能访问到
二、请求参数
对于请求参数的传递和接收是和请求方式有关系的,比较常见的请求方式有两种,GET请求和POST请求
1.环境准备
创建一个web的Maven项目,在pom.xml中添加相关依赖
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>SpringMVC_05</groupId>
<artifactId>SpringMVC_05</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>war</packaging>
<name>SpringMVC_05 Maven Webapp</name>
<!-- FIXME change it to the project's website -->
<url>http://www.example.com</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>16</maven.compiler.source>
<maven.compiler.target>16</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.3.0</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<version>2.1</version>
<configuration>
<port>80</port>
<path>/</path>
</configuration>
</plugin>
</plugins>
</build>
</project>
创建相应配置类
SpringMVCConfig
@Configuration
@ComponentScan("com.controller")
public class SpringMVCConfig {
}
ServletContainersInitConfig
public class ServletContainersInitConfig extends AbstractAnnotationConfigDispatcherServletInitializer {
@Override
protected Class<?>[] getRootConfigClasses() {
return new Class[0];
}
@Override
protected Class<?>[] getServletConfigClasses() {
return new Class[]{SpringMVCConfig.class};
}
@Override
protected String[] getServletMappings() {
return new String[]{"/"};
}
}
编写UserController
@Controller
public class UserController {
@RequestMapping("/commonParam")
@ResponseBody
public String commonParam() {
return "{'module':'commonParam'}";
}
}
编写模型类
Address
public class Address {
private String province;
private String city;
public String getProvince() {
return province;
}
public void setProvince(String province) {
this.province = province;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
@Override
public String toString() {
return "Address{" +
"province='" + province + '\'' +
", city='" + city + '\'' +
'}';
}
}
User
public class User {
private String name;
private int age;
private Address address;
public Address getAddress() {
return address;
}
public void setAddress(Address address) {
this.address = address;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
", age=" + age +
", province=" + address.getProvince() +
", city=" + address.getCity() +
'}';
}
}
项目结构如下
与上文同样删除web.xml,配置tomcat
2.GET发送参数
在UserController中设置接收参数
@RequestMapping("/commonParam")
@ResponseBody
public String commonParam(@RequestParam("name") String username, int age) {
System.out.println("普通参数传递 name -->" + username);
System.out.println("普通参数传递 age -->" + age);
return "{'module':'commonParam'}";
}
@RequestParam解决前端传输参数名与后端定义的参数名不一致问题,否则需保持前端参数名和后端接收的形参名一致
启动tomcat服务器
在apifox中发送请求与参数
此时控制台输出
name值产生了中文乱码,可通过修改pom.xml来解决GET请求中文乱码的问题
<build>
<plugins>
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<version>2.1</version>
<configuration>
<port>80</port>
<path>/</path>
<!--解决发送get请求时中文乱码的问题-->
<uriEncoding>UTF-8</uriEncoding>
</configuration>
</plugin>
</plugins>
</build>
<uriEncoding>设置访问路径编解码字符集
重启服务器,再次发送相同请求
此时控制台输出
2.POST发送参数
与上文UserController配置相同,启动服务器,在apifox中发送请求与参数
此时控制台输出
此时POST请求依旧产生中文乱码问题,可以通过配置过滤器解决
在ServletContainersInitConfig配置类中添加如下方法
//乱码处理
protected Filter[] getServletFilters(){
CharacterEncodingFilter filter = new CharacterEncodingFilter();
filter.setEncoding("UTF-8");
return new Filter[]{filter};
}
此时重启服务器,发送相同数据
控制台输出如下
3.POJO数据类型参数
在UserController中添加接收POJO类型参数方法
请求参数与形参对象中的属性对应即可完成参数传递
@RequestMapping("/pojoParam")
@ResponseBody
public String pojoParam(User user){
System.out.println("pojo参数传递 user --> " + user.toString());
return "{'module':'pojo param'}";
}
由于User的toString方法为了更直观展现,使用了Address中的get,set方法,所以前端传参如未传address参数,则会报无address的错误
启动服务器,在apifox发送请求与参数
注意请求参数KEY的名称要与POJO中的属性名称一致,否则无法封装
此时控制台输出
4.数组类型参数
在UserController中添加接收数组类型参数方法
@RequestMapping("/arrayParam")
@ResponseBody
public String arrayParam(String[] likes){
System.out.println("数组参数传递 likes --> " + Arrays.toString(likes));
return "{'module':'array param'}";
}
对于数组参数,只需请求参数名与形参对象属性名相同且请求参数为多个,定义数组类型即可接收参数
启动服务器,在apifox中发送请求与参数
此时控制台输出
5.集合类型参数
在UserController中添加接收集合类型参数方法
@RequestMapping("/listParam")
@ResponseBody
public String listParam(@RequestParam List<String> likes){
System.out.println("集合参数传递 likes --> " + likes);
return "{'module':'list param'}";
}
与接收数组类型相同,需保证请求参数名与形参对象属性名相同且请求参数为多个,即可接收数据
注意使用集合类型接收数据时,需使用@RequestParam注解绑定参数关系,如不使用@RequestParam注解,则在传输数据时会报错java.lang.IllegalStateException: No primary or single public constructor found for interface java.util.List - and no default constructor found either,这是因为SpringMVC将List看做是一个POJO对象来处理,将其创建一个对象并准备把前端的数据封装到对象中,但是List是一个接口无法创建对象,所以报错。
同名请求参数用@RequestParam注解映射到对应名称的集合对象中作为数据
启动服务器,在apifox中发送请求与参数
此时控制台输出
6.JSON数据传输参数
对于JSON数据类型,我们常见的有三种
- JSON普通数组 ["value1","value2","values3",...]
- JSON对象 {"key1":"value1","key2":"value2",...}
- JSON对象数组 [{"key1":"value1",...},{"key2":"value2",...}]
以下将展示如何接收上述三种类型JSON数据
对于JSON数据,SpringMVC默认使用的是jackson来处理json的转换,所以需要在pom.xml添加jackson依赖
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.0</version>
</dependency>
同时需在SpringMVC的配置类中开启SpringMVC的注解支持,这里面就包含了将JSON转换成对象的功能
@Configuration
@ComponentScan("com.controller")
//开启json数据类型自动转换
@EnableWebMvc
public class SpringMVCConfig {
}
- JSON普通数组数据
在UserController中添加接收JSON普通数组类型参数方法
@RequestMapping("/listParamForJson")
@ResponseBody
public String listParamForJSon(@RequestBody List<String> likes){
System.out.println("list common(json)参数传递 likes --> " + likes);
return "{'module':'list common for json param'}";
}
使用@RequestBody注解将外部传递的json数组数据映射到形参的集合对象中作为数据
启动服务器,在apifox中发送请求与参数
此时控制台输出
- JSON对象数据
在UserController中添加接收JSON对象类型参数方法
@RequestMapping("/listParamForJsonOb")
@ResponseBody
public String listParamForJSonOb(@RequestBody User user){
System.out.println("list common(json)参数传递 likes --> " + user);
return "{'module':'list common for jsonOb param'}";
}
启动服务器,在apifox中发送请求与参数
此时控制台输出
- JSON对象数组数据
在UserController中添加接收JSON对象数组类型参数方法
@RequestMapping("/listParamForJsonObs")
@ResponseBody
public String listParamForJSonObs(@RequestBody List<User> list){
System.out.println("集合参数传递 likes --> " + list);
return "{'module':'list common for jsonObs param'}";
}
启动服务器,在apifox中发送请求与参数
此时控制台输出
@RequestParam与@RequestBody的区别
- @RequestParam用于接收url地址传参,表单传参【application/x-www-form-urlencoded】
- @RequestBody用于接收json数据【application/json】
7.日期类型参数
对于日期类型,我们有不同的输入方式
- 1949/10/01
- 1949-10-01
- 10/01/1949
- ......
对于这些日期格式,SpringMVC如何实现接收这些日期类型数据
在UserController类中添加方法,将参数设置为日期类型
@RequestMapping("/dateParam")
@ResponseBody
public String dateParam(Date date,
@DateTimeFormat(pattern = "yyyy-MM-dd") Date date1,
@DateTimeFormat(pattern = "MM-dd-yyyy") Date date2,
@DateTimeFormat(pattern = "yyyy/MM/dd HH:mm:ss") Date date3) {
System.out.println("日期参数传递 date " + date);
System.out.println("日期参数传递 date1 " + date1);
System.out.println("日期参数传递 date2 " + date2);
System.out.println("日期参数传递 date3 " + date3);
return "{'module':'date param'}";
}
@DateTimeFormat:设定日期时间型数据格式
启动服务器,在apifox中发送请求与参数
此时控制台输出
三、响应
对于响应,在SpringMVC接收到请求和数据后,将其转发给Service,或直接进行了一些处理,处理完之后,将结果返回给前端,主要包括响应页面与响应数据两部分
1.环境准备
创建一个web的Maven项目,在pom.xml中添加相关依赖
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>SpringMVC_06</groupId>
<artifactId>SpringMVC_06</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>war</packaging>
<name>SpringMVC_06 Maven Webapp</name>
<!-- FIXME change it to the project's website -->
<url>http://www.example.com</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>16</maven.compiler.source>
<maven.compiler.target>16</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.3.0</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.0</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<version>2.1</version>
<configuration>
<port>80</port>
<path>/</path>
<uriEncoding>UTF-8</uriEncoding>
</configuration>
</plugin>
</plugins>
</build>
</project>
创建相应的配置类
SpringMVCConfig
@Configuration
@ComponentScan("com.controller")
@EnableWebMvc
public class SpringMVCConfig {
}
ServletContainersInitConfig
public class ServletContainersInitConfig extends AbstractAnnotationConfigDispatcherServletInitializer {
@Override
protected Class<?>[] getRootConfigClasses() {
return new Class[0];
}
@Override
protected Class<?>[] getServletConfigClasses() {
return new Class[]{SpringMVCConfig.class};
}
@Override
protected String[] getServletMappings() {
return new String[]{"/"};
}
//乱码处理
protected Filter[] getServletFilters(){
CharacterEncodingFilter filter = new CharacterEncodingFilter();
filter.setEncoding("UTF-8");
return new Filter[]{filter};
}
}
编写模型类User
public class User {
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
编写UserController
@Controller
public class Usercontroller {
}
更改index.xml中输出内容
<html>
<body>
<h2>Hello SpringMVC!</h2>
</body>
</html>
与上文同样删除web.xml,配置tomcat
最终结构如下
2.响应页面
在UserController中添加跳转页面方法
@Controller
public class Usercontroller {
@RequestMapping("/toJumpPage")
public String toJumpPage(){
System.out.println("跳转页面");
return "index.jsp";
}
}
此处不能添加@ResponseBody,如果加入了该注入,会直接将page.jsp当字符串返回前端
方法需要返回String
启动服务器,在浏览器中访问http://localhost/toJumpPage
此时控制台输出
3.返回文本数据
在UserController中添加返回文本数据方法
@RequestMapping("/toText")
@ResponseBody
public String toText(){
System.out.println("返回纯文本数据");
return "response text";
}
重启服务器,在浏览器中访问http://localhost/toText
此时控制台输出
4.响应JSON数据
(1)、响应POJO对象
在UserController中添加响应POJO对象方法
@RequestMapping("/toJsonPOJO")
@ResponseBody
public User toJsonPOJO(){
System.out.println("返回json对象数据");
User user = new User();
user.setName("wangerhhh");
user.setAge(21);
return user;
}
重启服务器,在浏览器中访问http://localhost/toJsonPOJO
此时控制台输出
(2)、响应POJO对象集合
在UserController中添加响应POJO对象集合方法
@RequestMapping("/toJsonList")
@ResponseBody
public List<User> toJsonList(){
System.out.println("返回json集合数据");
User user1 = new User();
user1.setName("王大");
user1.setAge(22);
User user2 = new User();
user2.setName("王二");
user2.setAge(21);
List<User> userList = new ArrayList<User>();
userList.add(user1);
userList.add(user2);
return userList;
}
重启服务器,在浏览器中访问http://localhost/toJsonList
此时控制台输出
@ResponseBody:设置当前控制器返回值作为响应体
该注解可以写在类上或者方法上,写在类上就是该类下的所有方法都有@ResponseBody功能
当方法上有@ResponseBody注解后
- 方法的返回值为字符串,会将其作为文本内容直接响应给前端
- 方法的返回值为对象,会将对象转换成JSON响应给前端
对于类型转换,SpringMVC内部是通过Converter接口的实现类完成的