Spring MVC学习随笔-控制器(Controller)开发详解:接受客户端(Client)请求参数

这篇具有很好参考价值的文章主要介绍了Spring MVC学习随笔-控制器(Controller)开发详解:接受客户端(Client)请求参数。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

学习视频:孙哥说SpringMVC:结合Thymeleaf,重塑你的MVC世界!|前所未有的Web开发探索之旅

第三章、SpringMVC控制器开发详解

3.1 核心要点

💡 1. 接受客户端(client)请求参数[讲解] 2. 调用业务对象 3. 页面跳转

3.2 控制器接受客户端(client)请求参数详解

3.2.1 回顾:Web开发中如何接受Client请求参数

Spring MVC学习随笔-控制器(Controller)开发详解:接受客户端(Client)请求参数

3.2.2 基于Servlet API接受Client请求参数

@Controller
@RequestMapping("/param")
public class ParamController {

    @RequestMapping("param1")
    public String param(HttpServletRequest request) {
        String name = request.getParameter("name");
        String password = request.getParameter("password");

        System.out.println("name = " + name);
        System.out.println("password = " + password);
        return  "param1";
    }
}
**注意:这种方式虽然最为直观,简单,但是代码冗余且与ServletAPI存在耦合,所以在SpringMVC开发中并不建议使用**

3.2.3 基于简单变量接受Client请求参数

  1. 所谓简单变量:指的就是8种基本类型+String这些类型的变量。把这些类型的变量,作为控制器方法的形参,用于接受client提交的数据。
  • 思路分析

Spring MVC学习随笔-控制器(Controller)开发详解:接受客户端(Client)请求参数

  • 代码

    @Controller
    @RequestMapping("/param")
    public class ParamController {
    
        @RequestMapping("param2")
        public String param2(String name,String password) {
    
            System.out.println("name = " + name);
            System.out.println("password = " + password);
            return  "param1";
        }
    }
    
  • 细节分析

    • 常见类型自动转换

      @RequestMapping("param3")
      public String param3(String name,int age) {
          System.out.println("name = " + name);
          System.out.println("age = " + age);
          return  "param1";
      }
      
      SpringMVC底层针对age接受数据时会自动调用 int age = Integer.parseInt("10")
      
      1. 常见类型泛指:8种基本类型及其包装器,String等常见类型。
      2. Date日期等特殊类型,默认不支持,需要程序员自定义类型转换器【后续讲解】
    • 基本类型尽量使用包装器

      客户端请求:http://localhost:8989/param/param/param3?name=jack
      @Controller
      @RequestMapping("/param")
      public class ParamController {
      
          @RequestMapping("param3")
          public String param3(String name,int age) {
              System.out.println("name = " + name);
              System.out.println("age = " + age);
              return  "param1";
          }
      }
      程序报错:原因在于age没有提交内容,等同于null,而int是基本类型无法存储null值,所以报错
      改正方式:1.age参数使用包装器类型,可以存储null值
      					2.为age参数设置默认值,需要@RequestParam注解配合使用。
      

3.2.4 基于POJO类型接受Client请求参数

  • 什么是POJO
    1. POJO全称叫做 Plain Ordinary Java Object(简单的Java对象)
    2. POJO类型对象的特点是:
      1. 类型中如果存在成员变量,必须提供set get
      2. 提供默认无参构造
      3. 可以实现Serializable,也可以不实现
      4. 不实现容器或者框架所规定的接口
    3. 用户根据业务封装的实体,DTO这些类型就是POJO
  • 使用场景

Spring MVC学习随笔-控制器(Controller)开发详解:接受客户端(Client)请求参数

