springMVC系列(八)——springMVC參數接收詳解

  • 2019 年 10 月 30 日
  • 筆記

版權聲明:本文為博主原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接和本聲明。

本文鏈接:https://blog.csdn.net/luo4105/article/details/72480997

參數接收

springMVC參數傳遞有一下幾種形式:

1.request、response、session傳遞。

2.參數綁定

3.url動態參數

request、response、session傳遞

這種和servlet是一樣的,request.getAttribute(「」),response.setAttribute(「」)等

參數綁定

http的參數是以key-value的形式傳遞的, springMVC接收參數是通過方法的形參來接收,而不是通過控制器的類成員來接收。

參數綁定分為這麼幾種形式

1.基本的java對象參數綁定

2.自定義pojo對象參數綁定

3.參數解析綁定pojo

4集合對象參數(List、Set等)綁定

基本的java對象參數綁定

http的參數是以key-value的形式傳遞的,springMVC會自動綁定key與形參名相同的參數。

1.測試方法

@Test  public void strParam() throwsIOException {      InputStream is = HttpUtil.doGet(testUrl + "/string?id=1&name=mark");      String response= StreamUtils.inputStreamToString(is, "UTF-8");      System.out.println(response);  }

testUrl是項目的url

public static String testUrl = "http://127.0.0.1:8080/study_ssmvc/params";

HttpUtil.doGet是發送http請求的工具方法,在下面的測試方法中也會出現

public class HttpUtil {      public static InputStream doGet(String urlstr) throws IOException {         URL url= new URL(urlstr);         HttpURLConnection conn= (HttpURLConnection) url.openConnection();         InputStream inputStream= conn.getInputStream();         return inputStream;      }  }

StreamUtils.inputStreamToString是將http響應InputStream轉成String便於打印輸出的工具方法。在下面的測試方法中也會出現。

public class StreamUtils {      public static String inputStreamToString(InputStreamis, String charset) throws IOException {         byte[] bytes = new byte[1024];         int byteLength = 0;         StringBuffer sb = new StringBuffer();         while((byteLength = is.read(bytes)) != -1) {             sb.append(new String(bytes, 0, byteLength, charset));         }         return sb.toString();      }  }

2.Controller

@ResponseBody  @RequestMapping("string")  public String strParam(String id, String name){      System.out.println("params = id:"+ id + ", name: "+ name);      TestVovo = new TestVo();      vo.setId(id);      vo.setName(name);      return vo.toString();  }

3.測試通過、響應數據

需要注意一點的是」@ResponseBody」的作用是將java對象轉成json字符串,以response.write()形式產生響應。需要導入jackson.jar,或者也可以使用fastjson來序列化json。

使用fastjson的配置

<mvc:annotation-driven>      <mvc:message-converters register-defaults="true">         <!-- 配置Fastjson支持 -->         <bean             class="com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter">             <property name="supportedMediaTypes">                <list>                    <value>text/html;charset=UTF-8</value>                    <value>application/json</value>                </list>             </property>             <property name="features">                <list>                    <value>WriteMapNullValue</value>                    <value>QuoteFieldNames</value>                </list>             </property>         </bean>      </mvc:message-converters>  </mvc:annotation-driven>

Pojo數據綁定

springMVC會自動將http請求參數的key與pojo類中屬性名相同的屬性綁定。

1.測試方法

@Test  public void pojoParam() throwsIOException {      InputStream is = HttpUtil.doGet(testUrl + "/pojo?id=1&name=mark");      String response= StreamUtils.inputStreamToString(is, "UTF-8");      System.out.println(response);  }

2.Pojo

public class TestVo {        private String id;      private String name;      /*       getter()、setter()、toString()      */  }

3.Controller

@Test  public void pojoParam() throwsIOException {      InputStream is = HttpUtil.doGet(testUrl + "/pojo?id=1&name=mark");      String response= StreamUtils.inputStreamToString(is, "UTF-8");      System.out.println(response);  }

4.測試通過、響應數據

Date類型數據解析綁定

這裡把date類型單獨拿出來說,http請求的參數是String類型,要把String解析成其他實體類型參數,需要使用自定義類型轉化器Converter。

在springMVC中,可以通過Converter對參數進行自定義轉化。

