• 2,Spring MVC 学习总结(二)- 方法(Action)参数映射


    一,Controller层方法(Action)参数映射

    1,自动参数映射

    1.1,基本数据类型参数映射

    方法的参数可以是任意基本数据类型,如果方法参数名与http中请求的参数名称相同时会进行自动映射。例如:

    ActionController:

    @Controller
    @RequestMapping("/Action")
    public class ActionController {
        /**
         * 
         * @方法名: returnAction
         * @描述: 自动参数映射---基本数据类型
         * @param model
         * @param i
         * @param s
         * @return 返回视图名称
         * @创建人 Zender
         */
        @RequestMapping("/returnAction")
        public String returnAction(Model model, int i, String s) {
            model.addAttribute("message", "i:" + i + ",s:" + s);
            return "index";
        }
    }

    Index.jsp:

    <%@ page language="java" contentType="text/html; charset=UTF-8"
        pageEncoding="UTF-8"%>
    <!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>Insert title here</title>
    </head>
    <body>
        内容:${message}
    </body>
    </html>

    运行结果:

    1.2,自定义数据类型参数映射

    自定义的POJO对象,Spring MVC会通过反射把请中的参数设置到对象中,转换类型,例如:

    Person:

    public class Person {
        private int id;
        private String name;
        private String addrs;
        public int getId() {
            return id;
        }
        public void setId(int id) {
            this.id = id;
        }
        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
        public String getAddrs() {
            return addrs;
        }
        public void setAddrs(String addrs) {
            this.addrs = addrs;
        }
        public Person(int id, String name, String addrs) {
            this.id = id;
            this.name = name;
            this.addrs = addrs;
        }
        public Person() {
        }
        @Override
        public String toString() {
            return "Person [id=" + id + ", name=" + name + ", addrs=" + addrs + "]";
        }
    }

    ActionController:

    @Controller
    @RequestMapping("/Action")
    public class ActionController {
        /**
         * 
         * @方法名: returnPersonAction
         * @描述: 自动参数映射---自定义数据类型
         * @param model
         * @param person
         * @return 返回视图名称
         * @创建人 Zender
         */
        @RequestMapping("/returnPersonAction")
        public String returnPersonAction(Model model, Person person){
            model.addAttribute("person", person.toString());
            return "index";
        }
    }

    index.jsp:

    <%@ page language="java" contentType="text/html; charset=UTF-8"
        pageEncoding="UTF-8"%>
    <!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>Insert title here</title>
    </head>
    <body>
        内容:${person}
    </body>
    </html>

    运行结果:

    1.3,复杂数据类型参数映射

    复杂数据类型指的是一个自定义类型中还包含另外一个对象类型,或者包含集合,Map等等对象类型,例如如下Pojo类:

    public class SysUser {
        private String userName;
        private String userPwd;
        private Person person;
        public String getUserName() {
            return userName;
        }
        public void setUserName(String userName) {
            this.userName = userName;
        }
        public String getUserPwd() {
            return userPwd;
        }
        public void setUserPwd(String userPwd) {
            this.userPwd = userPwd;
        }
        public Person getPerson() {
            return person;
        }
        public void setPerson(Person person) {
            this.person = person;
        }
        public SysUser(String userName, String userPwd, Person person) {
            this.userName = userName;
            this.userPwd = userPwd;
            this.person = person;
        }
        public SysUser() {
        }
        @Override
        public String toString() {
            return "SysUser [userName=" + userName + ", userPwd=" + userPwd + ", person=" + person + "]";
        }
    }

    Index.jsp:

    <%@ page language="java" contentType="text/html; charset=UTF-8"
        pageEncoding="UTF-8"%>
    <%
       String path = request.getContextPath();
       String basePath = request.getScheme() + "://"
               + request.getServerName() + ":" + request.getServerPort()
               + path + "/";
    %>
    <!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>Insert title here</title>
    </head>
    <body>
        <form method="post" action="Action/returnSysUserAction">
         username:<input name="userName" /><br/>
         userpwd:<input name="userPwd" /><br/>
         id:<input name="person.id" /><br/>
         name:<input name="person.name" /><br/>
         addrs:<input name="person.addrs" /><br/>
        <button>提交</button>
    </form>
    </body>
    </html>

    return.jsp:

    <%@ page language="java" contentType="text/html; charset=UTF-8"
        pageEncoding="UTF-8"%>
    <!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>Insert title here</title>
    </head>
    <body>
        内容:${sysUser}
    </body>
    </html>

    ActionController:

    @Controller
    @RequestMapping("/Action")
    public class ActionController {
        /**
         * 
         * @方法名: returnSysUserAction
         * @描述: 自动参数映射---复杂数据类型
         * @param model
         * @param sysUser
         * @return 返回视图名称
         * @创建人 Zender
         * @创建时间 2017年12月10日下午6:33:43
         */
        @RequestMapping("/returnSysUserAction")
        public String returnSysUserAction(Model model, SysUser sysUser){
            model.addAttribute("sysUser", sysUser.toString());
            return "return";
        }
    }

    运行结果:

    1.4,集合类型参数映射

    List集合类型:

    不能直接在方法(action)的参数中指定List<T>类型,定义一个类型包装List集合在其中,例如:

    public class PersonList {
        private List<Person> list;
     
        public List<Person> getList() {
            return list;
        }
     
        public void setList(List<Person> list) {
            this.list = list;
        }
    }

    定义方法(action)代码如下:

    @Controller
    @RequestMapping("/Action")
    public class ActionController {
        /**
         * 
         * @方法名: returnListAction
         * @描述: 自动参数映射---List数据类型
         * @param model
         * @param personList
         * @return
         * @创建人 Zender
         */
        @RequestMapping("/returnListAction")
        public String returnListAction(Model model, PersonList personList){
            model.addAttribute("personList", personList.getList().get(0).toString());
            return "return";
        }
    }

    表单页面如下:

    <%@ page language="java" contentType="text/html; charset=UTF-8"
        pageEncoding="UTF-8"%>
    <%
       String path = request.getContextPath();
       String basePath = request.getScheme() + "://"
               + request.getServerName() + ":" + request.getServerPort()
               + path + "/";
    %>
    <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
    <html>
    <head>
    <base href="<%=basePath%>" />
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title>List</title>
    <link href="css/bootstrap.css" rel="stylesheet">
    <script src="js/jquery-3.2.1.js"></script>
    <script src="js/bootstrap.js"></script>
    </head>
    <body>
    <form class="form-horizontal" action="<%=request.getContextPath()%>/Action/returnListAction" role="form" method="post">
            <div class="form-group">
                <label for="firstname" class="col-sm-1 control-label">id</label>
                <div class="col-sm-3">
                    <input type="text" class="form-control" name="list[0].id"
                        placeholder="请输入id">
                </div>
            </div>
            <div class="form-group">
                <label for="lastname" class="col-sm-1 control-label">名字</label>
                <div class="col-sm-3">
                    <input type="text" class="form-control" name="list[0].name"
                        placeholder="请输名字">
                </div>
            </div>
            <div class="form-group">
                <label for="lastname" class="col-sm-1 control-label">地址</label>
                <div class="col-sm-3">
                    <input type="text" class="form-control" name="list[0].addrs"
                        placeholder="请输地址">
                </div>
            </div>
            <div class="form-group">
                <div class="col-sm-offset-1 col-sm-3">
                    <button type="submit" class="btn btn-default">提交</button>
                    <button type="reset" class="btn btn-default">重置</button>
                </div>
            </div>
        </form>
    </body>
    </html>

    表单向服务器提交数据,提交后结果如下:

    Map集合类型:

    Map与List的实现方式基本一样,同样需要包装Map类型,例如:

    public class PersonMap {
        private Map<String,Person> map;
     
        public Map<String, Person> getMap() {
            return map;
        }
     
        public void setMap(Map<String, Person> map) {
            this.map = map;
        }
    }

    定义方法(action)代码如下:

    @Controller
    @RequestMapping("/Action")
    public class ActionController {
        /**
         * 
         * @方法名: returnMapAction
         * @描述: 自动参数映射---Map数据类型
         * @param model
         * @param personMap
         * @return
         * @创建人 Zender
         */
        @RequestMapping("/returnMapAction")
        public String returnMapAction(Model model, PersonMap personMap){
            model.addAttribute("personMap", personMap.getMap().get("user1").toString());
            return "return";
        }
    }

    表单页面如下:

    <%@ page language="java" contentType="text/html; charset=UTF-8"
        pageEncoding="UTF-8"%>
    <%
       String path = request.getContextPath();
       String basePath = request.getScheme() + "://"
               + request.getServerName() + ":" + request.getServerPort()
               + path + "/";
    %>
    <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
    <html>
    <head>
    <base href="<%=basePath%>" />
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title>Map</title>
    <link href="css/bootstrap.css" rel="stylesheet">
    <script src="js/jquery-3.2.1.js"></script>
    <script src="js/bootstrap.js"></script>
    </head>
    <body>
    <form class="form-horizontal" action="<%=request.getContextPath()%>/Action/returnMapAction" role="form" method="post">
            <div class="form-group">
                <label for="firstname" class="col-sm-1 control-label">id</label>
                <div class="col-sm-3">
                    <input type="text" class="form-control" name="map[user1].id"
                        placeholder="请输入id">
                </div>
            </div>
            <div class="form-group">
                <label for="lastname" class="col-sm-1 control-label">名字</label>
                <div class="col-sm-3">
                    <input type="text" class="form-control" name="map[user1].name"
                        placeholder="请输名字">
                </div>
            </div>
            <div class="form-group">
                <label for="lastname" class="col-sm-1 control-label">地址</label>
                <div class="col-sm-3">
                    <input type="text" class="form-control" name="map[user1].addrs"
                        placeholder="请输地址">
                </div>
            </div>
            <div class="form-group">
                <div class="col-sm-offset-1 col-sm-3">
                    <button type="submit" class="btn btn-default">提交</button>
                    <button type="reset" class="btn btn-default">重置</button>
                </div>
            </div>
        </form>
    </body>
    </html>

    表单向服务器提交数据,提交后结果如下:

    2,@RequestParam参数绑定

    复杂一些的数据需使用@RequestParam完成参数映射,虽然自动参数映射很方便,但有些细节是不能处理的,例如参数是否为必须参数名称没有办法指定参数的默认值。如果使用@RequestParam可以实现请求参数绑定,Spring MVC会自动查找请求中的参数转类型并将与参数进行绑定。

    2.1,基本数据类型参数绑定

    @Controller
    @RequestMapping("/Action")
    public class ActionController {
        /**
         * 
         * @方法名: requestParamAction
         * @描述: RequestParam注解参数绑定
         * @param model
         * @param text
         * @return
         * @创建人 Zender
         */
        @RequestMapping("/requestParamAction")
        public String requestParamAction(Model model, @RequestParam(required = false, defaultValue = "默认的文本") String text){
            model.addAttribute("text", text);
            return "return";
        }
    }

    @RequestParam共有4个注解属性:

    required属性

    表示是否为必须,默认值为true,如果请求中没有指定的参数会报异常。

    defaultValue属性

    用于设置参数的默认值,如果不指定值则使用默认值,只能是String类型的。

    name与value属性

    两个互为别名关系用于指定参数名称。

    运行结果:

    2.2,List数据类型参数绑定

    @Controller
    @RequestMapping("/Action")
    public class ActionController {
        /**
         * 
         * @方法名: requestParamListAction
         * @描述:  RequestParam注解List类型参数绑定
         * @param model
         * @param text
         * @return
         * @创建人 Zender
         */
        @RequestMapping("/requestParamListAction")
        public String requestParamListAction(Model model, @RequestParam("text") List<String> text){
            model.addAttribute("text", text);
            return "return";
        }
    }

    运行结果:

    2.3,自定义数据类型参数绑定与Ajax

    如果需要直接绑定更加复杂的数据类型,则需要使用@RequestBody与@ResponseBody注解:

    @RequestBody

    将HTTP请求正文转换为适合的HttpMessageConverter对象。

    @ResponseBody

    将内容或对象作为 HTTP 响应正文返回,并调用适合HttpMessageConverter的Adapter转换对象,写入输出流。

    @RequestBody默认接收的Content-Type是application/json,因此发送POST请求时需要设置请求报文头信息,否则Spring MVC在解析集合请求参数时不会自动的转换成JSON数据再解析成相应的集合,Spring默认的json协议解析由Jackson完成。要完成这个功能还需要修改pom.xml,添加jackson依赖,如下:

    <!-- jackson -->
    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-core</artifactId>
        <version>2.5.2</version>
    </dependency>
    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-databind</artifactId>
        <version>2.5.2</version>
    </dependency>

    方法(Action)定义如下:

    @Controller
    @RequestMapping("/Action")
    public class ActionController {
        /**
         * 
         * @方法名: requestJSONAction
         * @描述: 接收JSON格式的数据显示控制台
         * @param response
         * @param person
         * @throws IOException
         * @创建人 Zender
         */
        @RequestMapping("/requestJSONAction")
        //@RequestBody的作用是让Spring MVC在收到客户端请求时将选择合适的转换器将参数转换成相应的对象。
        public void requestJSONAction(HttpServletResponse response, @RequestBody List<Person> person) throws IOException{
             response.setCharacterEncoding("UTF-8");
             System.out.println(Arrays.deepToString(person.toArray()));
             response.getWriter().write("添加成功");
        }
        /**
         * 
         * @方法名: requestJSON2Action
         * @描述: 接收JSON格式的数据返回页面
         * @param response
         * @param person
         * @return
         * @throws IOException
         * @创建人 Zender
         */
        @RequestMapping("/requestJSON2Action")
        @ResponseBody//该注解会使用jackson将该对象自动序列化成json字符
        public List<Person> requestJSON2Action(HttpServletResponse response, @RequestBody List<Person> person) throws IOException{
             return person;
        }
    }

    页面如下:

    <%@ page language="java" contentType="text/html; charset=UTF-8"
        pageEncoding="UTF-8"%>
    <%
       String path = request.getContextPath();
       String basePath = request.getScheme() + "://"
               + request.getServerName() + ":" + request.getServerPort()
               + path + "/";
    %>
    <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
    <html>
    <head>
    <base href="<%=basePath%>" />
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title>Map</title>
    <link href="css/bootstrap.css" rel="stylesheet">
    <script src="js/jquery-3.2.1.js"></script>
    <script src="js/bootstrap.js"></script>
    </head>
    <body>
        <button class="btn btn-default" type="submit" onclick="addPersion();">提交</button>
        <button class="btn btn-default" type="submit" onclick="getPersion();">获取</button>
        <p id="msg"></p>
        <script type="text/javascript">
            function addPersion(){
                $.ajax({
                    type : "POST",
                    url : "Action/requestJSONAction",
                    data : '[{"id" : 1, "name" : "Zender", "addrs" : "Shanghai"},' +
                            '{"id" : 2, "name" : "Zender1", "addrs" : "Shanghai1"},' +
                            '{"id" : 3, "name" : "Zender2", "addrs" : "Shanghai2"}]',
                    contentType : "application/json;charset=UTF-8",
                    dataType : "text",
                    success : function(result) {
                        $("#msg").html(result);
                    }
                });
            }
            function getPersion(){
                $.ajax({
                    type : "POST",
                    url : "Action/requestJSON2Action",
                    data : '[{"id" : 1, "name" : "Zender", "addrs" : "Shanghai"},' +
                            '{"id" : 2, "name" : "Zender1", "addrs" : "Shanghai1"},' +
                            '{"id" : 3, "name" : "Zender2", "addrs" : "Shanghai2"}]',
                    contentType : "application/json;charset=UTF-8",
                    dataType : "json",
                    success : function(result) {
                        var str = "";
                        $.each(result, function(i, obj) {
                            str += "id:" + obj.id + ",name:" + obj.name + ",addrs:"+ obj.addrs + "<br/>";
                        });
                        $("#msg").html(str);
                    }
                });
            }
        </script>
    </body>
    </html>

    点击提交按钮运行结果:

    控制台:

    点击获取按钮运行结果:

    3,重定向与RedirectAttributes

    在一个请求处理方法Action中如果返回结果为"return"字符则表示转发到视图return,有时候我们需要重定向,则可以在返回的结果前加上一个前缀"redirect:",可以重定向到一个指定的页面也可以是另一个方法(action),代码如下:

    @Controller
    @RequestMapping("/Action")
    public class ActionController {
        @RequestMapping("/redirectAction1")
        public String redirectAction1(Model model, Person person){
            model.addAttribute("person", person);
            System.out.println(person.toString());
            return "return";
        }
        
        @RequestMapping("/redirectAction2")
        //RedirectAttributes是Spring mvc 3.1版本之后出来的一个功能,专门用于重定向之后还能带参数跳转的.
        public String redirectAction2(Model model, RedirectAttributes redirectAttributes){
            Person person = new Person(1, "Zender", "Shanghai");
            redirectAttributes.addFlashAttribute("person", person);
            return "redirect:redirectAction1";
        }
    }

    RedirectAttributes:

    RedirectAttributes是Spring mvc 3.1版本之后出来的一个功能,专门用于重定向之后还能带参数跳转的。

    他有两种带参的方式:

    第一种:

    attr.addAttribute("param", value);

    这种方式就相当于重定向之后,在url后面拼接参数,这样在重定向之后的页面或者控制器再去获取url后面的参数就可以了,但这个方式因为是在url后面添加参数的方式,所以暴露了参数,有风险。

    第二种:

    attr.addFlashAttribute("param", value);

    这种方式也能达到重新向带参,而且能隐藏参数,其原理就是放到session中,session在跳到页面后马上移除对象。所以你刷新一下后这个值就会丢掉参数。

    访问redirectAction2,首先创建了一个person对象,将该对象添加到了Flash属性中,在重定向到redirectAction1后取出person对象,显示到页面上。

    4,@ModelAttribute注解

    @ModelAttribute可以应用在方法参数上或方法上。

    注解在参数上

    会将注解的参数对象添加到Model中。

    注解在方法上

    会将该方法(Action)变成一个非请求处理的方法,在其它方法(Action)被调用时会首先调用该方法。

    4.1,注解在参数上

    注解在参数上会将注解的参数对象添加到Model中。

    @Controller
    @RequestMapping("/Action")
    public class ActionController {
        /**
         * 
         * @方法名: modelAttributeAction
         * @描述: 自动数据绑定
         * @param model
         * @param person
         * @return 返回视图名称
         * @创建人 Zender
         */
        @RequestMapping("/modelAttributeAction")
        public String modelAttributeAction(Model model, @ModelAttribute(name = "person", binding = true) Person person){
            System.out.println("是否在Model里:" + model.containsAttribute("person"));
            model.addAttribute("person", person);
            return "return";
        }
    }

    运行结果:

    4.2,注解在方法上

    注解在方法上会将该方法(Action)变成一个非请求处理的方法,在其它方法(Action)被调用时会首先调用该方法。

    @Controller
    @RequestMapping("/Action")
    public class ActionController {
        /**
         * 
         * @方法名: modelAttributeAction
         * @描述: 自动数据绑定
         * @param model
         * @param person
         * @return 返回视图名称
         * @创建人 Zender
         */
        @RequestMapping("/modelAttributeAction")
        public String modelAttributeAction(Model model, @ModelAttribute(name = "person", binding = true) Person person){
            System.out.println("是否在Model里:" + model.containsAttribute("person"));
            model.addAttribute("person", person);
            Map<String, Object> map = model.asMap();
            for (String key : map.keySet()) {
                System.out.println(map.get(key));
            }
            return "return";
        }
        
        @ModelAttribute
        public String initAction(){
            System.out.println("initAction方法被调用!");
            String text = "测试数据";
            return text;
        }
        
        @ModelAttribute
        public void initAction2(){
            System.out.println("initAction2方法被调用!");
        }
    }

    运行结果:

    非请求处理方法可以返回void,也可以返回一个任意对象,该对象会被自动添加到每一个要被访问的Action的Model中。

  • 相关阅读:
    环境变量的配置
    java语言概述
    快捷键,功能键及常用的DOS命令
    html介绍
    Java web学习框架
    线程的使用
    Task类(任务)
    Parallel类(简化Task 操作)
    文件及数据流技术
    泛型的使用
  • 原文地址:https://www.cnblogs.com/Zender/p/8073157.html
Copyright © 2020-2023  润新知