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