Java開發學習(二十五)----使用PostMan完成不同類型參數傳遞

一、請求參數

請求路徑設置好後,只要確保頁面發送請求地址和後臺Controller類中配置的路徑一致,就可以接收到前端的請求,接收到請求後,如何接收頁面傳遞的參數?

關於請求參數的傳遞與接收是和請求方式有關係的,目前比較常見的兩種請求方式爲:

  • GET

  • POST

針對於不同的請求前端如何發送,後端如何接收?

1.1 環境準備

  • 創建一個Web的Maven項目

  • pom.xml添加Spring依賴

    <?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>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發送單個參數

發送請求與參數:

http://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發送多個參數

發送請求與參數:

http://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請求中文亂碼

如果我們傳遞的參數中有中文,你會發現接收到的參數會出現中文亂碼問題。

發送請求:http://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地址傳參,地址參數名與形參變量名相同,定義形參即可接收參數。

如果形參與地址參數名不一致該如何解決?

發送請求與參數:

http://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發送請求,攜帶兩個不同的日期格式,

http://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發送請求,攜帶兩個不同的日期格式,

http://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功能之一:根據類型匹配對應的類型轉換器

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章