准备一个实体,成员变量名字要和表单的name对应,其次在控制器方法中,将POJO类作为形参类型定义在控制器方法参数中。
  • 代码

    // POJO
    public class User implements Serializable {
        private String name;
        private String password;
        private int age;
    
    // Controller
    @RequestMapping("param4")
        public String param4(User user) {
            System.out.println("user = " + user);
            return  "param1";
        }
    // 表单请求
    <form method="post" action="${pageContext.request.contextPath}/param/param4">
        UserName <input type="text" name="name"><br>
        Password <input type="text" name="password"><br>
        Age <input type="text" name="age"><br>
        <input type="submit" value="reg">
    </form>
    **POJO的成员变量的名字要和请求参数的key或者表单name属性的值严格对应**
    
  • 注意1.提交的表单中的name和控制器方法的name同名,那么谁会获取到内容?

    http://localhost:8989/param/param/param4?name=小明&age=12&password=12
    @RequestMapping("param4")
        public String param4(**String name**,User user) {
            System.out.println("user = " + user);
            return  "param1";
     }
    **name形参与user对象的name属性都会获取对应的内容,这个特定在后续前后端分离中会使用。**
    
  • 注意2.

    1. 如果SpringMVC发现控制器形参类型,是8种基本类型+String的话,他会通过形参名与请求参数的key对象,接受数据
    2. 如果SpringMVC发现控制器形参类型,不是8种基本类型+String的话,他会通过形参类型的属性名与请求参数的key对象,接受数据
    3. 如果存在自定义类型转换器不适用于上述规律

3.2.5 接受一组简单变量的请求参数

  • 使用场景

Spring MVC学习随笔-控制器(Controller)开发详解:接受客户端(Client)请求参数

  • 代码

    @RequestMapping("param5")
    public String param5(Integer[] ids) {
        for (Integer id : ids) {
            System.out.println("id = " + id);
        }
        return  "param1";
    }
    // checkbox表单
    <form method="post" action="${pageContext.request.contextPath}/param/param5">
        <input type="checkbox" name="ids" value="1"><br>
        <input type="checkbox" name="ids" value="2"><br>
        <input type="checkbox" name="ids" value="3"><br>
        <input type="checkbox" name="ids" value="4"><br>
        <input type="checkbox" name="ids" value="5"><br>
        <input type="submit" value="reg">
    </form>
    
  • 细节分析 以List类举例

    @RequestMapping("param6")
    public String param6(ArrayList<Integer> ids) {
        for (Integer id : ids) {
            System.out.println("id = " + id);
        }
        return  "param1";
    }
    没有异常,但接收不到数据:SpringMVC会按照POJO的匹配方式,进行成员变量查找
    
    @RequestMapping("param6")
        public String param6(List<Integer> ids) {
            for (Integer id : ids) {
                System.out.println("id = " + id);
            }
            return  "param1";
        }
    抛出异常:SpringMVC无法提供具体的实现类、实例化形参
    

3.2.6 接收一组POJO类型对象的请求参数

  • 使用场景

Spring MVC学习随笔-控制器(Controller)开发详解:接受客户端(Client)请求参数

按照POJO的匹配方式,对于非8种基本类型的方法形参,只有将List实例化作为成员变量封装在POJO类中,并将这个类作为形参才能正确接收数据。

  • 代码

    **// POJO类**
    public class UsersDTO {
        private List<User> users = new ArrayList<>();
    
        public List<User> getUsers() {
            return users;
        }
    
        public void setUsers(List<User> users) {
            this.users = users;
        }
    }
    **//Controller类**
    @RequestMapping("param7")
        public String param7(UsersDTO usersDTO) {
            List<User> users = usersDTO.getUsers();
            for (User user : users) {
                System.out.println("user = " + user);
            }
            return  "param1";
        }
    
    **//JSP页**
    <form method="post" action="${pageContext.request.contextPath}/param/param7">
        UserName <input type="text" name="users[0].name"><br>
        Password <input type="text" name="users[0].password"><br>
        Age <input type="text" name="users[0].age"><br>
        <hr>
        UserName <input type="text" name="users[1].name"><br>
        Password <input type="text" name="users[1].password"><br>
        Age <input type="text" name="users[1].age"><br>
        <input type="submit" value="submit">
    </form>
    

3.3 接收Client请求参数的总结

Spring MVC学习随笔-控制器(Controller)开发详解:接受客户端(Client)请求参数

3.4@RequestParam注解

作用:用于修饰控制器方法的形参

@RequestMapping("param2")
public String param2(@RequestParam String name,@RequestParam String password)

3.4.1 @RequestParam注解详解

  • 解决请求参数与方法形参名字不一致的问题

    Http请求:http://localhost:8989/param/param1/param1?n=jack&p=1234
    @RequestMapping("/param1")
    public String param1(@RequestParam("n") String name, @RequestParam("p") String password) {
        System.out.println("name = " + name);
        System.out.println("password = " + password);
        return "param1";
    }
    
    
  • 注意

    1. @RequestParam注解简写形式:不书写value书写的内容,@RequestParam默认会把对应形参名作为value属性的值

    2. 使用了@RequestParam注解的形参,客户端必须传递数据,不能省略,否则报错。

    3. POJO类型的形参,不能与@RequestParam注解联用。会报400错误

    4. 典型的应用场景

      htpp请求:http://localhost:8989/param/paramController/param1?id≤10
      @RequestMapping("/param1")
      public String param1(@RequestParam("id<") Integer id) {
      }
      **当提交的数据参数名不符合java的变量命名规则时,可以采用这种方式**
      
  • @RequestParam的required属性

    required = true时:@RequestParam修饰的控制器方法参数,客户端必须提交数据,否则报错,默认值

    required = false时:@RequestParam修饰的控制器方法参数,客户端可以不提交数据,不会报错

    解决了使用@RequestParam注解时,客户端必须传递数据的问题。

  • @RequestParam的defaultValue属性

    • 客户端没有提交数据的时候,给对应的形参提供默认值

      http://localhost:8989/param/paramController/param1?name=jack
      @RequestMapping("/param4")
          public String param4(@RequestParam String name, @RequestParam(defaultValue="9999") String password) {
              System.out.println("name = " + name);
              System.out.println("password = " + password);
              return "param1";
          }
      注意:如果使用了defaultValue,则required属性也默认设置成了false
      
    • 解决控制器方法形参,使用包装器的问题

      @RequestMapping("param6")
      public String param6(@RequestParam(defaultValue = "0") int age) {
          System.out.println("age = " + age);
          return "param1";
      }
      
    • defaultValue典型的使用场景

      默认值操作,一个典型的应用场景是:分页首页查询,不传页号的设计

      http://localhost:8989/param/page/findall
      http://localhost:8989/param/page/findall?pageNum=2
      @RequestMapping("findall")
      public String findall(@RequestParam(defaultValue = "0") int pageNum) {
         
      }
      

3.5 中文请求参数的乱码问题

3.5.1 回顾JavaWeb开发中 中文乱码的解决方案

  • GET请求乱码的解决方案

Spring MVC学习随笔-控制器(Controller)开发详解:接受客户端(Client)请求参数

  • POST请求乱码的解决方案

Spring MVC学习随笔-控制器(Controller)开发详解:接受客户端(Client)请求参数

3.5.2 SpringMVC解决中文字符集乱码

  1. GET请求的中文乱码

    UTF-8字符集,Tomcat8已经内部处理,无需我们处理。GBK字符集或者Tomcat8以前版本,需要配置server.xml

  2. POST请求的中文乱码,SpringMVC提供了过滤器解决

    org.springframework.web.filter.CharacterEncodingFilter

  • web.xml配置(通过alt+insert插入)

    <filter>
        <filter-name>encodingFilter</filter-name>
        <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
        <init-param>
            <param-name>encoding</param-name>
            <param-value>UTF-8</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>encodingFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
    

3.6 SpringMVC的类型转换器

3.6.1 SpringMVC中的内置类型转换器

  • 分析

Spring MVC学习随笔-控制器(Controller)开发详解:接受客户端(Client)请求参数

  • 内置类型转换器的概念

    1. SpringMVC中提供了内置类型转换器,把客户端提交的字符串类型的请求参数,转换承控制器方法参数需要的数据类型

    2. SpringMVC并不是对于所有的类型,都提供了内置的类型转换器,他只是提供了常见类型的转换器

      比如:8种基本类型,常见的集合类型等

  • 原理分析

Spring MVC学习随笔-控制器(Controller)开发详解:接受客户端(Client)请求参数

在SpringMVC启动时,会通过mvc:annotation-driven/把FormattingConversionServiceFactoryBean。引入到SpringMVC体系中。FormattingConversionServiceFactoryBean存储了SpringMVC种所有的内置类型转换器。后续client提交请求参数时,如果对于控制器方法形参不是字符串类型,那么FormattingConversionServiceFactoryBean就会调用对应的类型转换器,进行类型转换,最终完成控制器方法形参的赋值。

3.6.2 SpringMVC中自定义类型转换器

SpringMVC在接收客户端提交请求参数时,如果请求参数对应的控制器方法形参,是非常规数据类型,SpringMVC默认情况下无法进行类型转换。会抛出异常,程序员可以通过自定义类型转换器解决上述问题。例如:日期类型
  • 开发思路

Spring MVC学习随笔-控制器(Controller)开发详解:接受客户端(Client)请求参数

  • 编码

    **// 实现Converter<S,T>接口**
    public class DateConverter implements Converter<String, Date> {
    
        @Override
        public Date convert(String source) {
            Date date = null;
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
            try {
                date = sdf.parse(source);
            } catch (ParseException e) {
                e.printStackTrace();
            }
            return date;
        }
    }
    // **配置类型转换器,让Spring进行对象的创建**
    <bean id="dateConverter" class="com.baizhi.DateConverter"/>
    // **进行类型转换器注册,让SpringMVC能够识别日期类型转换的类型转换器-->**
    <bean id="serviceFactoryBean" class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
            <property name="converters">
                <set>
                    <ref bean="dateConverter"/>
                </set>
            </property>
        </bean>
    // **最后一步**
    <mvc:annotation-driven conversion-service="serviceFactoryBean"/>
    
    // **上述第一步 第二步可以合二为一**
    <bean id="formattingConversionService" class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
            <property name="converters">
                <set>
                    <bean id="converter" class="com.baizhi.DateConverter"/>
                </set>
            </property>
        </bean>
    

3.7 接收其他请求数据

3.7.1 动态参数收集

  • 单值动态参数收集(一个key对应一个请求数据)

    http://localhost:8989/param/param2/param1?name=suns
    http://localhost:8989/param/param2/param1?age=10
    @RequestMapping("/param1")
        public String param1(@RequestParam Map<String, String> params) {
            Set<String> keys = params.keySet();
            for (String key : keys) {
                System.out.println("key = " + key+",value = "+params.get(key));
            }
            return "param1";
        }
    **注意:如果需要接收动态参数,必须保证Map的形参前面加入@RequestParam注解,否则接收不到数据**
    
  • 多值动态参数收集(一个key对应多个请求数据)

    http://localhost:8989/param/param2/param1?id=2&id=3&id=4
    
    **第一种解决思路:通过数组形参接收请求参数**
    @RequestMapping("param5")
    public String param5(Integer[] ids) {
        for (Integer id : ids) {
            System.out.println("id = " + id);
        }
        return  "param1";
    }
    存在的问题:请求参数的key发生改变就接收不到请求数据
    
    第二种解决思路:通过MultiValueMap<K,V> 接收请求参数
    @RequestMapping("/param2")
        public String param2(@RequestParam MultiValueMap<String, String> params) {
            Set<String> keys = params.keySet();
            for (String key : keys) {
                List<String> values = params.get(key);
                System.out.println("key = " + key);
                for (String value : values) {
                    System.out.println("value = " + value);
                }
            }
            return "param1";
        }
    
  • 典型应用场景

Spring MVC学习随笔-控制器(Controller)开发详解:接受客户端(Client)请求参数

3.7.2 接收cookie数据

  • 回顾Servlet中获取的方式

Spring MVC学习随笔-控制器(Controller)开发详解:接受客户端(Client)请求参数

  • SpringMVC获取Cookie的方式

    测试Cookie 通过postman测试
    @RequestMapping("/param4")
    public String param4(@CookieValue("name") String value) {
        System.out.println("value = " + value);
        return "param1";
    }
    推荐使用@CookieValue获取cookie
    
    @RequestMapping("/param3")
    public String param3(HttpServletRequest request) {
        Cookie[] cookies = request.getCookies();
        for (Cookie cookie : cookies) {
            if ("name".equals(cookie.getName())) {
                System.out.println("cookie.getValue() = " + cookie.getValue());
            }
        }
        return "param1";
    }
    这种方式基于Servlet API存在耦合,不推荐使用。
    

3.7.3 接收请求头数据

  • 什么是请求头

Spring MVC学习随笔-控制器(Controller)开发详解:接受客户端(Client)请求参数

  • 获取请求头的方式
    • Servlet中的获取方式

      核心代码
      String value = request.getHeader("key");
      
    • SpringMVC中的获取方式

      @RequestMapping("/param6")
      public String param6(@RequestHeader("Host") String host) {
          System.out.println("host = " + host);
          return "param1";
      }
      推荐使用@RequestHeader的方式获取请求头
      
      @RequestMapping("/param5")
      public String param5(HttpServletRequest request) {
          String host = request.getHeader("Host");
          System.out.println("host = " + host);
          return "param1";
      }
      这种方式存在与Servlet API的耦合问题,不建议后续使用
      

下一章:Spring MVC学习随笔-控制器(Controller)开发详解:调用业务对象、父子工厂拆分(applicationContext.xml、dispatcher.xml)文章来源地址https://www.toymoban.com/news/detail-747313.html

到了这里,关于Spring MVC学习随笔-控制器(Controller)开发详解:接受客户端(Client)请求参数的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 什么是域控制器Domain Controller?

    一个域描述了一组用户、系统、应用程序、网络、数据库服务器和其他任何资源,这些资源都受到一组共同的管理规则的控制。通常,一个域还包括一个物理空间,比如一个办公室或多个办公室。如果你在域内,你就处于一个理论上安全和可信的空间。如果在外面,你就是不

    2024年02月07日
    浏览(52)
  • 5、Kubernetes核心技术 - Controller控制器工作负载

    目录 一、Deployments - 控制器应用 二、Deployment升级回滚和弹性收缩 2.1、创建一个 1.14 版本的 pod 2.2、应用升级 2.3、查看升级状态 2.4、查看历史版本 2.5、应用回滚 2.6、弹性伸缩  三、StatefulSet - 有状态应用 四、DaemonSet - 守护进程 五、Job - 单次任务 六、Cronjob - 定时任务 Deplo

    2024年02月15日
    浏览(28)
  • beego的控制器Controller篇 — 数据处理

    1.1 获取参数 通过如下方式获取数据: GetString(key string) string GetStrings(key string) []string GetInt(key string) (int64, error) GetBool(key string) (bool, error) GetFloat(key string) (float64, error) 例如: 如果需要的数据是其他类型的,例如是 int 类型而不是 int64,那么你需要这样处理: 1.2 获取表单中的

    2024年01月17日
    浏览(38)
  • 第三十章 Unity角色控制器 Character Controller

    在我们之前的章节中,我们已经了解了碰撞体和刚体。但是,对于刚体这个组件来讲,有两种使用方式。其一就是用它来模拟现实世界的移动或碰撞效果(例如,门的开关);其二就是使用代码来控制物体移动或碰撞(例如,角色的行走)。两种方式使用场景不同而已。 本章

    2024年02月08日
    浏览(34)
  • 【P31】JMeter 循环控制器(Loop Controller)

    可以对部分逻辑按常量进行循环迭代 选择线程组右键 添加 逻辑控制器 循环控制器(Loop Controller) Loop Count:设置运行次数,Infinite 勾选为永久运行 2.1、设置循环次数 (1)、测试计划右键 添加 线程(用户) 线程组 参数默认即可 (2)、线程组右键 添加 取样器 调试取样器

    2024年02月07日
    浏览(36)
  • 【P38】JMeter 随机控制器(Random Controller)

    可以让控制器内部的逻辑随机执行一个,一般用来模拟业务的不确定性;随机控制器在线程迭代或者控制器循环的时候均会触发 选择线程组右键 添加 逻辑控制器 随机控制器(Random Controller) 忽略子控制器块(Ignore sub-controller blocks):子控制器功能失效,由交替控制器代替

    2024年02月07日
    浏览(32)
  • 【P30】JMeter 事务控制器(Transaction Controller)

    可以生成一个额外的样本,这样能够将它的所有子元素作为一个计量单元进行监听;事务控制器本身不包含任何业务逻辑,只是组合出一个新的计量单元 选择线程组右键 添加 逻辑控制器 事务控制器(Transaction Controller) Generate parent sample:选中,事务控制器将作为其他取样器

    2024年02月06日
    浏览(70)
  • 【P34】JMeter ForEach控制器(ForEach Controller)

    可以对一个组变量进行循环迭代;该组件通常与后置处理器中的 JSON 提取器、正则提取器、边界提取器等进行联合使用 选择线程组右键 添加 逻辑控制器 ForEach控制器(ForEach Controller) 输入变量前缀(Input variable prefix):默认为一个空字符串作为前缀 开始循环字段(不包含)

    2024年02月06日
    浏览(33)
  • Kubernetes技术--k8s核心技术Controller控制器

    1.Controller概述    Controller是在集群上管理和运行容器的对象。是一个实际存在的对象。 2.pod和Controller之间的关系 pod通过controller实现应用的运维,包括伸缩、滚动升级等操作。 这里pod和controller通过label标签来建立关系。如下所示: 3.Deployment控制器应用场景 -1:部署无状态的应

    2024年02月10日
    浏览(34)
  • 【P33】JMeter 临界部分控制器(Critical Section Controller)

    可以对指定代码块增加同步锁,确保此代码块由单线程执行;通过 Java synchronized 实现 选择线程组右键 添加 逻辑控制器 临界部分控制器(Critical Section Controller) 锁名称(Lock name):锁名为空,认为每个锁为不同的锁;锁名相同,多个锁认为是同一个锁,同一个时间点

    2024年02月07日
    浏览(39)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包