Skip to content

7. 参数绑定

7.1. 参数绑定的过程

下表描述了支持的控制器方法参数

Controller method argumentDescription
WebRequest, NativeWebRequestGeneric access to request parameters and request and session attributes, without direct use of the Servlet API.
javax.servlet.ServletRequest, javax.servlet.ServletResponseChoose any specific request or response type — for example, ServletRequest, HttpServletRequest, or Spring’s MultipartRequest, MultipartHttpServletRequest.
javax.servlet.http.HttpSessionEnforces 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.PushBuilderServlet 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.PrincipalCurrently 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.
HttpMethodThe HTTP method of the request.
java.util.LocaleThe current request locale, determined by the most specific LocaleResolver available (in effect, the configured LocaleResolver or LocaleContextResolver).
java.util.TimeZone + java.time.ZoneIdThe time zone associated with the current request, as determined by a LocaleContextResolver.
java.io.InputStream, java.io.ReaderFor access to the raw request body as exposed by the Servlet API.
java.io.OutputStream, java.io.WriterFor access to the raw response body as exposed by the Servlet API.
@PathVariableFor access to URI template variables. See URI patterns.
@MatrixVariableFor access to name-value pairs in URI path segments. See Matrix Variables.
@RequestParamFor 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.
@RequestHeaderFor access to request headers. Header values are converted to the declared method argument type. See @RequestHeader.
@CookieValueFor access to cookies. Cookies values are converted to the declared method argument type. See @CookieValue.
@RequestBodyFor 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.
@RequestPartFor 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.ModelMapFor access to the model that is used in HTML controllers and exposed to templates as part of view rendering.
RedirectAttributesSpecify 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.
@ModelAttributeFor 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, BindingResultFor 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 @SessionAttributesFor marking form processing complete, which triggers cleanup of session attributes declared through a class-level @SessionAttributes annotation. See @SessionAttributes for more details.
UriComponentsBuilderFor 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.
@SessionAttributeFor 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.
@RequestAttributeFor access to request attributes. See @RequestAttribute for more details.
Any other argumentIf 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>

Released under the MIT License.