“SpringMVC:注解开发”的版本间差异

来自Wikioe
跳到导航 跳到搜索
 
(未显示同一用户的27个中间版本)
第2行: 第2行:


== @RequestMapping 使用==
== @RequestMapping 使用==
通过RequestMapping注解可以定义不同的处理器映射规则。
在SpringMVC中,[[RequestDispatcher]](在Front Controller之下)这个servlet负责将进入的HTTP请求路由到控制器的处理方法,并通过RequestMapping注解指定请求与处理方法之间的映射关系。<br/>
@RequestMapping注解可以在Controller类及类中方法的级别上使用。
* '''<syntaxhighlight lang="java" inline>@RestController</syntaxhighlight>=<syntaxhighlight lang="java" inline>@Controller</syntaxhighlight>+<syntaxhighlight lang="java" inline>@ResponseBody</syntaxhighlight>'''


=== URL路径映射 ===
=== URL路径映射 ===
第60行: 第62行:
=== 限定请求方法 ===
=== 限定请求方法 ===
出于安全性考虑,对http的链接进行方法限制。<br/>
出于安全性考虑,对http的链接进行方法限制。<br/>
* HTTP 请求的方法:<syntaxhighlight lang="java" inline>RequestMethod.GET</syntaxhighlight>、<syntaxhighlight lang="java" inline>RequestMethod.POST</syntaxhighlight>、<syntaxhighlight lang="java" inline>RequestMethod.DELETE</syntaxhighlight>、<syntaxhighlight lang="java" inline>RequestMethod.PUT</syntaxhighlight>、<syntaxhighlight lang="java" inline>RequestMethod.PATCH</syntaxhighlight>
<syntaxhighlight lang="java">
<syntaxhighlight lang="java">
//商品信息修改页面显示
//商品信息修改页面显示
第77行: 第81行:
[[File:RequestMapping请求限定.png|400px]]
[[File:RequestMapping请求限定.png|400px]]


