7. 参数绑定
7.1. 参数绑定的过程
下表描述了支持的控制器方法参数
Controller method argument | Description |
---|---|
WebRequest , NativeWebRequest | Generic access to request parameters and request and session attributes, without direct use of the Servlet API. |
javax.servlet.ServletRequest , javax.servlet.ServletResponse | Choose any specific request or response type — for example, ServletRequest , HttpServletRequest , or Spring’s MultipartRequest , MultipartHttpServletRequest . |
javax.servlet.http.HttpSession | Enforces the presence of a session. As a consequence, such an argument is never null . Note that session access is not thread-safe. Consider setting the RequestMappingHandlerAdapter instance’s synchronizeOnSession flag to true if multiple requests are allowed to concurrently access a session. |
javax.servlet.http.PushBuilder | Servlet 4.0 push builder API for programmatic HTTP/2 resource pushes. Note that, per the Servlet specification, the injected PushBuilder instance can be null if the client does not support that HTTP/2 feature. |
java.security.Principal | Currently authenticated user — possibly a specific Principal implementation class if known.Note that this argument is not resolved eagerly, if it is annotated in order to allow a custom resolver to resolve it before falling back on default resolution via HttpServletRequest#getUserPrincipal . For example, the Spring Security Authentication implements Principal and would be injected as such via HttpServletRequest#getUserPrincipal , unless it is also annotated with @AuthenticationPrincipal in which case it is resolved by a custom Spring Security resolver through Authentication#getPrincipal . |
HttpMethod | The HTTP method of the request. |
java.util.Locale | The current request locale, determined by the most specific LocaleResolver available (in effect, the configured LocaleResolver or LocaleContextResolver ). |
java.util.TimeZone + java.time.ZoneId | The time zone associated with the current request, as determined by a LocaleContextResolver . |
java.io.InputStream , java.io.Reader | For access to the raw request body as exposed by the Servlet API. |
java.io.OutputStream , java.io.Writer | For access to the raw response body as exposed by the Servlet API. |
@PathVariable | For access to URI template variables. See URI patterns. |
@MatrixVariable | For access to name-value pairs in URI path segments. See Matrix Variables. |
@RequestParam | For access to the Servlet request parameters, including multipart files. Parameter values are converted to the declared method argument type. See @RequestParam as well as Multipart.Note that use of @RequestParam is optional for simple parameter values. See “Any other argument”, at the end of this table. |
@RequestHeader | For access to request headers. Header values are converted to the declared method argument type. See @RequestHeader . |
@CookieValue | For access to cookies. Cookies values are converted to the declared method argument type. See @CookieValue . |
@RequestBody | For access to the HTTP request body. Body content is converted to the declared method argument type by using HttpMessageConverter implementations. See @RequestBody . |
HttpEntity<B> | For access to request headers and body. The body is converted with an HttpMessageConverter . See HttpEntity. |
@RequestPart | For access to a part in a multipart/form-data request, converting the part’s body with an HttpMessageConverter . See Multipart. |
java.util.Map , org.springframework.ui.Model , org.springframework.ui.ModelMap | For access to the model that is used in HTML controllers and exposed to templates as part of view rendering. |
RedirectAttributes | Specify attributes to use in case of a redirect (that is, to be appended to the query string) and flash attributes to be stored temporarily until the request after redirect. See Redirect Attributes and Flash Attributes. |
@ModelAttribute | For access to an existing attribute in the model (instantiated if not present) with data binding and validation applied. See @ModelAttribute as well as Model and DataBinder .Note that use of @ModelAttribute is optional (for example, to set its attributes). See “Any other argument” at the end of this table. |
Errors , BindingResult | For access to errors from validation and data binding for a command object (that is, a @ModelAttribute argument) or errors from the validation of a @RequestBody or @RequestPart arguments. You must declare an Errors , or BindingResult argument immediately after the validated method argument. |
SessionStatus + class-level @SessionAttributes | For marking form processing complete, which triggers cleanup of session attributes declared through a class-level @SessionAttributes annotation. See @SessionAttributes for more details. |
UriComponentsBuilder | For preparing a URL relative to the current request’s host, port, scheme, context path, and the literal part of the servlet mapping. See URI Links. |
@SessionAttribute | For access to any session attribute, in contrast to model attributes stored in the session as a result of a class-level @SessionAttributes declaration. See @SessionAttribute for more details. |
@RequestAttribute | For access to request attributes. See @RequestAttribute for more details. |
Any other argument | If a method argument is not matched to any of the earlier values in this table and it is a simple type (as determined by BeanUtils#isSimpleProperty), it is resolved as a @RequestParam . Otherwise, it is resolved as a @ModelAttribute |
7.2. 内置的参数
HttpServletRequest、HttpServletResponse、HTTPSession、Model、ModelMap
7.2.1.1. 映射方法
java
@RequestMapping("/list")
public String list(ModelMap model , HttpServletRequest request, HttpServletResponse response, HttpSession session ) throws ServletException, IOException {
ServletContext app1 = session.getServletContext();
ServletContext app2 = request.getServletContext();
System.out.println("app = " + app1);
model.addAttribute("userList",userService.selectListEntity());
return "/user/user_list";
}
7.3. 基础类型
支持整型、字符串、单精度/双精度、布尔型
当请求的【参数名称】和【处理器形参名称】一致(区分大小写)时会将请求参数与形参进行绑定。
完成修改的功能
java
package com.neuedu.mvc.controller;
import com.neuedu.mvc.entity.User;
import com.neuedu.mvc.service.IUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;
/**
* 项目: spring-framework
* 类名: UserController
* 创建时间: 2024/3/18 16:23
* 描述 :
* 作者 : 张金山
* QQ : 314649444
* Site: https://jshand.gitee.io
*/
@Controller
@RequestMapping("/user")
public class UserController {
@Autowired
IUserService userService;
@RequestMapping("/list")
public String list(ModelMap model , HttpServletRequest request, HttpServletResponse response, HttpSession session ) throws ServletException, IOException {
ServletContext app1 = session.getServletContext();
ServletContext app2 = request.getServletContext();
System.out.println("app = " + app1);
model.addAttribute("userList",userService.selectListEntity());
return "/user/user_list";
}
@RequestMapping("toAdd")
public String toAdd(){
return "/user/user_add";
}
/**
* http://lo
* @param request
* @param response
* @return
* @throws ParseException
*/
@RequestMapping("add")
public String add(HttpServletRequest request,HttpServletResponse response) throws ParseException {
// 获取参数
String userId = request.getParameter("userId");
String userName = request.getParameter("userName");
String birthday = request.getParameter("birthday");// "2024-03-19" "asdfasfasdfas"
String gender = request.getParameter("gender");
String status = request.getParameter("status");
//调用service保存
User user = new User();
user.setUserId(Integer.parseInt(userId));
user.setUserName(userName);
user.setBirthday(new SimpleDateFormat("yyyy-MM-dd").parse(birthday));
user.setGender(gender);
user.setStatus(Integer.parseInt(status));
boolean success = userService.insert(user);
String path = "";
if(success) {
// 重定向
// redirect 和 forward 使用的不带前缀和后缀的视图层处理
path = "redirect:/user/list";
}else{
path = "/user/user_add";
}
return path;
}
@RequestMapping("forward")
public ModelAndView forward(HttpServletRequest request) throws ParseException {
ModelAndView mv = new ModelAndView();
// mv.setViewName("/dept/dept_add.jsp");
mv.setViewName("forward:/dept/dept_add.jsp");
return mv;
}
/**
* http://localhost:8080/web/user/toEdit?userId=>>>
* @param modelMap
* @param userId
* @return
*/
@GetMapping("/toEdit")
public String toEdit( ModelMap modelMap, Integer userId ){
modelMap.addAttribute("user",userService.selectById(userId));
return "/user/user_edit";
}
@RequestMapping("update")
// public String update( String userId, String userName, String birthday, String gender, String status ) throws ParseException {
public String update( User user ) throws ParseException {
//调用service保存
boolean success = userService.updateById(user);
String path = "";
if(success) {
// 重定向
// redirect 和 forward 使用的不带前缀和后缀的视图层处理
path = "redirect:/user/list";
}else{
path = "/user/user_edit";
}
return path;
}
}
html
<%@ page import="java.util.List" %>
<%@ page import="com.neuedu.mvc.entity.User" %><%--
Created by IntelliJ IDEA.
User: Administrator
Date: 2024/3/18
Time: 16:26
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<%--<%--%>
<%-- List<User> userList = (List<User>) request.getAttribute("userList");--%>
<%--%>--%>
<h3>用户列表: </h3>
<form action="${pageContext.request.contextPath}/user/update" method="post">
<table>
<tr>
<td>用户ID</td>
<td> <input type="text" name="userId" value="${user.userId}"> </td>
</tr>
<tr>
<td>用户名</td>
<td> <input type="text" name="userName" value="${user.userName}"> </td>
</tr>
<tr>
<td>出生日期("2024-03-19")</td>
<td> <input type="text" name="birthday" value="<fmt:formatDate pattern="yyyy-MM-dd" value="${user.birthday}"/>"> </td>
</tr>
<tr>
<td>性别</td>
<td> <input type="text" name="gender" value="${user.gender}"> </td>
</tr>
<tr>
<td>状态</td>
<td> <input type="text" name="status" value="${user.status}"> </td>
</tr>
<tr>
<td>
<button type="submit">提交</button>
<button type="reset">重置</button>
</td>
</tr>
</table>
</form>
</body>
</html>
7.3.1. @RequestParam
当请求的【参数名称】和【处理器形参名称】不一致的时候需要使用注解@RequestParam进行自定义的绑定,
声明次注解则默认该参数必须提供(必须传),可以使用required属性=false设置为非必须。
<input type="text" name="test" value="123546">
@RequestParam(value = "test",required = false) String myVar
通过defaultValue属性设置默认值
java
// http://127.0.0.1:8080/springmvc/param4?username=jshand&age=30&salary=3000.01&onstudy=true
@RequestMapping("/param4")
public void param4(HttpServletResponse response, @RequestParam(value = "username",required = false,defaultValue="admin") String name , Integer age, Double salary, boolean onstudy) throws ServletException, IOException {
System.out.println("name-->"+name);
System.out.println("age-->"+age);
System.out.println("salary-->"+salary);
System.out.println("onstudy-->"+onstudy);
response.setContentType("text/html;charset=utf-8");//响应html,格式utf8
PrintWriter out = response.getWriter();
out.println("<div style='border:1px solid red'>name:"+name+"</div>");
out.println("<div style='border:1px solid red'>age:"+age+"</div>");
out.println("<div style='border:1px solid red'>salary:"+salary+"</div>");
out.println("<div style='border:1px solid red'>onstudy:"+onstudy+"</div>");
out.flush();
out.close();
}
7.4. Pojo类型
7.4.1. 表单
html
<%--
Created by IntelliJ IDEA.
User: root
Date: 2020/3/27
Time: 14:38
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<%--模拟用户注册,存在大量的字段--%>
<form action="../param5">
<!--模拟都是 30-字段 -->
<table>
<tr>
<td>用户名字</td>
<td><input type="text" name="username"></td>
</tr>
<tr>
<td>常用地址</td>
<td><input type="text" name="password"></td>
</tr>
<tr>
<td>账户余额</td>
<td><input type="text" name="amount"></td>
</tr>
<tr>
<td colspan="2"><input type="submit" value="用户注册"></td>
</tr>
</table>
</form>
</body>
</html>
7.5. Pojo包装的POJO
为了解决同名参数可以使用pojo嵌套pojo解决
http://localhost:8080/web/doctor/update?doctor.id=1&doctor.name=222&dept.id=456&dept.name=DEV
java
package com.neuedu.mvc.entity;
/**
* 项目: spring-framework
* 类名: Doctor
* 创建时间: 2024/3/19 14:52
* 描述 :
* 作者 : 张金山
* QQ : 314649444
* Site: https://jshand.gitee.io
*/
public class Doctor {
private Integer id;
private String name;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Doctor{" +
"id=" + id +
", name='" + name + '\'' +
'}';
}
}
java
package com.neuedu.mvc.entity;
/**
* 项目: spring-framework
* 类名: Dept
* 创建时间: 2024/3/19 14:54
* 描述 :
* 作者 : 张金山
* QQ : 314649444
* Site: https://jshand.gitee.io
*/
public class Dept {
private Integer id;
private String name;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Dept{" +
"id=" + id +
", name='" + name + '\'' +
'}';
}
}
java
package com.neuedu.mvc.vo;
import com.neuedu.mvc.entity.Dept;
import com.neuedu.mvc.entity.Doctor;
/**
* 项目: spring-framework
* 类名: DoctorVo
* 创建时间: 2024/3/19 14:58
* 描述 :
* 作者 : 张金山
* QQ : 314649444
* Site: https://jshand.gitee.io
*/
public class DoctorVo {
private Doctor doctor;
private Dept dept;
public Doctor getDoctor() {
return doctor;
}
public void setDoctor(Doctor doctor) {
this.doctor = doctor;
}
public Dept getDept() {
return dept;
}
public void setDept(Dept dept) {
this.dept = dept;
}
@Override
public String toString() {
return "DoctorVo{" +
"doctor=" + doctor +
", dept=" + dept +
'}';
}
}
java
package com.neuedu.mvc.controller;
import com.neuedu.mvc.entity.Dept;
import com.neuedu.mvc.entity.Doctor;
import com.neuedu.mvc.vo.DoctorVo;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import javax.servlet.http.HttpServletResponse;
/**
* 项目: spring-framework
* 类名: DoctorController
* 创建时间: 2024/3/19 14:51
* 描述 :
* 作者 : 张金山
* QQ : 314649444
* Site: https://jshand.gitee.io
*/
@Controller
@RequestMapping("doctor")
public class DoctorController {
/**
*
* <input type="text" name="doctor.id" value=""/>
* <input type="text" name="doctor.name" value=""/>
*
* <input type="text" name="dept.id" value=""/>
* <input type="text" name="dept.name" value=""/>
*
*
* http://localhost:8080/web/doctor/update?doctor.id=1&doctor.name=222&dept.id=456&dept.name=DEV
// * @param doctor
* @param vo
*/
@RequestMapping("update")
// public void save(Doctor doctor, Dept dept , HttpServletResponse response){
public void save(DoctorVo vo , HttpServletResponse response){
System.out.println("vo = " + vo);
}
}
7.6. 数组类型
7.6.1. 控制器
java
/***
* 接受数组
*
* 批量删除用户信息 【userId、userId、userId、userId】
*
*/
@RequestMapping("/param7")
public void param7(HttpServletResponse response, Integer[] userId) throws IOException {
response.setContentType("text/html;charset=utf-8");//响应html,格式utf8
PrintWriter out = response.getWriter();
StringBuffer ids = new StringBuffer();
for (Integer id : userId) {
ids.append(id+",");
}
out.println("<div style='border:1px solid blue'>批量删除的id::"+
ids.toString()
+"</div>");
out.flush();
out.close();
}
7.6.2. Form表单
html
<%--
Created by IntelliJ IDEA.
User: root
Date: 2020/3/27
Time: 14:38
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<form action="../param7">
<table>
<tr>
<td>勾选id删除</td>
<td>用户名</td>
<td>密码</td>
</tr>
<tr>
<td><input type="checkbox" name="userId" value="1"/> 1</td>
<td>admin</td>
<td>123456</td>
</tr>
<tr>
<td><input type="checkbox" name="userId" value="2"/> 2</td>
<td>jshand</td>
<td>456789</td>
</tr>
<tr>
<td><input type="checkbox" name="userId" value="3"/> 3</td>
<td>yaoming</td>
<td>456789</td>
</tr>
</table>
<input type="submit" value="批量删除">
</form>
</body>
</html>
7.6.3. 页面效果
7.7. List类型封装参数
7.7.3. Form表单
<%--
Created by IntelliJ IDEA.
User: root
Date: 2020/3/27
Time: 14:38
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<form action="${pageContext.request.contextPath}/user/batchAdd" method="post">
<table>
<tr>
<td>用户id</td>
<td>用户名</td>
<td>性别</td>
</tr>
<tr>
<td><input type="text" name="userList[0].userId"/></td>
<td><input type="text" name="userList[0].userName"/></td>
<td><input type="text" name="userList[0].gender"/></td>
</tr>
<tr>
<td><input type="text" name="userList[1].userId"/></td>
<td><input type="text" name="userList[1].userName"/></td>
<td><input type="text" name="userList[1].gender"/></td>
</tr>
<tr>
<td><input type="text" name="userList[2].userId"/></td>
<td><input type="text" name="userList[2].userName"/></td>
<td><input type="text" name="userList[2].gender"/></td>
</tr>
</table>
<input type="submit" value="批量保存">
</form>
</body>
</html>
7.7.1. Vo中添加List属性 添加setter、getter方法
java
package com.neuedu.mvc.vo;
import com.neuedu.mvc.entity.User;
import java.util.List;
/**
* 项目: spring-framework
* 类名: ParamVo
* 创建时间: 2024/3/20 08:53
* 描述 :
* 作者 : 张金山
* QQ : 314649444
* Site: https://jshand.gitee.io
*/
public class ParamVo {
List<User> userList;
public List<User> getUserList() {
return userList;
}
public void setUserList(List<User> userList) {
this.userList = userList;
}
}
7.7.2. 控制器方法
java
@RequestMapping("batchAdd")
public String batchAdd(ParamVo vo ){
for (User user : vo.getUserList()) {
userService.insert(user);
}
return "redirect:/user/list";
}
/**
* 跳转到批量添加页面
* @param vo
* @return
*/
@RequestMapping("toBatchAdd")
public String toBatchAdd(ParamVo vo ){
return "/user/user_add_batch";
}
7.7.4. 测试效果
7.8. Map接受参数
7.8.1. Form表单
html
<%@ page import="java.util.List" %>
<%@ page import="com.neuedu.mvc.entity.User" %><%--
Created by IntelliJ IDEA.
User: Administrator
Date: 2024/3/18
Time: 16:26
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<%--<%--%>
<%-- List<User> userList = (List<User>) request.getAttribute("userList");--%>
<%--%>--%>
<h3>用户列表: </h3>
<form action="${pageContext.request.contextPath}/user/add2" method="post">
<table>
<tr>
<td>用户ID</td>
<td> <input type="text" name="userId" value=""> </td>
</tr>
<tr>
<td>用户名</td>
<td> <input type="text" name="userName" value=""> </td>
</tr>
<tr>
<td>出生日期("2024-03-19")</td>
<td> <input type="text" name="birthday" value=""> </td>
</tr>
<tr>
<td>性别</td>
<td> <input type="text" name="gender" value=""> </td>
</tr>
<tr>
<td>状态</td>
<td> <input type="text" name="status" value=""> </td>
</tr>
<tr>
<td>
<button type="submit">提交</button>
<button type="reset">重置</button>
</td>
</tr>
</table>
</form>
</body>
</html>
7.8.2. 控制器
需要注意,在Map参数上添加@RequestParam注解才能绑定参数
java
@RequestMapping("add2")
public String add(@RequestParam Map map) throws ParseException {
System.out.println("map = " + map);
//没有真正插入数据库,页面没有变化
return "redirect:/user/list";
}
7.9. 自定义的参数转换
页面上传递过的基础类型(Stirng、浮点型、整数等)可以直接绑定,Date特殊Springmvc默认无法转换,需要自定义转换器
7.9.1. 自定义一个转换器
java
package com.neuedu.converter;
import org.springframework.core.convert.converter.Converter;;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.logging.SimpleFormatter;
/**
* 项目 : spring-mvc-java1
* 创建时间 :2020/3/31 11:42 31
* author :jshand-root
* site : http://314649444.iteye.com
* 描述 : 自定义的 类型转换器
*/
public class String2DateConverter implements Converter<String, Date> {
static List<SimpleDateFormat> sdfs = new ArrayList();
static{
sdfs.add(new SimpleDateFormat("yyyy-MM-dd"));
sdfs.add(new SimpleDateFormat("yyyy/MM/dd"));
sdfs.add(new SimpleDateFormat("yyyy-MM-dd"));
sdfs.add(new SimpleDateFormat("yyyy/MM/dd HH:mm:ss"));
sdfs.add(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
}
@Override
public Date convert(String s) {
Date date = null;
for (SimpleDateFormat sdf : sdfs) {
try {
date = sdf.parse(s);
return date;
} catch (ParseException e) {
e.printStackTrace();
}
}
return null;
}
}
7.9.2. 给处理器适配器注入converService**
xml
<mvc:annotation-driven conversion-service="conversionService" />
<!-- 自定义的参数转换器 配置各种转换器 有默认值 String- stirng stirng- Double .... -->
<bean id="conversionService" class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
<property name="converters">
<list>
<!--内部的Bean声明-->
<bean id="string2DateConverter" class="com.neuedu.converter.String2DateConverter"/>
</list>
</property>
</bean>
