Spring MVC之请求参数绑定

生活中,最使人疲惫的往往不是道路的遥远,而是心中的郁闷;最使人痛苦的往往不是生活的不幸,而是希望的破灭;最使人颓废的往往不是前途的坎坷,而是自信的丧失;最使人绝望的往往不是挫折的打击,而是心灵的死亡。所以我们要有自己的梦想,让梦想的星光指引着我们走出落漠,走出惆怅,带着我们走进自己的理想。

导读:本篇文章讲解 Spring MVC之请求参数绑定,希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com,来源:原文

一、请求参数的绑定

服务器端要获得请求的参数,需要进行数据的封装,SpringMVC可以接收如下类型的参数。

Controller中的方法的参数名称要与请求参数的name一致,参数值会自动映射匹配,并且能自动做类型转换;自动的类型转换是指从String向其他类型的转换。

数据类型 描述 要求
基本类型参数 包括基本类型和 String 类型 参数名称必须和控制器中方法的形参名称保持一致,严格区分大小写
POJO 类型参数 包括实体类,以及关联的实体类 要求表单中参数名称和 POJO 类的属性名称保持一致。并且控制器方法的参数类型是 POJO 类型。
数组和集合类型参数 包括 List 结构和 Map 结构的集合(包括数组) 1:要求集合类型的请求参数必须在 POJO 中。2:在表单中请求参数名称要和 POJO 中集合属性名称相同。 3.给 List 集合中的元素赋值,使用下标,给 Map 集合中的元素赋值,使用键值对。4:接收的请求参数是 json 格式数据时,需要借助@RequestBody 注解实现。

1.基本类型和String类型

1.简单数据类型:值必须存在,不传可以通过默认值代替

2.包装类型:值可以为空