=== @RequestParam 的RequestMapping ===
=== 带有@RequestParam的RequestMapping ===
//@RequestParam里边指定request传入参数名称和形参进行绑定。
@RequestParam注解配合@RequestMapping一起使用,可以将请求的参数同处理方法的参数绑定在一起。<br/>
//通过required属性指定参数是否必须要传入
@RequestParam 的使用:
//通过defaultValue可以设置默认值,如果id参数没有传入,将默认值和形参绑定。
# 通过在@RequestParam里边指定request传入参数名称和形参进行绑定;
#: <syntaxhighlight lang="java" inline>@RequestParam Integer items_id</syntaxhighlight>:传入参数、形参均为items_id;
#: <syntaxhighlight lang="java" inline>@RequestParam(value="id") Integer items_id</syntaxhighlight>:传入参数为id,形参为items_id;
# 通过required属性指定参数是否必须要传入;
#: <syntaxhighlight lang="java" inline>@RequestParam(value="id",required=true) Integer items_id</syntaxhighlight>
# 通过defaultValue可以设置默认值,如果形参没有传入,将默认值和形参绑定;
#: <syntaxhighlight lang="java" inline>@RequestParam(value="id",required=true,defaultValue="10001") Integer items_id</syntaxhighlight>
<syntaxhighlight lang="java">
<syntaxhighlight lang="java">
//商品信息修改页面显示
//商品信息修改页面显示
第93行: 第103行:
return "items/editItems";
return "items/editItems";
}
</syntaxhighlight>
=== 处理生产和消费对象 ===
可以使用@RequestMapping注解的<syntaxhighlight lang="java" inline>produces</syntaxhighlight>和<syntaxhighlight lang="java" inline>consumes</syntaxhighlight>这两个元素来缩小请求映射类型的范围。
# 用@RequestMapping的<syntaxhighlight lang="java" inline>produces</syntaxhighlight>元素结合<syntaxhighlight lang="java" inline>@ResponseBody</syntaxhighlight>注解,来请求的媒体类型产生对象;
# 用@RequestMapping的<syntaxhighlight lang="java" inline>comsumes</syntaxhighlight>元素结合<syntaxhighlight lang="java" inline>@RequestBody</syntaxhighlight>注解,来请求的媒体类型消费对象;
如:
<syntaxhighlight lang="java">
@RestController
@RequestMapping("/home ")
public class IndexController {
    @RequestMapping(value = "/prod ", produces = {"application/JSON "})
    @ResponseBody
    String getProduces() {
        return "Produces attribute ";
    }
    @RequestMapping(value = "/cons ", consumes = {"application/JSON ","application/XML "})
    @RequestBody
    String getConsumes() {
        return "Consumes attribute ";
    }
}
</syntaxhighlight>
在这段代码中,getProduces()处理方法会产生一个JSON响应,getConsumes()处理方法可以同时处理请求中的JSON和XML内容。
=== 处理消息头 ===
@RequestMapping注解提供了<syntaxhighlight lang="java" inline>header</syntaxhighlight>元素来根据请求中的消息头内容缩小请求映射的范围。
指定消息头,如:
<syntaxhighlight lang="java">
@RestController
@RequestMapping("/home ")
public class IndexController {
    @RequestMapping(value = "/head ", headers = {"content-type=text/plain"})
    String post() {
        return "Mapping applied along with headers ";
    }
}
</syntaxhighlight>
如上代码段, @RequestMapping注解的headers属性将映射范围缩小到了post()方法,使post()只会处理url为“/home/head”并且content-type为“text/plain”的请求。<br/>
指定多个消息头,如:
<syntaxhighlight lang="java">
@RestController
@RequestMapping("/home ")
public class IndexController {
    @RequestMapping(value = "/head ", headers = {
        "content-type=text/plain ",
        "content-type=text/html "
    }) String post() {
        return "Mapping applied along with headers ";
    }
}
</syntaxhighlight>
如上代码段, post()会处理url为“/home/head”,并且content-type为“text/plain”和“text/html”的请求。<br/>
=== 处理请求参数 ===
@RequestMapping 直接的<syntaxhighlight lang="java" inline>params</syntaxhighlight>元素可以进一步帮助我们缩小请求映射的定位范围。使用<syntaxhighlight lang="java" inline>params</syntaxhighlight>元素,可以让多个处理方法处理params不一样的同一个URL请求。<br/>
如:
<syntaxhighlight lang="java">
@RestController
@RequestMapping("/home ")
public class IndexController {
   @RequestMapping(value = "/fetch", params = {"id=10"})
    String getParams(@RequestParam("personId") String id) {
        return "Fetched parameter using params attribute =  " + id;
    }
    @RequestMapping(value = "/fetch", params = {"personId=20"})
    String getParamsDiff(@RequestParam("personId") String id) {
        return "Fetched parameter using params attribute =  " + id;
    }
    @RequestMapping(value = "/fetch", params = {"username","age!=10"})
    public String getParamsDifferent() {
        System.out.println("testParamsAndHeaders");
        return SUCCESS;
    }
}
</syntaxhighlight>
如上代码段,getParams() 和 getParamsDifferent() 两个方法都能处理相同的一个 URL (“/home/fetch”) ,但是会根据 params 元素的配置不同而决定具体来执行哪一个方法:
# URL 为“/home/fetch?id=10”时,getParams() 会执行;
# URL 为“/home/fetch?personId=20”时,getParamsDiff() 会执行;
# URL 包含时“username”和“age”,且“age”不等于“10”时(如“/home/fetch?username=ejiux&age=26”),getParamsDifferent() 会执行;
=== 处理动态URI ===
@RequestMapping 注解可以同<syntaxhighlight lang="java" inline>@PathVaraible</syntaxhighlight>注解一起使用,用来处理动态的 URI,URI 的值可以作为控制器中处理方法的参数。<br/>
* 可以使用正则表达式,以只处理匹配到的动态URI。
* @PathVariable 同 @RequestParam的运行方式不同。使用 @PathVariable 是为了从 URI 里取到查询参数值,而使用 @RequestParam 是为了从 URI 模板中获取参数值。
<syntaxhighlight lang="java">
@RestController
@RequestMapping("/home ")
public class IndexController {
    @RequestMapping(value = "/fetch/{id} ", method = RequestMethod.GET)
    String getDynamicUriValue(@PathVariable String id) {
        System.out.println("ID is  " + id);
        return "Dynamic URI parameter fetched ";
    }
    @RequestMapping(value = "/fetch/{id:[a-z]+}/{name} ", method = RequestMethod.GET)
    String getDynamicUriValueRegex(@PathVariable("name") String name) {
        System.out.println("Name is  " + name);
        return "Dynamic URI parameter fetched using regex ";
    }
}
</syntaxhighlight>
如上代码段:
# 方法 getDynamicUriValue() 会在“localhost:8080/home/fetch/10”的请求时执行;
# 方法 getDynamicUriValueRegex() 会在“localhost:8080/home/fetch/category/shirt”的请求时执行;
# 如果请求是“/home/fetch/10/shirt”,则会抛出异常,因为这个URI并不能匹配正则表达式;
=== 默认的处理方法 ===
在Controller中可以有一个默认的处理方法,它在发起请求默认 URI 时被执行。<br/>
如:
<syntaxhighlight lang="java">
@RestController
@RequestMapping("/home")
public class IndexController {
    @RequestMapping()
    String
    default () {
        return "This is a default method for the class ";
    }
}
</syntaxhighlight>
如上代码段,发起请求“/home”将会由 default() 来处理,因为方法的 @RequestMapping 注解并没有指定任何值。
=== 快捷方式(组合注解) ===
Spring 4.3 引入了方法级注解的变体,也被叫做 @RequestMapping 的'''组合注解''',组合注解可以更好的表达被注解方法的语义。它们所扮演的角色就是针对 @RequestMapping 的封装,而且成了定义端点的标准方法。<br/>
方法级别的注解变体,如:
# GetMapping :相当于 @RequestMapping(method =RequestMethod.GET) 的一个快捷方式;
# PostMapping :...;
# PutMapping :...;
# DeleteMapping :...;
# PatchMapping :...;
* 每个变体都可以使用带有方法属性的 @RequestMapping 注解来互换实现。
组合注解的使用如下:
<syntaxhighlight lang="java">
@RestController
@RequestMapping("/home")
public class IndexController {
    @GetMapping("/person")
    public @ResponseBody ResponseEntity < String > getPerson() {
        return new ResponseEntity < String > ("Response from GET", HttpStatus.OK);
    }
    @GetMapping("/person/{id}")
    public @ResponseBody ResponseEntity < String > getPersonById(@PathVariable String id) {
        return new ResponseEntity < String > ("Response from GET with id " + id, HttpStatus.OK);
    }
    @PostMapping("/person")
    public @ResponseBody ResponseEntity < String > postPerson() {
        return new ResponseEntity < String > ("Response from POST method", HttpStatus.OK);
    }
    @PutMapping("/person")
    public @ResponseBody ResponseEntity < String > putPerson() {
        return new ResponseEntity < String > ("Response from PUT method", HttpStatus.OK);
    }
    @DeleteMapping("/person")
    public @ResponseBody ResponseEntity < String > deletePerson() {
        return new ResponseEntity < String > ("Response from DELETE method", HttpStatus.OK);
    }
    @PatchMapping("/person")
    public @ResponseBody ResponseEntity < String > patchPerson() {
        return new ResponseEntity < String > ("Response from PATCH method", HttpStatus.OK);
    }
}
}
</syntaxhighlight>
</syntaxhighlight>
第98行: 第270行:
== Handler方法返回值 ==
== Handler方法返回值 ==
=== ModelAndView ===
=== ModelAndView ===
controller方法中定义<syntaxhighlight lang="java" inline>ModelAndView</syntaxhighlight>对象并返回,对象中可添加'''model'''数据、指定'''view'''。
<syntaxhighlight lang="java">
@RequestMapping("/queryItems")
public ModelAndView queryItems(HttpServletRequest request) throws Exception {
List<ItemsCustom> itemsList = itemsService.findItemsList(null);
ModelAndView modelAndView = new ModelAndView();
modelAndView.addObject("itemsList", itemsList);
modelAndView.setViewName("items/itemsList");
return modelAndView;
}
</syntaxhighlight>
itemsList页面代码如:
<syntaxhighlight lang="jsp">
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>查询商品列表</title>
</head>
<body>
<form
action="${pageContext.request.contextPath }/items/queryItems.action"
method="post">
查询条件:
<table width="100%" border=1>
<tr>
<td><input type="submit" value="查询" /></td>
</tr>
</table>
商品列表:
<table width="100%" border=1>
<tr>
<td>商品名称</td>
<td>商品价格</td>
<td>生产日期</td>
<td>商品描述</td>
<td>操作</td>
</tr>
<c:forEach items="${itemsList }" var="item">
<tr>
<td>${item.name }</td>
<td>${item.price }</td>
<td><fmt:formatDate value="${item.createtime}"
pattern="yyyy-MM-dd HH:mm:ss" /></td>
<td>${item.detail }</td>
<td><a href="${pageContext.request.contextPath }/items/editItems.action?id=${item.id}">修改</a></td>
</tr>
</c:forEach>
</table>
</form>
</body>
</html>
</syntaxhighlight>
=== void ===
=== void ===
在controller方法形参上可以定义<syntaxhighlight lang="java" inline>request</syntaxhighlight>和<syntaxhighlight lang="java" inline>response</syntaxhighlight>,使用request或response指定响应结果:
# 使用request转向页面,如:
#: <syntaxhighlight lang="java" inline>request.getRequestDispatcher("页面路径").forward(request, response);</syntaxhighlight>
# 通过response页面重定向:
#: <syntaxhighlight lang="java" inline>response.sendRedirect("url")</syntaxhighlight>
# 通过response指定响应结果,例如响应json数据如下:
#: <syntaxhighlight lang="java" inline>response.setCharacterEncoding("utf-8");</syntaxhighlight>
#: <syntaxhighlight lang="java" inline>response.setContentType("application/json;charset=utf-8");</syntaxhighlight>
#: <syntaxhighlight lang="java" inline>response.getWriter().write("json串");</syntaxhighlight>
=== 字符串 ===
=== 字符串 ===
Handler方法返回字符串内容,可以用作指定逻辑视图、转发或重定向,如:
<syntaxhighlight lang="java">
@RequestMapping("/editItemsSubmit")
public String editItemsSubmit(HttpServletRequest request,Integer id,ItemsCustom itemsCustom)throws Exception {
//调用service更新商品信息,页面需要将商品信息传到此方法
itemsService.updateItems(id, itemsCustom);
//重定向到商品查询列表
//return "redirect:queryItems.action";
//页面转发
//return "forward:queryItems.action";
//转到"items/editItems"页面
// return "items/editItems";
return "success";
}
</syntaxhighlight>
==== 逻辑视图名 ====
==== 逻辑视图名 ====
controller方法返回字符串可以指定逻辑视图名,通过视图解析器解析为物理视图地址。<br/>
如:<syntaxhighlight lang="java" inline>return "items/editItems";</syntaxhighlight>,经过视图解析器解析为jsp物理路径:“/WEB-INF/jsp/item/editItem.jsp”。
==== Redirect重定向 ====
==== Redirect重定向 ====
Contrller方法返回结果重定向到一个url地址。<br/>
如:<syntaxhighlight lang="java" inline>return "redirect:queryItem.action";</syntaxhighlight>,重定向到“queryItem.action”地址(request无法带过去)。
* redirect方式相当于“response.sendRedirect()”,转发后浏览器的'''地址栏变为转发后的地址'''。
* 转发即'''执行了一个新的request和response''',原来的参数在转发时就不能传递到下一个url,如果要传参数可以在url后边加参数,如:“redirect:queryItem?...&…..”。
==== forward转发 ====
==== forward转发 ====
controller方法执行后继续执行另一个controller方法。<br/>
如:<syntaxhighlight lang="java" inline>return "forward:editItem.action";</syntaxhighlight>,结果转发到“editItem.action”(request可以带过去)。
* forward方式相当于“request.getRequestDispatcher().forward(request,response)”,转发后浏览器'''地址栏还是原来的地址'''。
* 转发并没有执行新的request和response,而是和转发前的请求'''共用一个request和response'''。所以转发前请求的参数在转发后仍然可以读取到。


