一、前言
在上一篇博客的基础上,学习参数绑定,即,前端传参到后端。SpringMVC学习笔记(三)——整合 Mybatis(详细讲解搭建ssm框架)。
二、Controller 方法的返回值类型
1. 返回 ModelAndView
在 Controller 方法中定义 ModelAndView 对象,对象中可添加 Model 数据和指定 View,最后返回。
2. 返回 Void
2.1 通过使用 request 转向页面,如下:request.getRequestDispatcher("").forward(request, response);
2.2 通过使用 response 页面重定向:response.sendRedirect("url");
2.3 通过使用 response 指定响应结果,例如响应 JSON 数据如下:response.setCharacterEncoding("utf-8"); response.setContentType("application/json;charset=utf-8"); response.getWriter().write("json串");
3. 返回 String
3.1 单纯返回一个字符串,则这个字符串就是逻辑视图名,最后会通过视图解析器解析为物理视图(前缀 + 逻辑视图名 + 后缀)地址。
3.2 字符串前加“redirect:”,例如:return "redirect:queryItem.action";
表示重定向,相当于response.sendRedirect()
。
3.3 字符串前加“forward:”,例如:return "forward:queryItem.action";
表示转发,相当于request.getRequestDispatcher("").forward(request,response)
。
三、参数绑定介绍
Spring MVC 的参数绑定是将接收到的前端提交的数据(key/value形式)通过方法的形参来接收(struts2 是通过类的成员变量来结构)。参数绑定过程:在处理器适配器调用 Spring MVC 提供参数绑定组件 converter (3.0 版本前是 PropertyEditor )将 key/value 数据转成 Controller 方法的形参。我们可以自定义 converter 。比如日期类型绑定。
1. 默认支持的参数绑定类型
具体默认支持的参数类型有:HttpServletRequest、HttpServletResponse、HttpSession、Model / ModelMap。前三个是三大对象,后一个的 Model 是接口, ModelMap 是 Model 的实现类,可通过 addAttribute() 方法向页面传值。
通过在 Controller 中的 queryItems 方法加入形参,代码演示:
//商品查询
@RequestMapping("/queryItems")
public String queryItems(HttpServletRequest request, HttpServletResponse response,HttpSession session, Model model) throws Exception {
System.out.println(request);
System.out.println(response);
System.out.println(session);
//1.调用service 查找数据库的商品查询
List<ItemsCustom> itemsList = itemService.findItemsList(null);
model.addAttribute("itemsList", itemsList);
return "itemsList";
}
控制台输出:
org.apache.catalina.connector.RequestFacade@65144694
org.apache.catalina.connector.ResponseFacade@1625d264
org.apache.catalina.session.StandardSessionFacade@d17ae98
通过获取这几个默认对象,可以进行各种操作,比如重定向,返回 json 数据等等。
2. 简单类型的参数绑定
简单类型的数据绑定包括有 Integer、String、Double、Float、Boolean,具体的绑定方法是直接在方法中定义形参即可,形参名和前端传入的变量名一致,如果不一致可以使用注解 @RequestParam 对形参进行注解,其源码是:
@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface RequestParam {
@AliasFor("name")
String value() default "";
@AliasFor("value")
String name() default "";
boolean required() default true;
String defaultValue() default ValueConstants.DEFAULT_NONE;
}
当形参名和传入的变量名一致时可以省略注解 @RequestParam,但是如果不一致,就必须标注。
格式:
@RequestParam([value=]变量名,[…]) 形参类型 形参名
参数:
value :变量名,即入参的请求参数名字,如 value=“item_id”表示请求的参数中的名字为 item_id 的参数的值将传入;
required :是否必须传入,默认为true;
defaultValue :默认值,表示如果请求中没有同名参数时的默认值。
作用:
1. URL路径映射;
2. 窄化映射请求,注解在类上设置请求前缀;
3. 请求方法限定,例如 method=RequestMethod.GET。
参数绑定演示:
1.访问传参:http://localhost:8080/ssm/items/queryItems.action?items_id=1
2.代码演示:
//商品查询
@RequestMapping("/queryItems")
public String queryItems(@RequestParam("items_id") Integer items_id, Model model) throws Exception {
System.out.println("items_id = " + items_id);
//1.调用service 查找数据库的商品查询
List<ItemsCustom> itemsList = itemService.findItemsList(null);
model.addAttribute("itemsList", itemsList);
return "itemsList";
}
因为我传入的参数是 items_id ,而接收的形参也是 items_id,所以可以省略代码 @RequestParam("items_id")
。
3. 控制台打印:
items_id = 1
其他类型的同理。
3. POJO 类型的参数绑定
POJO 的类型绑定包括有简单 POJO 类型和复杂(POJO中有POJO)的 POJO 类型。两者都一样,在简单的 POJO类型进行参数绑定时,需要前台传入的参数名和 POJO 的成员变量名一致才能绑定上,复杂的 POJO 参数绑定对于内部的 POJO 类型通过 POJO成员变量名.另一个POJO的成员变量名
的方式进行绑定。
3.1 简单 POJO 参数绑定
JSP 代码:
<form name="itemsForm"
action="${pageContext.request.contextPath }/items/queryItems.action"
method="post">
查询条件:
<table width="100%" border=1>
<tr>
<td>
商品名称:<input name="name" type="text" /><br>
商品描述:<input name="detail" type="text" />
</td>
<td><input type="submit" value="查询" /> </td>
</tr>
</table>
</form>
后端代码:
@RequestMapping("/queryItems")
public String queryItems(Items items, Model model) throws Exception {
System.out.println("items = " + items);
//1.调用service 查找数据库的商品查询
List<ItemsCustom> itemsList = itemService.findItemsList(null);
model.addAttribute("itemsList", itemsList);
return "itemsList";
}
3.2 复杂 POJO 参数绑定
POJO ItemsQueryVo 类代码:
package com.ssm.po;
public class ItemsQueryVo {
private Items items; //商品类
//自定义用户扩展类,提高系统的可扩展性
private ItemsCustom itemsCustom; //自定义用户扩展类
public Items getItems() {
return items;
}
public void setItems(Items items) {
this.items = items;
}
public ItemsCustom getItemsCustom() {
return itemsCustom;
}
public void setItemsCustom(ItemsCustom itemsCustom) {
this.itemsCustom = itemsCustom;
}
@Override
public String toString() {
return "ItemsQueryVo [items=" + items + ", itemsCustom=" + itemsCustom + "]";
}
}
JSP 代码:
<form name="itemsForm"
action="${pageContext.request.contextPath }/items/queryItems.action"
method="post">
查询条件:
<table width="100%" border=1>
<tr>
<td>
商品名称:<input name="itemsCustom.name" type="text" /><br>
商品描述:<input name="itemsCustom.detail" type="text" />
</td>
<td><input type="submit" value="查询" /> </td>
</tr>
</table>
</form>
后端代码:
@RequestMapping("/queryItems")
public String queryItems(ItemsQueryVo itemsQueryVo, Model model) throws Exception {
System.out.println("itemsQueryVo = " + itemsQueryVo);
//1.调用service 查找数据库的商品查询
List<ItemsCustom> itemsList = itemService.findItemsList(null);
model.addAttribute("itemsList", itemsList);
return "itemsList";
}
4. 集合类型的参数绑定
常用的集合有数组类型,List 类型、Map 类型。
4.1 数组类型参数绑定
页面定义多个 checkbox 选中后向 Controller 提交。
<input type="checkbox" name="item_id" value="1"/>
<input type="checkbox" name="item_id" value="2"/>
<input type="checkbox" name="item_id" value="3"/>
Controller代码
@RequestMapping("/queryItems")
public String queryItems(String[] items_id, Model model) throws Exception {
System.out.println("items_id = " + items_id);
//1.调用service 查找数据库的商品查询
List<ItemsCustom> itemsList = itemService.findItemsList(null);
model.addAttribute("itemsList", itemsList);
return "itemsList";
}
4.2 List 类型参数绑定
在 POJO 中定义一个 List 类型的成员变量,生成 get/set 方法。
public class ItemsCustom extends Items{
//这里添加扩展字段
private List<Items> itemss;
//get/set方法
}
在 Jsp 页面定义两个 input,注意 name 的命名,itemss为 POJO 的成员变两名,name为 Items 变量名。
商品List0:<input name="itemss[0].name" type="text" />
商品List1:<input name="itemss[1].name" type="text" />
在 Controller 中方法定义如下:
@RequestMapping("/queryItems")
public String queryItems(ItemsCustom itemsCustom, Model model) throws Exception {
System.out.println("itemsCustom = " + itemsCustom);
//1.调用service 查找数据库的商品查询
List<ItemsCustom> itemsList = itemService.findItemsList(null);
model.addAttribute("itemsList", itemsList);
return "itemsList";
}
4.3 Map 类型参数绑定
在 POJO 中定义一个 Map 类型的成员变量,生成 get/set 方法。
public class ItemsCustom extends Items{
//这里添加扩展字段
private Map<String, Object> map;
//get/set方法
}
在 Jsp 页面定义两个 input,注意 name 的命名,map 为成员变量名,name 和 price 对应 key ,其传入的值对应 value。
商品Map0:<input name="map['name']" type="text" />
商品Map1:<input name="map['price']" type="text" />
在 Controller 中方法定义如下:
@RequestMapping("/queryItems")
public String queryItems(ItemsCustom itemsCustom, Model model) throws Exception {
System.out.println("itemsCustom = " + itemsCustom);
//1.调用service 查找数据库的商品查询
List<ItemsCustom> itemsList = itemService.findItemsList(null);
model.addAttribute("itemsList", itemsList);
return "itemsList";
}
5. 自定义参数绑定实现日期(Date)类型的参数绑定
第一步是编写一个自定义的 Converter ,功能是将 String 类型转换为 Date 类型。
package com.ssm.controller.converter;
import java.text.SimpleDateFormat;
import java.util.Date;
import org.springframework.core.convert.converter.Converter;
public class CustomDateConverter implements Converter<String, Date> {
@Override
public Date convert(String source) {
try {
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
//转换成功,返回
return simpleDateFormat.parse(source);
} catch (Exception e) {
e.printStackTrace();
}
//不成功,返回null
return null;
}
}
第二步是在springmvc.xml 中进行配置:
<mvc:annotation-driven conversion-service="conversionService"></mvc:annotation-driven>
<!-- 自定义转换器 -->
<bean id="conversionService"
class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
<!-- 转换器 -->
<property name="converters">
<list>
<bean class="com.ssm.controller.converter.CustomDateConverter"/>
</list>
</property>
</bean>
JSP代码
创建时间:<input name="createtime" type="text" />
Controller代码
@RequestMapping("/queryItems")
public String queryItems(ItemsCustom itemsCustom, Model model) throws Exception {
System.out.println("itemsCustom = " + itemsCustom);
//1.调用service 查找数据库的商品查询
List<ItemsCustom> itemsList = itemService.findItemsList(null);
model.addAttribute("itemsList", itemsList);
return "itemsList";
}
四、Spring MVC 传参乱码解决
- Spring MVC post 请求乱码解决方法
在 web.xml 中增加下面代码即可。
<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>
</filter>
<filter-mapping>
<filter-name>CharacterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
- Spring MVC get 请求乱码解决
对于 GET 请求参数乱码可以是在 Tomcat 的配置文件 server.xml 中修改代码<Connector connectionTimeout="20000" port="8080" protocol="HTTP/1.1" redirectPort="8443"/>
,增加属性URIEncoding="utf-8"
,即:<Connector URIEncoding="utf-8" connectionTimeout="20000" port="8080" protocol="HTTP/1.1" redirectPort="8443"/>
。
还可以对参数进行重新编码String params new String(request.getParamter("params").getBytes("ISO8859-1"),"UTF-8");
等重新编码的方法。