Java開發學習(二十五)—-使用PostMan完成不同類型參數傳遞
請求路徑設置好後,只要確保頁面發送請求地址和後台Controller類中配置的路徑一致,就可以接收到前端的請求,接收到請求後,如何接收頁面傳遞的參數?
關於請求參數的傳遞與接收是和請求方式有關係的,目前比較常見的兩種請求方式為:
-
GET
-
POST
針對於不同的請求前端如何發送,後端如何接收?
1.1 環境準備
-
創建一個Web的Maven項目
-
pom.xml添加Spring依賴
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="//maven.apache.org/POM/4.0.0" xmlns:xsi="//www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="//maven.apache.org/POM/4.0.0 //maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.itheima</groupId> <artifactId>springmvc_03_request_mapping</artifactId> <version>1.0-SNAPSHOT</version> <packaging>war</packaging> <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.2.10.RELEASE</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>
-
創建對應的配置類
public class ServletContainersInitConfig extends AbstractAnnotationConfigDispatcherServletInitializer { protected Class<?>[] getServletConfigClasses() { return new Class[]{SpringMvcConfig.class}; } protected String[] getServletMappings() { return new String[]{"/"}; } protected Class<?>[] getRootConfigClasses() { return new Class[0]; } } @Configuration @ComponentScan("com.itheima.controller") public class SpringMvcConfig { }
-
編寫UserController
@Controller public class UserController { @RequestMapping("/commonParam") @ResponseBody public String commonParam(){ return "{'module':'commonParam'}"; } }
-
編寫模型類,User和Address
public class Address { private String province; private String city; //setter...getter...略 } public class User { private String name; private int age; //setter...getter...略 }
最終創建好的項目結構如下:
1.2 參數傳遞
GET發送單個參數
發送請求與參數:
//localhost/commonParam?name=itcast
另外:對於PostMan如何覺得字小不好看,可以使用ctrl+=
調大,ctrl+-
調小。
接收參數:
@Controller
public class UserController {
@RequestMapping("/commonParam")
@ResponseBody
public String commonParam(String name){
System.out.println("普通參數傳遞 name ==> "+name);
return "{'module':'commonParam'}";
}
}
GET發送多個參數
發送請求與參數:
//localhost/commonParam?name=itcast&age=15
接收參數:
@Controller
public class UserController {
@RequestMapping("/commonParam")
@ResponseBody
public String commonParam(String name,int age){
System.out.println("普通參數傳遞 name ==> "+name);
System.out.println("普通參數傳遞 age ==> "+age);
return "{'module':'commonParam'}";
}
}
GET請求中文亂碼
如果我們傳遞的參數中有中文,你會發現接收到的參數會出現中文亂碼問題。
發送請求://localhost/commonParam?name=張三&age=18
控制台:
出現亂碼的原因相信大家都清楚,Tomcat8.5以後的版本已經處理了中文亂碼的問題,但是IDEA中的Tomcat插件目前只到Tomcat7,所以需要修改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><!--tomcat端口號-->
<path>/</path> <!--虛擬目錄-->
<uriEncoding>UTF-8</uriEncoding><!--訪問路徑編解碼字符集-->
</configuration>
</plugin>
</plugins>
</build>
POST發送參數
發送請求與參數:
接收參數:
和GET一致,不用做任何修改
@Controller
public class UserController {
@RequestMapping("/commonParam")
@ResponseBody
public String commonParam(String name,int age){
System.out.println("普通參數傳遞 name ==> "+name);
System.out.println("普通參數傳遞 age ==> "+age);
return "{'module':'commonParam'}";
}
}
POST請求中文亂碼
form-data與x-www-form-urlencoded都可以post請求,區別在於form-data可以發送文件
發送請求與參數:
接收參數:
控制台打印,會發現有中文亂碼問題。
解決方案:配置過濾器
public class ServletContainersInitConfig extends AbstractAnnotationConfigDispatcherServletInitializer {
protected Class<?>[] getRootConfigClasses() {
return new Class[0];
}
protected Class<?>[] getServletConfigClasses() {
return new Class[]{SpringMvcConfig.class};
}
protected String[] getServletMappings() {
return new String[]{"/"};
}
//亂碼處理
@Override
protected Filter[] getServletFilters() {
CharacterEncodingFilter filter = new CharacterEncodingFilter();
filter.setEncoding("UTF-8");
return new Filter[]{filter};
}
}
CharacterEncodingFilter是在spring-web包中,所以用之前需要導入對應的jar包。
二、五種類型參數傳遞
前面我們已經能夠使用GET或POST來發送請求和數據,所攜帶的數據都是比較簡單的數據,接下來在這個基礎上,我們來研究一些比較複雜的參數傳遞,常見的參數種類有:
-
普通參數
-
POJO類型參數
-
嵌套POJO類型參數
-
數組類型參數
-
集合類型參數
這些參數如何發送,後台改如何接收?
2.1 普通參數
-
普通參數:url地址傳參,地址參數名與形參變量名相同,定義形參即可接收參數。
如果形參與地址參數名不一致該如何解決?
發送請求與參數:
//localhost/commonParamDifferentName?name=張三&age=18
後台接收參數:
@RequestMapping("/commonParamDifferentName")
@ResponseBody
public String commonParamDifferentName(String userName , int age){
System.out.println("普通參數傳遞 userName ==> "+userName);
System.out.println("普通參數傳遞 age ==> "+age);
return "{'module':'common param different name'}";
}
因為前端給的是name
,後台接收使用的是userName
,兩個名稱對不上,導致接收數據失敗:
解決方案:使用@RequestParam註解
@RequestMapping("/commonParamDifferentName")
@ResponseBody
public String commonParamDifferentName(@RequestParam("name") String userName , int age){
System.out.println("普通參數傳遞 userName ==> "+userName);
System.out.println("普通參數傳遞 age ==> "+age);
return "{'module':'common param different name'}";
}
注意:寫上@RequestParam註解框架就不需要自己去解析注入,能提升框架處理性能
2.2 POJO數據類型
簡單數據類型一般處理的是參數個數比較少的請求,如果參數比較多,那麼後台接收參數的時候就比較複雜,這個時候我們可以考慮使用POJO數據類型。
-
POJO參數:請求參數名與形參對象屬性名相同,定義POJO類型形參即可接收參數
此時需要使用前面準備好的POJO類,先來看下User
public class User {
private String name;
private int age;
//setter...getter...略
}
發送請求和參數:
後台接收參數:
//POJO參數:請求參數與形參對象中的屬性對應即可完成參數傳遞
@RequestMapping("/pojoParam")
@ResponseBody
public String pojoParam(User user){
System.out.println("pojo參數傳遞 user ==> "+user);
return "{'module':'pojo param'}";
}
注意:
-
POJO參數接收,前端GET和POST發送請求數據的方式不變。
-
請求參數key的名稱要和POJO中屬性的名稱一致,否則無法封裝。
2.3 嵌套POJO類型參數
如果POJO對象中嵌套了其他的POJO類,如
public class Address {
private String province;
private String city;
//setter...getter...略
}
public class User {
private String name;
private int age;
private Address address;
//setter...getter...略
}
-
嵌套POJO參數:請求參數名與形參對象屬性名相同,按照對象層次結構關係即可接收嵌套POJO屬性參數
發送請求和參數:
後台接收參數:
//POJO參數:請求參數與形參對象中的屬性對應即可完成參數傳遞
@RequestMapping("/pojoParam")
@ResponseBody
public String pojoParam(User user){
System.out.println("pojo參數傳遞 user ==> "+user);
return "{'module':'pojo param'}";
}
注意:
請求參數key的名稱要和POJO中屬性的名稱一致,否則無法封裝
2.4 數組類型參數
舉個簡單的例子,如果前端需要獲取用戶的愛好,愛好絕大多數情況下都是多個,如何發送請求數據和接收數據呢?
-
數組參數:請求參數名與形參對象屬性名相同且請求參數為多個,定義數組類型即可接收參數
發送請求和參數:
後台接收參數:
//數組參數:同名請求參數可以直接映射到對應名稱的形參數組對象中
@RequestMapping("/arrayParam")
@ResponseBody
public String arrayParam(String[] likes){
System.out.println("數組參數傳遞 likes ==> "+ Arrays.toString(likes));
return "{'module':'array param'}";
}
2.5 集合類型參數
數組能接收多個值,那麼集合是否也可以實現這個功能呢?
發送請求和參數:
後台接收參數:
//集合參數:同名請求參數可以使用@RequestParam註解映射到對應名稱的集合對象中作為數據
@RequestMapping("/listParam")
@ResponseBody
public String listParam(List<String> likes){
System.out.println("集合參數傳遞 likes ==> "+ likes);
return "{'module':'list param'}";
}
運行會報錯,
錯誤的原因是:SpringMVC將List看做是一個POJO對象來處理,將其創建一個對象並準備把前端的數據封裝到對象中,但是List是一個接口無法創建對象,所以報錯。
解決方案是:使用@RequestParam
註解
//集合參數:同名請求參數可以使用@RequestParam註解映射到對應名稱的集合對象中作為數據
@RequestMapping("/listParam")
@ResponseBody
public String listParam(@RequestParam List<String> likes){
System.out.println("集合參數傳遞 likes ==> "+ likes);
return "{'module':'list param'}";
}
-
集合保存普通參數:請求參數名與形參集合對象名相同且請求參數為多個,@RequestParam綁定參數關係
-
對於簡單數據類型使用數組會比集合更簡單些。
知識點1:@RequestParam
名稱 | @RequestParam |
---|---|
類型 | 形參註解 |
位置 | SpringMVC控制器方法形參定義前面 |
作用 | 綁定請求參數與處理器方法形參間的關係 |
相關參數 | required:是否為必傳參數 defaultValue:參數默認值 |
三、JSON數據傳輸參數
現在比較流行的開發方式為異步調用。前後台以異步方式進行交換,傳輸的數據使用的是JSON,所以前端如果發送的是JSON數據,後端該如何接收?
對於JSON數據類型,我們常見的有三種:
-
json普通數組([“value1″,”value2″,”value3”,…])
-
json對象({key1:value1,key2:value2,…})
-
json對象數組([{key1:value1,…},{key2:value2,…}])
對於上述數據,前端如何發送,後端如何接收?
JSON普通數組
步驟1:pom.xml添加依賴
SpringMVC默認使用的是jackson來處理json的轉換,所以需要在pom.xml添加jackson依賴
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.0</version>
</dependency>
步驟2:PostMan發送JSON數據
Body->raw->JSON
步驟3:開啟SpringMVC註解支持
在SpringMVC的配置類中開啟SpringMVC的註解支持,這裏面就包含了將JSON轉換成對象的功能。
@Configuration
@ComponentScan("com.itheima.controller")
//開啟json數據類型自動轉換
@EnableWebMvc
public class SpringMvcConfig {
}
步驟4:參數前添加@RequestBody
//使用@RequestBody註解將外部傳遞的json數組數據映射到形參的集合對象中作為數據
@RequestMapping("/listParamForJson")
@ResponseBody
public String listParamForJson(@RequestBody List<String> likes){
System.out.println("list common(json)參數傳遞 list ==> "+likes);
return "{'module':'list common for json param'}";
}
步驟5:啟動運行程序
JSON普通數組的數據就已經傳遞完成,下面針對JSON對象數據和JSON對象數組的數據該如何傳遞呢?
JSON對象數據
請求和數據的發送:
{
"name":"itcast",
"age":15
}
後端接收數據:
@RequestMapping("/pojoParamForJson")
@ResponseBody
public String pojoParamForJson(@RequestBody User user){
System.out.println("pojo(json)參數傳遞 user ==> "+user);
return "{'module':'pojo for json param'}";
}
啟動程序訪問測試
說明:
address為null的原因是前端沒有傳遞數據給後端。
如果想要address也有數據,我們需求修改前端傳遞的數據內容:
{
"name":"itcast",
"age":15,
"address":{
"province":"beijing",
"city":"beijing"
}
}
再次發送請求,就能看到address中的數據
JSON對象數組
集合中保存多個POJO該如何實現?
請求和數據的發送:
[
{"name":"itcast","age":15},
{"name":"itheima","age":12}
]
後端接收數據:
@RequestMapping("/listPojoParamForJson")
@ResponseBody
public String listPojoParamForJson(@RequestBody List<User> list){
System.out.println("list pojo(json)參數傳遞 list ==> "+list);
return "{'module':'list pojo for json param'}";
}
啟動程序訪問測試
小結
SpringMVC接收JSON數據的實現步驟為:
(1)導入jackson包
(2)使用PostMan發送JSON數據
(3)開啟SpringMVC註解驅動,在配置類上添加@EnableWebMvc註解
(4)Controller方法的參數前添加@RequestBody註解
知識點1:@EnableWebMvc
名稱 | @EnableWebMvc |
---|---|
類型 | 配置類註解 |
位置 | SpringMVC配置類定義上方 |
作用 | 開啟SpringMVC多項輔助功能 |
知識點2:@RequestBody
名稱 | @RequestBody |
---|---|
類型 | 形參註解 |
位置 | SpringMVC控制器方法形參定義前面 |
作用 | 將請求中請求體所包含的數據傳遞給請求參數,此註解一個處理器方法只能使用一次 |
@RequestBody與@RequestParam區別
-
區別
-
@RequestParam用於接收url地址傳參,表單傳參【application/x-www-form-urlencoded】
-
@RequestBody用於接收json數據【application/json】
-
-
應用
-
後期開發中,發送json格式數據為主,@RequestBody應用較廣
-
如果發送非json格式數據,選用@RequestParam接收請求參數
-
四、日期類型參數傳遞
前面我們處理過簡單數據類型、POJO數據類型、數組和集合數據類型以及JSON數據類型,接下來我們還得處理一種開發中比較常見的一種數據類型,日期類型
日期類型比較特殊,因為對於日期的格式有N多中輸入方式,比如:
-
2088-08-18
-
2088/08/18
-
08/18/2088
-
……
針對這麼多日期格式,SpringMVC該如何接收,它能很好的處理日期類型數據么?
步驟1:編寫方法接收日期數據
在UserController類中添加方法,把參數設置為日期類型
@RequestMapping("/dataParam")
@ResponseBody
public String dataParam(Date date)
System.out.println("參數傳遞 date ==> "+date);
return "{'module':'data param'}";
}
步驟2:啟動Tomcat服務器
步驟3:使用PostMan發送請求
使用PostMan發送GET請求,並設置date參數
步驟4:查看控制台
通過打印,我們發現SpringMVC可以接收日期數據類型,並將其打印在控制台。
這個時候,我們就想如果把日期參數的格式改成其他的,SpringMVC還能處理么?
步驟5:更換日期格式
為了能更好的看到程序運行的結果,我們在方法中多添加一個日期參數
@RequestMapping("/dataParam")
@ResponseBody
public String dataParam(Date date,Date date1)
System.out.println("參數傳遞 date ==> "+date);
System.out.println("參數傳遞 date1 ==> "+date1);
return "{'module':'data param'}";
}
使用PostMan發送請求,攜帶兩個不同的日期格式,
//localhost/dataParam?date=2088/08/08&date1=2088-08-08
發送請求和數據後,頁面會報400,控制台會報出一個錯誤
Resolved [org.springframework.web.method.annotation.==MethodArgumentTypeMismatchException==: Failed to convert value of type ‘java.lang.String’ to required type ‘java.util.Date’; nested exception is org.springframework.core.convert.==ConversionFailedException==: Failed to convert from type [java.lang.String] to type [java.util.Date] for value ‘2088-08-08’; nested exception is java.lang.IllegalArgumentException]
從錯誤信息可以看出,錯誤的原因是在將2088-08-08
轉換成日期類型的時候失敗了,原因是SpringMVC默認支持的字符串轉日期的格式為yyyy/MM/dd
,而我們現在傳遞的不符合其默認格式,SpringMVC就無法進行格式轉換,所以報錯。
解決方案也比較簡單,需要使用@DateTimeFormat
@RequestMapping("/dataParam")
@ResponseBody
public String dataParam(Date date,
@DateTimeFormat(pattern="yyyy-MM-dd") Date date1)
System.out.println("參數傳遞 date ==> "+date);
System.out.println("參數傳遞 date1(yyyy-MM-dd) ==> "+date1);
return "{'module':'data param'}";
}
重新啟動服務器,重新發送請求測試,SpringMVC就可以正確的進行日期轉換了
步驟6:攜帶時間的日期
接下來我們再來發送一個攜帶時間的日期,看下SpringMVC該如何處理?
先修改UserController類,添加第三個參數
@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("參數傳遞 date ==> "+date);
System.out.println("參數傳遞 date1(yyyy-MM-dd) ==> "+date1);
System.out.println("參數傳遞 date2(yyyy/MM/dd HH:mm:ss) ==> "+date2);
return "{'module':'data param'}";
}
使用PostMan發送請求,攜帶兩個不同的日期格式,
//localhost/dataParam?date=2088/08/08&date1=2088-08-08&date2=2088/08/08 8:08:08
重新啟動服務器,重新發送請求測試,SpringMVC就可以將日期時間的數據進行轉換
知識點1:@DateTimeFormat
名稱 | @DateTimeFormat |
---|---|
類型 | 形參註解 |
位置 | SpringMVC控制器方法形參前面 |
作用 | 設定日期時間型數據格式 |
相關屬性 | pattern:指定日期時間格式字符串 |
內部實現原理
講解內部原理之前,我們需要先思考個問題:
-
前端傳遞字符串,後端使用日期Date接收
-
前端傳遞JSON數據,後端使用對象接收
-
前端傳遞字符串,後端使用Integer接收
-
後台需要的數據類型有很多種
-
在數據的傳遞過程中存在很多類型的轉換
誰來做這個類型轉換?答:SpringMVC
SpringMVC是如何實現類型轉換的?SpringMVC中提供了很多類型轉換接口和實現類
在框架中,有一些類型轉換接口,其中有:
-
(1) Converter接口
/**
* S: the source type
* T: the target type
*/
public interface Converter<S, T> {
@Nullable
//該方法就是將從頁面上接收的數據(S)轉換成我們想要的數據類型(T)返回
T convert(S source);
}
注意:Converter所屬的包為org.springframework.core.convert.converter
Converter接口的實現類
框架中有提供很多對應Converter接口的實現類,用來實現不同數據類型之間的轉換,如:
請求參數年齡數據(String→Integer)
日期格式轉換(String → Date)
-
(2) HttpMessageConverter接口
該接口是實現對象與JSON之間的轉換工作,了解一下即可
注意:SpringMVC的配置類把@EnableWebMvc當做標配配置上去,不要省略
@EnableWebMvc功能之一:根據類型匹配對應的類型轉換器