== 参数绑定 ==
== 参数绑定 ==
参数绑定:即处理器适配器HandlerAdapter在执行Handler之前需要把http请求的key/value数据绑定到Handler方法形参数上。<br/>
早期springmvc采用PropertyEditor(属性编辑器)进行参数绑定将request请求的参数绑定到方法形参上,3.X之后springmvc就开始使用Converter进行参数绑定。
=== 默认支持的参数类型 ===
=== 默认支持的参数类型 ===
处理器形参中添加如下类型的参数处理适配器会默认识别并进行赋值:
# '''HttpServletRequest''':通过request对象获取请求信息;
# '''HttpServletResponse''':通过response处理响应信息;
# '''HttpSession''':通过session对象得到session中存放的对象;
# '''Model/ModelMap''':<syntaxhighlight lang="java" inline>Model</syntaxhighlight>是一个接口,<syntaxhighlight lang="java" inline>ModelMap</syntaxhighlight>是其实现类,其作用是通过Model或ModelMap将数据填充到request域,以向页面传递数据,如:
#: <syntaxhighlight lang="java">
@RequestMapping(value="/editItems",method={RequestMethod.POST,RequestMethod.GET})
public String editItems(Model model,@RequestParam(value="id",required=true) Integer items_id)throws Exception {
ItemsCustom itemsCustom = itemsService.findItemsById(items_id);
//通过形参中的model将model数据传到页面
//相当于modelAndView.addObject方法
model.addAttribute("itemsCustom", itemsCustom);
return "items/editItems";
}
</syntaxhighlight>
## 页面通过<syntaxhighlight lang="java" inline>${itemsCustom.XXXX}</syntaxhighlight>获取item对象的属性值。
## 使用Model和ModelMap的效果一样,如果直接使用Model,springmvc会实例化ModelMap。
=== 简单类型 ===
=== 简单类型 ===
* 不使用@RequestParam,要求request传入参数名称和 Handler方法的形参名称一致,方可绑定成功。
* 使用@RequestParam,不用限制request传入参数名称和 Handler方法的形参名称一致。
{| class="wikitable"
|-
! 类型 !! 示例
|-
| '''Integer'''
|
# Handler方法:
#: <syntaxhighlight lang="java" inline>public String editItem(Model model, Integer id) throws Exception{}</syntaxhighlight>
# 请求url:
#: <syntaxhighlight lang="java" inline>http://localhost:8080/springmvc_mybatis/item/editItem.action?id=1001</syntaxhighlight>
|-
| '''String'''
|
# Handler方法:
#: <syntaxhighlight lang="java" inline>public String editItem(Model model, Integer id, String name) throws Exception {}</syntaxhighlight>
# 请求url:
#: <syntaxhighlight lang="java" inline>http://localhost:8080/springmvc_mybatis/item/editItem.action?id=1001&name=eijux</syntaxhighlight>
|-
| '''Float/Double'''
|
# Handler方法:
#: <syntaxhighlight lang="java" inline>public String editItem(Model model, Integer id, Float price) throws Exception {}</syntaxhighlight>
# 请求url:
#: <syntaxhighlight lang="java" inline>http://localhost:8080/springmvc_mybatis/item/editItem.action?id=1001&price=10.28</syntaxhighlight>
|-
| '''Booblean'''
|
# Handler方法:
#: <syntaxhighlight lang="java" inline>public String editItem(Model model, Integer id, Boolean status) throws Exception {}</syntaxhighlight>
# 请求url:
#: <syntaxhighlight lang="java" inline>http://localhost:8080/springmvc_mybatis/item/editItem.action?id=1001&status=false</syntaxhighlight>
|-
| '''@RequestParam'''
|
# Handler方法:
#: <syntaxhighlight lang="java" inline>public String editItems(Model model,@RequestParam(value="id",required=true,defaultValue="1001") Integer items_id)throws Exception {}</syntaxhighlight>
# 请求url:
#: <syntaxhighlight lang="java" inline>http://localhost:8080/springmvc_mybatis/item/editItem.action?id=1002</syntaxhighlight>
* 参见:[[#带有@RequestParam的RequestMapping]]
|}
=== pojo ===
=== pojo ===
==== 简单pojo ====
请求的参数名称和pojo的属性名称一致,会自动将请求参数赋值给pojo的属性。<br/>
如:
# View:(请求的参数name与pojo属性名称对应,“http://localhost:8080/springmvc_mybatis/item/editItemSubmit.action?name=eijux&price=10.28”)
#: <syntaxhighlight lang="java">
...
    <input type="text" name="name"/>
    <input type="text" name="price"/>
...
</syntaxhighlight>
# Handler:(形参为pojo)
#: <syntaxhighlight lang="java">
@RequestMapping("/editItemSubmit")
public String editItemSubmit(Model model,Items items)throws Exception{
...
}
</syntaxhighlight>
# pojo:
#: <syntaxhighlight lang="java">
public class Items {
    private Integer id;
    private String name;
   private Float price;
...
}
</syntaxhighlight>
==== 包装pojo ====
如果采用类似struts中“对象.属性”的方式命名,需要将pojo对象作为一个包装对象的属性,而action中以该包装对象作为形参。<br/>
如:
# View:(请求的参数name与“Vo对象的pojo属性.pojo的属性名称”对应)
#: <syntaxhighlight lang="java">
...
    <input type="text" name="items.name"/>
    <input type="text" name="items.price"/>
...
</syntaxhighlight>
# Handler:(形参为Vo)
#: <syntaxhighlight lang="java">
@RequestMapping("/editItemSubmit")
public String editItemSubmit(Model model,QueryVo queryVo)throws Exception{
...
}
</syntaxhighlight>
# Vo:
#: <syntaxhighlight lang="java">
Public class QueryVo {
    private Items items;
...
}
</syntaxhighlight>
# pojo:
#: <syntaxhighlight lang="java">
public class Items {
    private Integer id;
    private String name;
   private Float price;
...
}
</syntaxhighlight>
=== 自定义参数绑定 ===
==== 自定义Converter ====
自定义Converter类必须实现Converter接口:
<syntaxhighlight lang="java">
package org.springframework.core.convert.converter;
public interface Converter<S, T> {
T convert(S var1);
}
</syntaxhighlight>
如,自定义日期格式进行参数绑定:
<syntaxhighlight lang="java">
package cn.itcast.ssm.controller.converter;
import java.text.ParseException;
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) {
//实现 将日期串转成日期类型(格式是yyyy-MM-dd HH:mm:ss)
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
try {
//转成直接返回
return simpleDateFormat.parse(source);
} catch (ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//如果参数绑定失败返回null
return null;
}
}
</syntaxhighlight>
==== 配置Converter ====
{| class="wikitable" style="width: 100%;"
|+ Converter配置
! style="width:50%;"| 使用<mvc:annotation-driven>
! style="width:50%;"| 使用HandlerAdapter
|- style="vertical-align:top;"
|
<syntaxhighlight lang="xml">
<mvc:annotation-driven conversion-service="conversionService"></mvc:annotation-driven>
</syntaxhighlight>
|
<syntaxhighlight lang="xml">
<!-- 注解适配器 -->
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
<property name="webBindingInitializer" ref="customBinder"></property>
</bean>
<!-- 自定义webBinder -->
<bean id="customBinder" class="org.springframework.web.bind.support.ConfigurableWebBindingInitializer">
<property name="conversionService" ref="conversionService" />
</bean>
</syntaxhighlight>
|-
| colspan="2" | <syntaxhighlight lang="xml">
<!-- conversionService -->
<bean id="conversionService" class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
<!-- converters -->
<property name="converters">
<list>
<bean class="cn.itcast.ssm.controller.converter.CustomDateConverter"/>
</list>
</property>
</bean>
</syntaxhighlight>
|}
=== 集合 ===
=== 集合 ===
=== 自定义参数绑定 ===
==== 字符串数组 ====
参数为字符串数组时,Handlder中需使用数组接受参数。<br/>
如:
# View:页面选中多个checkbox向Handler方法传递参数
#: <syntaxhighlight lang="java">
...
    <input type="checkbox" name="item_id" value="001"/>
    <input type="checkbox" name="item_id" value="002"/>
    <input type="checkbox" name="item_id" value="002"/>
...
</syntaxhighlight>
# Handler:Controller方法中可以用String[]接收
#: <syntaxhighlight lang="java">
@RequestMapping("/deleteitem")
public String deleteitem(String[] item_id)throws Exception{
    System.out.println(item_id);
...
}
</syntaxhighlight>
 
==== List ====
List中存放对象,并将定义的List放在包装类中,action使用包装对象接收。<br/>
如:
# View:
## 静态代码:
##: <syntaxhighlight lang="java">
...
<tr>
<td>
<input type="text" name="itemsList[0].id" value="${item.id}"/>
</td>
<td>
<input type="text" name="itemsList[0].name" value="${item.name}"/>
</td>
<td>
<input type="text" name="itemsList[0].price" value="${item.price}"/>
</td>
</tr>
<tr>
<td>
<input type="text" name="itemsList[1].id" value="${item.id}"/>
</td>
<td>
<input type="text" name="itemsList[1].name" value="${item.name}"/>
</td>
<td>
<input type="text" name="itemsList[1].price" value="${item.price}"/>
</td>
</tr>
...
</syntaxhighlight>
## 动态代码:
##: <syntaxhighlight lang="java">
...
<c:forEach items="${itemsList}" var="item" varStatus="s">
<tr>
<td><input type="text" name="itemsList[${s.index}].id" value="${item.id}"/></td>
<td><input type="text" name="itemsList[${s.index}].name" value="${item.name}"/></td>
<td><input type="text" name="itemsList[${s.index}].price" value="${item.price}"/></td>
</tr>
</c:forEach>
...
</syntaxhighlight>
# Handler:(形参为pojo)
#: <syntaxhighlight lang="java">
@RequestMapping("/editItemSubmit")
public String editItemSubmit(Model model,QueryVo queryVo)throws Exception{
System.out.println(queryVo.getItemList());
...
}
</syntaxhighlight>
# QueryVo:
#: <syntaxhighlight lang="java">
Public class QueryVo {
//商品列表
Private List<Items> itemList;
 
//get
...
//set
...
}
</syntaxhighlight>
# pojo:(略)
 
==== Map ====
将Map对象放在包装类中,并添加get/set方法,action使用包装对象接收。(类似于List)<br/>
如:
# View:
#: <syntaxhighlight lang="java">
...
<tr>
<td><input type="text" name="itemInfo['name']"/></td>
<td><input type="text" name="itemInfo['price']"/></td>
</tr>
...
</syntaxhighlight>
# Handler:(形参为pojo)
#: <syntaxhighlight lang="java">
@RequestMapping("/editItemSubmit")
public String editItemSubmit(Model model,QueryVo queryVo)throws Exception{
System.out.println(queryVo.getItemInfo());
...
}
</syntaxhighlight>
# QueryVo:
#: <syntaxhighlight lang="java">
Public class QueryVo {
private Map<String, Object> itemInfo = new HashMap<String, Object>();


== 示例代码 ==
//get
=== 需求 ===
...
=== dao ===
//set
=== service ===
...
=== controller ===
}
=== 页面 ===
</syntaxhighlight>
# pojo:(略)

2022年12月14日 (三) 20:35的最新版本


@RequestMapping 使用

在SpringMVC中,RequestDispatcher(在Front Controller之下)这个servlet负责将进入的HTTP请求路由到控制器的处理方法,并通过RequestMapping注解指定请求与处理方法之间的映射关系。
@RequestMapping注解可以在Controller类及类中方法的级别上使用。

  • @RestController=@Controller+@ResponseBody

URL路径映射

@RequestMapping(value="/item")@RequestMapping("/item") value的值是数组,可以将多个url映射到同一个方法,如:

@RestController
@RequestMapping("/home ")
public class IndexController {

    @RequestMapping(value = {
        " ",
        "/page ",
        "page* ",
        "view/*,**/msg "
    })
    String indexMultipleMapping() {
        return "Hello from index multiple mapping. ";
    }
}

如下的这些 URL 都会由 indexMultipleMapping() 来处理:

  • localhost:8080/home
  • localhost:8080/home/
  • localhost:8080/home/page
  • localhost:8080/home/pageabc
  • localhost:8080/home/view/
  • localhost:8080/home/view/view

窄化请求映射

在class上添加@RequestMapping(url)指定通用请求前缀, 限制此类下的所有方法请求url必须以请求前缀开头,通过此方法对url进行分类管理。

@Controller
@RequestMapping("/items")
public class ItemsController {

	@Autowired
	private ItemsService itemsService;

	// 商品查询
	@RequestMapping("/queryItems")
	public ModelAndView queryItems(HttpServletRequest request) throws Exception {

		List<ItemsCustom> itemsList = itemsService.findItemsList(null);
		
		ModelAndView modelAndView = new ModelAndView();
		modelAndView.addObject("itemsList", itemsList);
		modelAndView.setViewName("items/itemsList");

		return modelAndView;
	}
...
}

商品列表请求路径为:“/items/queryItems.action”。

限定请求方法

出于安全性考虑,对http的链接进行方法限制。

  • HTTP 请求的方法:RequestMethod.GETRequestMethod.POSTRequestMethod.DELETERequestMethod.PUTRequestMethod.PATCH
//商品信息修改页面显示
@RequestMapping(value="/editItems",method={RequestMethod.POST,RequestMethod.GET})
public ModelAndView editItems()throws Exception {
	
	ItemsCustom itemsCustom = itemsService.findItemsById(1);
	
	ModelAndView modelAndView = new ModelAndView();
	modelAndView.addObject("itemsCustom", itemsCustom);
	modelAndView.setViewName("items/editItems");
	
	return modelAndView;
}

如果限制请求为post方法(method={RequestMethod.GET}),进行get请求,报错: RequestMapping请求限定.png

带有@RequestParam的RequestMapping

@RequestParam注解配合@RequestMapping一起使用,可以将请求的参数同处理方法的参数绑定在一起。
@RequestParam 的使用:

  1. 通过在@RequestParam里边指定request传入参数名称和形参进行绑定;
    @RequestParam Integer items_id:传入参数、形参均为items_id;
    @RequestParam(value="id") Integer items_id:传入参数为id,形参为items_id;
  2. 通过required属性指定参数是否必须要传入;
    @RequestParam(value="id",required=true) Integer items_id
  3. 通过defaultValue可以设置默认值,如果形参没有传入,将默认值和形参绑定;
    @RequestParam(value="id",required=true,defaultValue="10001") Integer items_id
//商品信息修改页面显示
@RequestMapping(value="/editItems",method={RequestMethod.POST,RequestMethod.GET})
public String editItems(Model model,@RequestParam(value="id",required=true) Integer items_id)throws Exception {
	
	ItemsCustom itemsCustom = itemsService.findItemsById(items_id);
	
	//通过形参中的model将model数据传到页面
	//相当于modelAndView.addObject方法
	model.addAttribute("itemsCustom", itemsCustom);
	
	return "items/editItems";
}

处理生产和消费对象

可以使用@RequestMapping注解的producesconsumes这两个元素来缩小请求映射类型的范围。

  1. 用@RequestMapping的produces元素结合@ResponseBody注解,来请求的媒体类型产生对象;
  2. 用@RequestMapping的comsumes元素结合@RequestBody注解,来请求的媒体类型消费对象;

如:

@RestController
@RequestMapping("/home ")
public class IndexController {
    @RequestMapping(value = "/prod ", produces = {"application/JSON "})
    @ResponseBody
    String getProduces() {
        return "Produces attribute ";
    }

    @RequestMapping(value = "/cons ", consumes = {"application/JSON ","application/XML "})
    @RequestBody
    String getConsumes() {
        return "Consumes attribute ";
    }
}

在这段代码中,getProduces()处理方法会产生一个JSON响应,getConsumes()处理方法可以同时处理请求中的JSON和XML内容。

处理消息头

@RequestMapping注解提供了header元素来根据请求中的消息头内容缩小请求映射的范围。 指定消息头,如:

@RestController
@RequestMapping("/home ")
public class IndexController {
    @RequestMapping(value = "/head ", headers = {"content-type=text/plain"})
    String post() {
        return "Mapping applied along with headers ";
    }
}

如上代码段, @RequestMapping注解的headers属性将映射范围缩小到了post()方法,使post()只会处理url为“/home/head”并且content-type为“text/plain”的请求。
指定多个消息头,如:

@RestController
@RequestMapping("/home ")
public class IndexController {
    @RequestMapping(value = "/head ", headers = {
        "content-type=text/plain ",
        "content-type=text/html "
    }) String post() {
        return "Mapping applied along with headers ";
    }
}

如上代码段, post()会处理url为“/home/head”,并且content-type为“text/plain”和“text/html”的请求。

处理请求参数

@RequestMapping 直接的params元素可以进一步帮助我们缩小请求映射的定位范围。使用params元素,可以让多个处理方法处理params不一样的同一个URL请求。
如:

@RestController
@RequestMapping("/home ")
public class IndexController {
    @RequestMapping(value = "/fetch", params = {"id=10"})
    String getParams(@RequestParam("personId") String id) {
        return "Fetched parameter using params attribute =  " + id;
    }
    @RequestMapping(value = "/fetch", params = {"personId=20"})
    String getParamsDiff(@RequestParam("personId") String id) {
        return "Fetched parameter using params attribute =  " + id;
    }
    @RequestMapping(value = "/fetch", params = {"username","age!=10"})
    public String getParamsDifferent() {
        System.out.println("testParamsAndHeaders");
        return SUCCESS;
    }
}

如上代码段,getParams() 和 getParamsDifferent() 两个方法都能处理相同的一个 URL (“/home/fetch”) ,但是会根据 params 元素的配置不同而决定具体来执行哪一个方法:

  1. URL 为“/home/fetch?id=10”时,getParams() 会执行;
  2. URL 为“/home/fetch?personId=20”时,getParamsDiff() 会执行;
  3. URL 包含时“username”和“age”,且“age”不等于“10”时(如“/home/fetch?username=ejiux&age=26”),getParamsDifferent() 会执行;

处理动态URI

@RequestMapping 注解可以同@PathVaraible注解一起使用,用来处理动态的 URI,URI 的值可以作为控制器中处理方法的参数。

  • 可以使用正则表达式,以只处理匹配到的动态URI。
  • @PathVariable 同 @RequestParam的运行方式不同。使用 @PathVariable 是为了从 URI 里取到查询参数值,而使用 @RequestParam 是为了从 URI 模板中获取参数值。
@RestController
@RequestMapping("/home ")
public class IndexController {
    @RequestMapping(value = "/fetch/{id} ", method = RequestMethod.GET)
    String getDynamicUriValue(@PathVariable String id) {
        System.out.println("ID is  " + id);
        return "Dynamic URI parameter fetched ";
    }
    @RequestMapping(value = "/fetch/{id:[a-z]+}/{name} ", method = RequestMethod.GET)
    String getDynamicUriValueRegex(@PathVariable("name") String name) {
        System.out.println("Name is  " + name);
        return "Dynamic URI parameter fetched using regex ";
    }
}

如上代码段:

  1. 方法 getDynamicUriValue() 会在“localhost:8080/home/fetch/10”的请求时执行;
  2. 方法 getDynamicUriValueRegex() 会在“localhost:8080/home/fetch/category/shirt”的请求时执行;
  3. 如果请求是“/home/fetch/10/shirt”,则会抛出异常,因为这个URI并不能匹配正则表达式;

默认的处理方法

在Controller中可以有一个默认的处理方法,它在发起请求默认 URI 时被执行。
如:

@RestController
@RequestMapping("/home")
public class IndexController {
    @RequestMapping()
    String
    default () {
        return "This is a default method for the class ";
    }
}

如上代码段,发起请求“/home”将会由 default() 来处理,因为方法的 @RequestMapping 注解并没有指定任何值。

快捷方式(组合注解)

Spring 4.3 引入了方法级注解的变体,也被叫做 @RequestMapping 的组合注解,组合注解可以更好的表达被注解方法的语义。它们所扮演的角色就是针对 @RequestMapping 的封装,而且成了定义端点的标准方法。
方法级别的注解变体,如:

  1. GetMapping :相当于 @RequestMapping(method =RequestMethod.GET) 的一个快捷方式;
  2. PostMapping :...;
  3. PutMapping :...;
  4. DeleteMapping :...;
  5. PatchMapping :...;
  • 每个变体都可以使用带有方法属性的 @RequestMapping 注解来互换实现。

组合注解的使用如下:

@RestController
@RequestMapping("/home")
public class IndexController {
    @GetMapping("/person")
    public @ResponseBody ResponseEntity < String > getPerson() {
        return new ResponseEntity < String > ("Response from GET", HttpStatus.OK);
    }
    @GetMapping("/person/{id}")
    public @ResponseBody ResponseEntity < String > getPersonById(@PathVariable String id) {
        return new ResponseEntity < String > ("Response from GET with id " + id, HttpStatus.OK);
    }
    @PostMapping("/person")
    public @ResponseBody ResponseEntity < String > postPerson() {
        return new ResponseEntity < String > ("Response from POST method", HttpStatus.OK);
    }
    @PutMapping("/person")
    public @ResponseBody ResponseEntity < String > putPerson() {
        return new ResponseEntity < String > ("Response from PUT method", HttpStatus.OK);
    }
    @DeleteMapping("/person")
    public @ResponseBody ResponseEntity < String > deletePerson() {
        return new ResponseEntity < String > ("Response from DELETE method", HttpStatus.OK);
    }
    @PatchMapping("/person")
    public @ResponseBody ResponseEntity < String > patchPerson() {
        return new ResponseEntity < String > ("Response from PATCH method", HttpStatus.OK);
    }
}

Handler方法返回值

ModelAndView

controller方法中定义ModelAndView对象并返回,对象中可添加model数据、指定view

@RequestMapping("/queryItems")
public ModelAndView queryItems(HttpServletRequest request) throws Exception {

	List<ItemsCustom> itemsList = itemsService.findItemsList(null);
	
	ModelAndView modelAndView = new ModelAndView();
	modelAndView.addObject("itemsList", itemsList);
	modelAndView.setViewName("items/itemsList");

	return modelAndView;

}

itemsList页面代码如:

<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>查询商品列表</title>
</head>
<body>
	<form
		action="${pageContext.request.contextPath }/items/queryItems.action"
		method="post">
		查询条件:
		<table width="100%" border=1>
			<tr>
				<td><input type="submit" value="查询" /></td>
			</tr>
		</table>
		商品列表:
		<table width="100%" border=1>
			<tr>
				<td>商品名称</td>
				<td>商品价格</td>
				<td>生产日期</td>
				<td>商品描述</td>
				<td>操作</td>
			</tr>
			<c:forEach items="${itemsList }" var="item">
				<tr>
					<td>${item.name }</td>
					<td>${item.price }</td>
					<td><fmt:formatDate value="${item.createtime}"
							pattern="yyyy-MM-dd HH:mm:ss" /></td>
					<td>${item.detail }</td>

					<td><a href="${pageContext.request.contextPath }/items/editItems.action?id=${item.id}">修改</a></td>
				</tr>
			</c:forEach>

		</table>
	</form>
</body>
</html>

void

在controller方法形参上可以定义requestresponse,使用request或response指定响应结果:

  1. 使用request转向页面,如:
    request.getRequestDispatcher("页面路径").forward(request, response);
  2. 通过response页面重定向:
    response.sendRedirect("url")
  3. 通过response指定响应结果,例如响应json数据如下:
    response.setCharacterEncoding("utf-8");
    response.setContentType("application/json;charset=utf-8");
    response.getWriter().write("json串");

字符串

Handler方法返回字符串内容,可以用作指定逻辑视图、转发或重定向,如:

@RequestMapping("/editItemsSubmit")
public String editItemsSubmit(HttpServletRequest request,Integer id,ItemsCustom itemsCustom)throws Exception {
	
	//调用service更新商品信息,页面需要将商品信息传到此方法
	itemsService.updateItems(id, itemsCustom);
	
	//重定向到商品查询列表
	//return "redirect:queryItems.action";
	//页面转发
	//return "forward:queryItems.action";
	//转到"items/editItems"页面
	// return "items/editItems";
	return "success";
}

逻辑视图名

controller方法返回字符串可以指定逻辑视图名,通过视图解析器解析为物理视图地址。
如:return "items/editItems";,经过视图解析器解析为jsp物理路径:“/WEB-INF/jsp/item/editItem.jsp”。

Redirect重定向

Contrller方法返回结果重定向到一个url地址。
如:return "redirect:queryItem.action";,重定向到“queryItem.action”地址(request无法带过去)。

  • redirect方式相当于“response.sendRedirect()”,转发后浏览器的地址栏变为转发后的地址
  • 转发即执行了一个新的request和response,原来的参数在转发时就不能传递到下一个url,如果要传参数可以在url后边加参数,如:“redirect:queryItem?...&…..”。

forward转发

controller方法执行后继续执行另一个controller方法。
如:return "forward:editItem.action";,结果转发到“editItem.action”(request可以带过去)。

  • forward方式相当于“request.getRequestDispatcher().forward(request,response)”,转发后浏览器地址栏还是原来的地址
  • 转发并没有执行新的request和response,而是和转发前的请求共用一个request和response。所以转发前请求的参数在转发后仍然可以读取到。

参数绑定

参数绑定:即处理器适配器HandlerAdapter在执行Handler之前需要把http请求的key/value数据绑定到Handler方法形参数上。
早期springmvc采用PropertyEditor(属性编辑器)进行参数绑定将request请求的参数绑定到方法形参上,3.X之后springmvc就开始使用Converter进行参数绑定。

默认支持的参数类型

处理器形参中添加如下类型的参数处理适配器会默认识别并进行赋值:

  1. HttpServletRequest:通过request对象获取请求信息;
  2. HttpServletResponse:通过response处理响应信息;
  3. HttpSession:通过session对象得到session中存放的对象;
  4. Model/ModelMapModel是一个接口,ModelMap是其实现类,其作用是通过Model或ModelMap将数据填充到request域,以向页面传递数据,如:
    @RequestMapping(value="/editItems",method={RequestMethod.POST,RequestMethod.GET})
    public String editItems(Model model,@RequestParam(value="id",required=true) Integer items_id)throws Exception {
    
    	ItemsCustom itemsCustom = itemsService.findItemsById(items_id);
    	
    	//通过形参中的model将model数据传到页面
    	//相当于modelAndView.addObject方法
    	model.addAttribute("itemsCustom", itemsCustom);
    	
    	return "items/editItems";
    }
    
    1. 页面通过${itemsCustom.XXXX}获取item对象的属性值。
    2. 使用Model和ModelMap的效果一样,如果直接使用Model,springmvc会实例化ModelMap。

简单类型

  • 不使用@RequestParam,要求request传入参数名称和 Handler方法的形参名称一致,方可绑定成功。
  • 使用@RequestParam,不用限制request传入参数名称和 Handler方法的形参名称一致。
类型 示例
Integer
  1. Handler方法:
    public String editItem(Model model, Integer id) throws Exception{}
  2. 请求url:
    http://localhost:8080/springmvc_mybatis/item/editItem.action?id=1001
String
  1. Handler方法:
    public String editItem(Model model, Integer id, String name) throws Exception {}
  2. 请求url:
    http://localhost:8080/springmvc_mybatis/item/editItem.action?id=1001&name=eijux
Float/Double
  1. Handler方法:
    public String editItem(Model model, Integer id, Float price) throws Exception {}
  2. 请求url:
    http://localhost:8080/springmvc_mybatis/item/editItem.action?id=1001&price=10.28
Booblean
  1. Handler方法:
    public String editItem(Model model, Integer id, Boolean status) throws Exception {}
  2. 请求url:
    http://localhost:8080/springmvc_mybatis/item/editItem.action?id=1001&status=false
@RequestParam
  1. Handler方法:
    public String editItems(Model model,@RequestParam(value="id",required=true,defaultValue="1001") Integer items_id)throws Exception {}
  2. 请求url:
    http://localhost:8080/springmvc_mybatis/item/editItem.action?id=1002

pojo

简单pojo

请求的参数名称和pojo的属性名称一致,会自动将请求参数赋值给pojo的属性。
如:

  1. View:(请求的参数name与pojo属性名称对应,“http://localhost:8080/springmvc_mybatis/item/editItemSubmit.action?name=eijux&price=10.28”)
    ...
        <input type="text" name="name"/>
        <input type="text" name="price"/>
    ...
    
  2. Handler:(形参为pojo)
    @RequestMapping("/editItemSubmit")
    public String editItemSubmit(Model model,Items items)throws Exception{
    ...
    }
    
  3. pojo:
    public class Items {
        private Integer id;
        private String name;
        private Float price;
    ...
    }
    

包装pojo

如果采用类似struts中“对象.属性”的方式命名,需要将pojo对象作为一个包装对象的属性,而action中以该包装对象作为形参。
如:

  1. View:(请求的参数name与“Vo对象的pojo属性.pojo的属性名称”对应)
    ...
        <input type="text" name="items.name"/>
        <input type="text" name="items.price"/>
    ...
    
  2. Handler:(形参为Vo)
    @RequestMapping("/editItemSubmit")
    public String editItemSubmit(Model model,QueryVo queryVo)throws Exception{
    ...
    }
    
  3. Vo:
    Public class QueryVo {
        private Items items;
    ...
    }
    
  4. pojo:
    public class Items {
        private Integer id;
        private String name;
        private Float price;
    ...
    }
    

自定义参数绑定

自定义Converter

自定义Converter类必须实现Converter接口:

package org.springframework.core.convert.converter;

public interface Converter<S, T> {
	T convert(S var1);
}

如,自定义日期格式进行参数绑定:

package cn.itcast.ssm.controller.converter;

import java.text.ParseException;
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) {
		
		//实现 将日期串转成日期类型(格式是yyyy-MM-dd HH:mm:ss)
		
		SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		
		try {
			//转成直接返回
			return simpleDateFormat.parse(source);
		} catch (ParseException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		//如果参数绑定失败返回null
		return null;
	}
}

配置Converter

Converter配置
使用<mvc:annotation-driven> 使用HandlerAdapter
<mvc:annotation-driven conversion-service="conversionService"></mvc:annotation-driven>
<!-- 注解适配器 -->
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
	 <property name="webBindingInitializer" ref="customBinder"></property> 
</bean>

<!-- 自定义webBinder -->
<bean id="customBinder" class="org.springframework.web.bind.support.ConfigurableWebBindingInitializer">
	<property name="conversionService" ref="conversionService" />
</bean>
<!-- conversionService -->
<bean id="conversionService" class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
	<!-- converters -->
	<property name="converters">
		<list>
			<bean class="cn.itcast.ssm.controller.converter.CustomDateConverter"/>
		</list>
	</property>
</bean>

集合

字符串数组

参数为字符串数组时,Handlder中需使用数组接受参数。
如:

  1. View:页面选中多个checkbox向Handler方法传递参数
    ...
        <input type="checkbox" name="item_id" value="001"/>
        <input type="checkbox" name="item_id" value="002"/>
        <input type="checkbox" name="item_id" value="002"/>
    ...
    
  2. Handler:Controller方法中可以用String[]接收
    @RequestMapping("/deleteitem")
    public String deleteitem(String[] item_id)throws Exception{
        System.out.println(item_id);
    ...
    }
    

List

List中存放对象,并将定义的List放在包装类中,action使用包装对象接收。
如:

  1. View:
    1. 静态代码:
      ...
      	<tr>
      		<td>
      			<input type="text" name="itemsList[0].id" value="${item.id}"/>
      		</td>
      		<td>
      			<input type="text" name="itemsList[0].name" value="${item.name}"/>
      		</td>
      		<td>
      			<input type="text" name="itemsList[0].price" value="${item.price}"/>
      		</td>
      	</tr>
      	<tr>
      		<td>
      			<input type="text" name="itemsList[1].id" value="${item.id}"/>
      		</td>
      		<td>
      			<input type="text" name="itemsList[1].name" value="${item.name}"/>
      		</td>
      		<td>
      			<input type="text" name="itemsList[1].price" value="${item.price}"/>
      		</td>
      	</tr>
      ...
      
    2. 动态代码:
      ...
      	<c:forEach items="${itemsList}" var="item" varStatus="s">
      	<tr>
      		<td><input type="text" name="itemsList[${s.index}].id" value="${item.id}"/></td>
      		<td><input type="text" name="itemsList[${s.index}].name" value="${item.name}"/></td>
      		<td><input type="text" name="itemsList[${s.index}].price" value="${item.price}"/></td>
      	</tr>
      	</c:forEach>
      ...
      
  2. Handler:(形参为pojo)
    @RequestMapping("/editItemSubmit")
    public String editItemSubmit(Model model,QueryVo queryVo)throws Exception{
    	System.out.println(queryVo.getItemList());
    ...
    }
    
  3. QueryVo:
    Public class QueryVo {
    	//商品列表
    	Private List<Items> itemList;
    
    	//get
    	...
    	//set
    	...
    }
    
  4. pojo:(略)

Map

将Map对象放在包装类中,并添加get/set方法,action使用包装对象接收。(类似于List)
如:

  1. View:
    ...
    	<tr>
    		<td><input type="text" name="itemInfo['name']"/></td>
    		<td><input type="text" name="itemInfo['price']"/></td>
    	</tr>
    ...
    
  2. Handler:(形参为pojo)
    @RequestMapping("/editItemSubmit")
    public String editItemSubmit(Model model,QueryVo queryVo)throws Exception{
    	System.out.println(queryVo.getItemInfo());
    ...
    }
    
  3. QueryVo:
    Public class QueryVo {
    	
    	private Map<String, Object> itemInfo = new HashMap<String, Object>();
    
    	//get
    	...
    	//set
    	...
    }
    
  4. pojo:(略)