从零开始学习springmvc(2)——请求参数的绑定

【项目地址】 从零开始学习springmvc

二、请求参数的绑定

2.1 准备工作

本节我们会用到HttpServletRequest、HttpServletResponse等关于servlet请求的类,需要引入servlet-api包依赖,这里有必要说明一点的是,java EE规范在2018年更名为Jakarta EE,相应的我们之前使用的包名由javax.xx更名为jakarta.xx。为了适应新标准,我们更新了spring最新版本5.3.13,并引入jakarta.servlet-api

<properties>
    <spring.version>5.3.13</spring.version>
    <thymeleaf.version>3.0.12.RELEASE</thymeleaf.version>
    <servlet-api.version>4.0.4</servlet-api.version>
    <annotation-api.version>1.3.5</annotation-api.version>
</properties>
<dependencies>
    <!--servlet api-->
    <dependency>
        <groupId>jakarta.servlet</groupId>
        <artifactId>jakarta.servlet-api</artifactId>
        <version>${servlet-api.version}</version>
        <scope>provided</scope>
    </dependency>
    <!-- Spring依赖 -->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-webmvc</artifactId>
        <version>${spring.version}</version>
    </dependency>

    <!-- thymeleaf-->
    <dependency>
        <groupId>org.thymeleaf</groupId>
        <artifactId>thymeleaf</artifactId>
        <version>${thymeleaf.version}</version>
    </dependency>
    <dependency>
        <groupId>org.thymeleaf</groupId>
        <artifactId>thymeleaf-spring5</artifactId>
        <version>${thymeleaf.version}</version>
    </dependency>

    <!--annotation-->
    <dependency>
        <groupId>jakarta.annotation</groupId>
        <artifactId>jakarta.annotation-api</artifactId>
        <version>${annotation-api.version}</version>
    </dependency>
</dependencies>
  • 可能遇到的问题

    • @Resource注解无法import,或者注入为空

      添加annotation-api的依赖,并确认版本号

    • 无法启动Tomcat org.apache.catalina.LifecycleException: 子容器启动失败

      解决方法:确认是不是部署的war包存在多个不同版本的spring-web组件,并清理冗余jar包。

      https://blog.csdn.net/AIMINdeCSDN/article/details/103590010

2.2 参数绑定三种方法

2.2.1 通过servlet-api获取参数

我们可以在controller的方法上加参数HttpServletRequestHttpServletResponse,然后通过getParameter()方法获取请求参数,示例代码如下:

  • Controller层

创建一个GET请求/user,并有一个QueryParam参数为id,请求为

GET /user?id=00112233
@Controller
public class UserController {
    @Resource
    private UserService userService;

    @RequestMapping(value = "/user")
    @ResponseBody
    public String getUser(HttpServletRequest request, HttpServletResponse response) {
        String id = request.getParameter("id");
        return userService.getUserName(id);
    }
}
  • Service层

这里我们用hashmap模拟dao层查询数据库操作,查询id为00112233的user为"zhangsan"

@Service
public class UserService {
    private final Map<String, String> userMap = new HashMap<String, String>(){{
        put("00112233", "Zhang San");
        put("00112234", "Yan Si");
    }};

    public String getUserName(String userId) {
        return userMap.get(userId);
    }
}

我们利用postman测试接口,可以看到

我们简单介绍一下常用的方法

// 1.获取QueryParam参数
// 指定参数名的参数值,如果不存在则返回null
request.getParameter(String paramter);
// 获取所有的参数,如果有多个参数用&连接,形如id=00112233&name=zhangsan
request.getQueryString();

// 2.获取url路径参数
// 获取与Servlet中的“url-pattern”中完全匹配的部分
request.getServletPath()
    

2.2.2 通过注解获取(推荐)

由于springmvc的使用,一般获取参数是通过注解获取,常用的注解如下:

  • @PathVariable 获取路径参数
    • value:绑定URL路径参数的名称
    • name:同value
    • requried:是否必选参数,默认为true,必选。
  • @RequestParam 获取QueryParam参数
    • value:绑定请求中的参数名称
    • name:同value
    • requried:是否必选参数,默认为true,必选。
    • defaultValue:参数如果未传时的默认值。
  • @RequestBody 获取body请求体参数,可以将传入的参数序列化为一个对象

下面通过修改上面的示例User示例来演示一下:

增加pojo对象User

@Getter
@Setter
@ToString
public class User {
    private String id;

    private String name;
}

Controller层三个请求

  1. 查询一个用户:GET /user?id=00112233
  2. 添加多个用户:POST /users
  3. 删除一个用户:DELETE /user/{user_id}
@Controller
public class UserController {
    @Resource
    private UserService userService;

    @RequestMapping(value = "/user")
    @ResponseBody
    public String getUser(@RequestParam(value = "id") String id) {
        return userService.getUserName(id);
    }

    @RequestMapping(value = "/users")
    @ResponseBody
    public String getUser(@RequestBody List<User> users) {
        System.out.println(users);
        return "success";
    }

    @RequestMapping(value = "/user/{user_id}")
    @ResponseBody
    public String deleteUser(@PathVariable(value = "user_id") String userId) {
        System.out.println(userId);
        return "success";
    }
}

由于我们使用了post请求,并且将参数序列化为List<User>对象,计划使用json进行序列化和反序列化,所以这里引入json序列化依赖jackson

pom.xml中引入jackson依赖

<jackson.version>2.13.0</jackson.version>

<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>${jackson.version}</version>
</dependency>
  • 注意

    如果请求发现响应码为415,则可能时未引入jackson所致,所以必须引入相关序列化依赖。

为了测试上述三个接口,分别构造请求为:

  1. GET /user?id=00112233

  2. POST /users

    [
        {
            "id": 11223344,
            "name": "Zhang San"
        },
        {
            "id": 55667788,
            "name": "Li Si"
        }
    ]
    
  3. DELETE /user/00112233

利用postman工具测试结果如下:

2.2.3 QueryParam同名参数绑定

​ SpringMvc提供了QueryParam同名参数绑定的机制,对于QueryParam参数,springmvc会自动寻找Controller方法上的同名参数或者实体类的同名属性进行绑定。简单示例如下:

我们修改之前的HelloController,增加两个接口如下:

  1. 查询指定用户名用户:GET /hello?userName=ZhangSan
  2. 查询指定user用户:GET /hello?id=00112233&name=ZhangSan
@Controller
public class HelloController {

    @RequestMapping("/hello")
    @ResponseBody
    public String helloUser(String userName) {
        return "Hi, " + userName;
    }

    @RequestMapping("/hello/user")
    @ResponseBody
    public String helloUser(User user) {
        System.out.println("hello world");
        return "Hi, " + user.getName();
    }
}

上述示例中我们为对String userName@RequestParam注解,经过测试结果如下:

第一个示例中,我们请求参数是userName=ZhangSan,但是未加@RequestParam注解,ZhangSan也能绑定到userName上;同样第二个示例请求的name值也能绑定到user.name上。下面再看两个示例可以看出同名绑定机制:

可以看到上述userNameuser.getName()值都为null,可以看出SpringMVC的同名参数绑定机制。而@RquestParam@PathVariablevalue属性正是解决前后端参数不一致问题。前端的参数一般是带下划线的Kernel风格(user_name),后端一般是小驼峰风格(userName)。而且同名参数绑定机制不易于维护,所以一般推荐通过注解来进行参数绑定。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值