1.測試方法

date參數類型」yyyy-MM-ddhh:mm:ss」

@Test  public void dateParam() throws IOException {      String date= URLEncoder.encode("2017-5-18 12:12:12");      InputStream is = HttpUtil.doGet(testUrl + "/date?id=1&name=mark&time=" + date);      String response= StreamUtils.inputStreamToString(is, "UTF-8");      System.out.println(response);  }

URLEncoder.encode()方法作用是將參數中的空格、特殊字符轉成http能傳輸的格式的字符串。

2.實現轉化接口converter

新建自定義時間轉化類CustomDateConverter,實現Converter接口

public class CustomDateConverter implements Converter<String, Date> {      @Override      public Date convert(String source) {         SimpleDateFormat sdf= new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");         try {             return sdf.parse(source);         }catch(ParseException e){             e.printStackTrace();         }         return null;      }  }

3.配置轉化類

在springMVC配置文件中註冊formattingConversionServiceFactoryBean

<bean class="org.springframework.format.support.FormattingConversionServiceFactoryBean"id="factoryBean" >     <property name="converters"><!-- 在屬性converters註冊 -->          <list>              <bean class="com.lc.convert.CustomDateConverter"/>              <!-- <bean class="com.lc.convert.GirlConverter" />-->          </list>     </property>  </bean>  <mvc:annotation-driven conversion-service="factoryBean">

也可以註冊ConversionServiceFactoryBean,即將formattingConversionServiceFactoryBean 改為ConversionServiceFactoryBean。

ConversionServiceFactoryBean與formattingConversionServiceFactoryBean的區別在於formattingConversionServiceFactoryBean也是繼承ConversionService接口,它有兩個內建實現類,分別支持數組及數字類型的註解驅動格式化。 如果只用formattingConversionServiceFactoryBean自帶的兩個內建實現類,在mvc:annotation-driven可以不進行conversion-service的配置,如果有自定義converter,就必須加上mvc:annotation-driven的配置。

<mvc:annotation-driven conversion-service="factoryBean">

4.controller

@ResponseBody  @RequestMapping("date")  public Map<String, Object> dateParam(TestVo vo, Date time) {      System.out.println("param = "+ vo);      System.out.println("time = "+ time);      Map<String,Object> map= new HashMap<>();      map.put("param",vo);      map.put("time", time);      return map;  }

5.測試通過、響應數據

使用@ DateTimeFormat

實際上FormattingConversionServiceFactoryBean類中存在Date轉化類,不需要我們再去寫,我們只需要使用」 @DateTimeFormat(pattern="yyyy-MM-dd hh:mm:ss") Date time」放在參數前就可以了。

FormattingConversionServiceFactoryBean不僅支持@ DateTimeFormat,而且支持@NumberFormat標籤,可對數字類型屬性標註。

簡單List集合參數

1.測試方法

@Test  public voidlistParam() throwsIOException {      String date= URLEncoder.encode("2017-5-18 12:12:12");      InputStream is = HttpUtil.doGet(testUrl + "/list?id=1&name=mark&time=" + date+ "&son=Bob&son=John");      String response= StreamUtils.inputStreamToString(is, "UTF-8");      System.out.println(response);  }

Controller的形參是不支持直接用List<String>son,去接收List,它會拋出異常:

org.springframework.beans.BeanInstantiationException:Failed to instantiate [java.util.List]: Specified class is an interface

這裡需要把List<String> son用一個pojo去包裝一下,

2.Pojo

public class ListSon {        private List<String> son;           /*       getter()、setter()、toString()      */  }

在controller中用ListSon這個Pojo類作為形參,就可以獲得拿到List參數了

3.controller

@ResponseBody  @RequestMapping("list")  public Map<String, Object> listParam(TestVo vo, ListSon son) {      System.out.println("param = "+ vo);      System.out.println("son = "+ son.toString());      Map<String,Object> map= new HashMap<>();      map.put("param",vo);      map.put("son", son);      return map;  }

4.測試通過、響應數據

Set、Map相似

複雜的List集合

對於List<pojo>,自定義pojo類這種接收參數形式,有兩種方式去接收

1.前台轉成json,以json字符串的形式請求服務端,服務器解析json,轉成List<pojo>,這裡不介紹這一種。

2.http請求直接放數組,controller直接以包裝List<pojo>去接收

先看測試方法,注意請求參數格式

1.測試方法

@Test  public void pojolistParam() throwsIOException {      String date = URLEncoder.encode("2017-5-18 12:12:12");      InputStream is = HttpUtil.doGet(testUrl + "/pojolist?vos[0].id=1&vos[1].id=2&vos[0].name=john&vos[1].name=mark&time=" + date+ "&son=Bob&son=John");      String response= StreamUtils.inputStreamToString(is, "UTF-8");      System.out.println(response);  }

參數的形式是」 vos[0].id=1&vos[1].id=2&vos[0].name=john&vos[1].name=mark」這樣的形式

2.pojo類

public class ListSon {        private List<String> son;      private List<TestVo> vos;           /*       getter()、setter()、toString()      */  }

TestVo

public class TestVo {        private String id;      private String name;      /*       getter()、setter()、toString()      */  }

3.controller

@ResponseBody  @RequestMapping("pojolist")  public Map<String, Object> listParam( ListSon son) {      System.out.println("son = "+ son.toString());      Map<String,Object> map= new HashMap<>();      map.put("son", son);      return map;  }

4.測試通過、響應數據

自定義參數解析pojo

這實際上類似於Date的參數解析綁定

需求:girl類有id、name、age三個屬性,參數上傳格式」girl=id|name|age」的形式,如」girl=1|jonny|18」,實現springMVC形參直接用Girl對象接收」 id|name|age」字符串並解析。

1.測試方法

@Test  public void customParam() throws IOException {      String date= URLEncoder.encode("2017-5-18 12:12:12");      InputStream is = HttpUtil.doGet(testUrl + "/cutom?id=1&name=mark&time=" + date+ "&son=Bob&son=John&girl=Tim|Andy|Juddy");      String response= StreamUtils.inputStreamToString(is, "UTF-8");      System.out.println(response);  }

關注最後一個參數girl的形式

2.Pojo

public class Girl {        private String id;      private String name;      private Integer age;  /*       getter()、setter()、toString()      */  }

3.實現轉化接口converter

public class GirlConverter implements Converter<String, Girl> {        @Override      public Girl convert(String source) {         String[]girls= source.split("\|");         Girl girl= new Girl();         girl.setId(girls[0]);         girl.setName(girls[1]);         girl.setAge(Integer.valueOf(girls[2]));         return girl;      }  }

這只是簡單大致的實現一下,正常的情況應加上異常處理,這裡這麼寫,便於理解。注意情況見上面的Date類型數據綁定

4.配置轉化類

在springMVC配置文件中註冊formattingConversionServiceFactoryBean

<mvc:annotation-driven conversion-service="factoryBean">
<bean class="org.springframework.format.support.FormattingConversionServiceFactoryBean" id="factoryBean">     <property name="converters"><!-- 在屬性converters註冊 -->          <list>              <bean class="com.lc.convert.GirlConverter"/>          </list>     </property>  </bean>

5.controller

@ResponseBody  @RequestMapping("custom")  public Map<String, Object> customParam(TestVo vo, List<String> son, Girl girl) {      System.out.println("param = "+ vo);      System.out.println("son = "+ son.toString());      System.out.println("girl = "+ girl.toString());      Map<String,Object> map= new HashMap<>();      map.put("param",vo);      map.put("son", son);      map.put("girl", girl);      return map;  }

6.測試通過、響應數據

URL動態參數綁定

在restful風格的接口中,會以url的形式傳參,SpringMVC支持獲得url的動態參數

1.測試方法

@Test  public void urlParam() throws IOException {      InputStream is = HttpUtil.doGet(testUrl + "/url/mark");      String response= StreamUtils.inputStreamToString(is, "UTF-8");      System.out.println(response);  }

url後的mark就是參數

2.controller

@ResponseBody  @RequestMapping("/url/{name}")  public Map<String, Object> customParam(@PathVariable("name") String name) {      System.out.println("name = "+ name);      Map<String,Object> map= new HashMap<>();      map.put("name", name);      return map;  }

3.測試通過、響應數據

代碼地址:https://code.csdn.net/luo4105/study_ssmvc/tree/master