http://localhost:8080/test?username=admin&password=123

    @RequestMapping("/test")
    public String testParam(String username,String password,
						    @RequestParam(defaultValue="0",name="flag" int flag,
						    Integer age,){
        System.out.println("用户名:"+ username);
        System.out.println("密码:"+ password);
        System.out.println("请求来源:"+ flag);
        System.out.println("年龄:"+ age);
        return "success";
    }

2.POJO(VO)类型

public class User implements Serializable {
	private Integer id;
	private String name;
	private Integer age;
	private Car car;
	//getters and setters
}

public class Car implements Serializable {
	private Integer id;
	private String brand;
	private Float price;
	//getters and setters
}


	 <form action="test" method="post">
        姓名:<input type="text" name="name" /><br/>
        年龄:<input type="text" name="age" /><br/>
        车辆品牌:<input type="text" name="car.brand" /><br/>
        车辆价格:<input type="text" name="car.price" /><br/>
        <input type="submit" value="提交" />
    </form>

    @RequestMapping("/test")
    public String testParam(User user){
        System.out.println("User :"+user);
        return "success";
    }

3.POJO(VO)类中包含List、Map、Set集合类型

Map最为灵活,它需要绑定在对象上,Set和List类似,也需要绑定在对象上,而不能直接写在Controller方法的参数中。

public class User implements Serializable {
	private Integer id;
	private String name;
	private Integer age;
	private List<Car> list;
	private Map<String,Car> map;
	private Set<Car> set;
	//getters and setters
}

public class Car implements Serializable {
	private Integer id;
	private String brand;
	private Float price;
	//getters and setters
}


 <form action="test" method="post">
        姓名:<input type="text" name="name" /><br/>
        年龄:<input type="text" name="age" /><br/>
        
        车辆品牌:<input type="text" name="list[0].brand" /><br/>
        车辆价格:<input type="text" name="list[0].price" /><br/>
        
      	车辆品牌:<input type="text" name="map['one'].brand" /><br/>
        车辆价格:<input type="text" name="map['one'].price" /><br/>
        
		车辆品牌1<input type="text" name="set[0].brand" value="BM"/><br/>
		车辆品牌2<input type="text" name="set[1].brand" value="BC"/><br/>
 
        <input type="submit" value="提交" />
    </form>

    /**
     * POJO类中包含集合类型参数
     * @return
     */
    @RequestMapping("/test")
    public String testParam(User user){
        System.out.println("User :"+user);
        return "success";
    }

当使用ajax提交时,可以指定contentType为json形式,那么在方法参数位置使用@RequestBody可以直接接收集合数据而无需使用POJO进行包装

	var userList = new Array();
	userList.push({name:"zhangsan",age:18});
	userList.push({name:"lisi",age:28});
	$.ajax({
	type:"POST",
	url:"${pageContext.request.contextPath}/test",
	data:JSON.stringify(userList),
	contentType:"application/json;charset=utf-8"
	});

@RequestMapping(value="/test")
@ResponseBody
public void save15(@RequestBody List<User> userList) {
System.out.println(userList);
}

4.数组类型

    @RequestMapping("/test")
    public String testParam(String[] strs,@RequestParam(value="ids")String[] ids){
        System.out.println("strs:"+strs);
        System.out.println("ids:"+ids);
        return "success";
    }

5.使用 ServletAPI 对象作为方法参数

SpringMVC 还支持使用原始 ServletAPI 对象作为控制器方法的参数。

支持原始 ServletAPI 对象有:
HttpServletRequest、HttpServletResponse、HttpSession、java.security.Principal、Locale、InputStream、OutputStream、Reader、Writer

    /**
     *  使用 ServletAPI 对象作为方法参数
     * @return
     */
    @RequestMapping("/test")
    public String testParam(HttpServletRequest request, HttpServletResponse response, HttpSession session){
        System.out.println(request);
        System.out.println(response);
        System.out.println(session);
        return "success";
    }

二、开启静态资源的访问

当有静态资源需要加载时,比如js/css/images等文件,通过控制台开发者工具抓包发现,没有加载到js/css/images等文件,原因是SpringMVC的前端控制器DispatcherServlet的url-pattern配置的是/,代表对所有的资源都进行过滤操作,可以通过以下两种方式指定放行静态资源:

<!--第一种-->
<!-- location 表示路径,mapping 表示文件,**表示该目录下的文件以及子目录的文件 -->
<mvc:resources location="/css/" mapping="/css/**"/>
<mvc:resources location="/images/" mapping="/images/**"/>
<mvc:resources location="/scripts/" mapping="/javascript/**"/>

<!--第二种-->
<mvc:default-servlet-handler/>

三、配置全局乱码过滤器

post方式

在 web.xml 中配置一个过滤器

	<!--配置全局过滤的filter-->
	<filter>
		<filter-name>CharacterEncodingFilter</filter-name>
		<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
		<!-- 设置过滤器中的属性值 -->
		<init-param>
			<param-name>encoding</param-name>
			<param-value>UTF-8</param-value>
		</init-param>
		<!-- 启动过滤器 -->
		<init-param>
			<param-name>forceEncoding</param-name>
			<param-value>true</param-value>
		</init-param>
	</filter>
	<!-- 过滤所有请求 -->
	<filter-mapping>
		<filter-name>CharacterEncodingFilter</filter-name>
		<url-pattern>/*</url-pattern>
	</filter-mapping>

get方式

tomacat 对 GET和 POST 请求处理方式是不同的,GET请求的编码问题,要改 tomcat 的 server.xml配置文件

<Connector connectionTimeout="20000" port="8080"
	protocol="HTTP/1.1" redirectPort="8443"/>
改为:
<Connector connectionTimeout="20000" port="8080"
	protocol="HTTP/1.1" redirectPort="8443"
	useBodyEncodingForURI="true"/>
	
	当遇到 ajax 请求仍然乱码时,使用如下配置:
	useBodyEncodingForURI="true"改为 URIEncoding="UTF-8"

四、自定义类型转换器

表单提交的任何数据类型全部都是字符串类型,但是后台定义Integer类型,数据也可以封装上,说明Spring框架内部会默认进行数据类型转换。如果想自定义数据类型转换,可以实现Converter的接口。

在特殊情况下就需要自定义类型转换,如日期类型的转换。

例如:参数date=2020-01-01,springmvc使用String类型接收能够正常转换处理。但当使用Date 类型接收时将会报错。

    @RequestMapping("/test")
    public String testParam( String date){
        System.out.println("date:"+date);
        return "success";
    }

    @RequestMapping("/test")
    public String testParam( Date date){
        System.out.println("date:"+date);
        return "success";
    }

1.自定义类型转换器

定义一个类,实现 Converter 接口,该接口有两个泛型,S:表示接受的类型,T:表示目标类型。

/**
 * A converter converts a source object of type {@code S} to a target of type {@code T}.
 *
 * <p>Implementations of this interface are thread-safe and can be shared.
 *
 * <p>Implementations may additionally implement {@link ConditionalConverter}.
 *
 * @author Keith Donald
 * @since 3.0
 * @param <S> the source type
 * @param <T> the target type
 */
@FunctionalInterface
public interface Converter<S, T> {

	/**
	 * Convert the source object of type {@code S} to target type {@code T}.
	 * @param source the source object to convert, which must be an instance of {@code S} (never {@code null})
	 * @return the converted object, which must be an instance of {@code T} (potentially {@code null})
	 * @throws IllegalArgumentException if the source cannot be converted to the desired target type
	 */
	@Nullable
	T convert(S source);

}

/**
 * 把字符串转换日期
 */
public class StringToDateConverter implements Converter<String,Date>{

    /**
     * String source    传入字符串
     * @param source
     * @return
     */
    @Override
    public Date convert(String source) {
   
        if(source == null){
            throw new RuntimeException("参数不能为空!");
        }
        DateFormat df = new SimpleDateFormat("yyyy-MM-dd");

        try {
            // 把字符串转换日期
            return df.parse(source);
        } catch (Exception e) {
            throw new RuntimeException("字符串转日期类型转换出错!");
        }
    }

}

2.注册自定义类型转换器

在 spring 配置文件中配置类型转换器,spring 配置类型转换器的机制是,将自定义的转换器注册到类型转换服务中去。

   <!--配置自定义类型转换器-->
   
   <!-- 配置类型转换器工厂 -->
    <bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean">
        <!-- 给工厂注入一个新的类型转换器 -->
        <property name="converters">
            <set>
                <bean class="cn.ybzy.util.StringToDateConverter"/>
            </set>
        </property>
    </bean>

3.引用配置的类型转换服务

在 annotation-driven 标签中引用配置的类型转换服务

<!-- 引用自定义类型转换器 -->
<mvc:annotation-driven conversion-service="converterService"></mvc:annotation-driven>

配置完成后,查询Converter接口的实现,发现自定义类型转换已经注册到转换服务中.
在这里插入图片描述

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/137121.html

(0)
飞熊的头像飞熊bm

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!