SpringMVC快速入门之请求与响应

发布于:2025-07-24 ⋅ 阅读:(20) ⋅ 点赞:(0)

SpringMVC中请求(Request)与响应(Response)是核心交互流程:客户端通过请求传递数据,服务器处理后通过响应返回结果,掌握请求参数的接收和响应结果的处理,是开发Web接口的基础。

一、请求处理:获取请求参数

SpringMVC提供了多种注解简化请求参数的获取,无需像原生Servlet那样手动调用request.getParameter()

1.1 普通参数获取(@RequestParam)

适用于获取URL查询参数(?name=张三&age=25)或表单提交的参数。

1.1.1 基础用法
@Controller
@RequestMapping("/user")
public class UserController {

    /**
     * 获取普通参数
     * URL示例:/user/query?name=张三&age=25
     */
    @GetMapping("/query")
    public String queryUser(
            // @RequestParam:绑定参数(默认必填)
            @RequestParam String name,
            // 可指定参数名(若参数名与变量名一致,可省略@RequestParam)
            @RequestParam("age") Integer userAge,
            Model model) {
        
        model.addAttribute("message", "姓名:" + name + ",年龄:" + userAge);
        return "result"; // 跳转结果页面
    }
}
1.1.2 可选参数与默认值

若参数非必填,可通过required=false设置,或指定默认值:

/**
 * 可选参数与默认值
 * URL示例:/user/search?keyword=Spring(或无参数)
 */
@GetMapping("/search")
public String search(
        // 可选参数(required=false)
        @RequestParam(required = false) String keyword,
        // 默认值(若参数为空,使用默认值)
        @RequestParam(defaultValue = "10") Integer size,
        Model model) {
        
    model.addAttribute("message", "关键词:" + (keyword == null ? "无" : keyword) + ",每页条数:" + size);
    return "result";
}

核心说明

  • 若参数名与方法参数名一致,@RequestParam可省略(如String name等价于@RequestParam String name);
  • 基本类型(int)需确保参数存在,否则会报错,建议使用包装类(Integer)并设置required=false

1.2 路径变量(@PathVariable)

适用于REST风格的URL(如/user/1),从URL路径中获取参数。

/**
 * 路径变量
 * URL示例:/user/1/detail
 */
@GetMapping("/{id}/detail")
public String getUserDetail(
        // 从路径中获取id(与URL中的{id}对应)
        @PathVariable Integer id,
        Model model) {
        
    model.addAttribute("message", "查询ID为" + id + "的用户详情");
    return "result";
}

进阶用法:多路径变量

/**
 * 多路径变量
 * URL示例:/user/1/order/100
 */
@GetMapping("/{userId}/order/{orderId}")
public String getOrder(
        @PathVariable("userId") Integer uId,
        @PathVariable Integer orderId, // 变量名与{orderId}一致,可省略value
        Model model) {
        
    model.addAttribute("message", "用户ID:" + uId + ",订单ID:" + orderId);
    return "result";
}

1.3 表单数据绑定到对象

当参数较多时(如用户注册),可将参数自动绑定到Java对象。

1.3.1 定义实体类
package com.example.pojo;

import lombok.Data;

@Data // Lombok注解,自动生成getter/setter
public class User {
    private String username;
    private Integer age;
    private String email;
}
1.3.2 绑定对象参数
/**
 * 表单数据绑定到对象
 * 表单提交示例:username=张三&age=25&email=test@example.com
 */
@PostMapping("/register")
public String registerUser(
        // 自动将参数绑定到User对象(参数名与对象属性名一致)
        User user,
        Model model) {
        
    model.addAttribute("message", "注册用户:" + user.getUsername() 
            + ",年龄:" + user.getAge() 
            + ",邮箱:" + user.getEmail());
    return "result";
}

核心说明

  • 要求表单参数名或查询参数名与对象的属性名一致(如username对应user.getUsername());
  • 支持嵌套对象(如User包含Address对象,参数名需为address.city)。

1.4 获取请求头与Cookie(@RequestHeader、@CookieValue)

1.4.1 获取请求头
/**
 * 获取请求头
 */
@GetMapping("/header")
public String getHeader(
        // 获取User-Agent请求头
        @RequestHeader("User-Agent") String userAgent,
        // 获取Accept请求头
        @RequestHeader("Accept") String accept,
        Model model) {
        
    model.addAttribute("message", "浏览器信息:" + userAgent + ",Accept:" + accept);
    return "result";
}
1.4.2 获取Cookie
/**
 * 获取Cookie
 */
@GetMapping("/cookie")
public String getCookie(
        // 获取名为JSESSIONID的Cookie值
        @CookieValue(value = "JSESSIONID", required = false) String sessionId,
        Model model) {
        
    model.addAttribute("message", "JSESSIONID:" + (sessionId == null ? "无" : sessionId));
    return "result";
}

1.5 获取JSON请求体(@RequestBody)

适用于接收前端发送的JSON数据(如Ajax请求),需结合@ResponseBody使用。

1.5.1 依赖准备

确保添加Jackson依赖(用于JSON解析):

<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.13.3</version>
</dependency>
1.5.2 接收JSON数据
/**
 * 接收JSON请求体
 * 请求体示例:{"username":"张三","age":25}
 */
@PostMapping("/json")
@ResponseBody // 返回JSON(而非跳转页面)
public User receiveJson(@RequestBody User user) {
    // 处理逻辑(如保存用户)
    user.setUsername(user.getUsername() + "_processed"); // 修改用户名
    return user; // 返回处理后的对象(自动转为JSON)
}

测试方式
使用Postman发送POST请求:

  • URL:http://localhost:8080/user/json
  • 请求头:Content-Type: application/json
  • 请求体:{"username":"张三","age":25}

响应结果(JSON):

{"username":"张三_processed","age":25,"email":null}

二、响应处理:返回结果给客户端

SpringMVC的响应方式分为两类:页面跳转(返回视图)和数据响应(返回JSON、字符串等)。

2.1 页面跳转(ModelAndView)

通过返回逻辑视图名或ModelAndView实现页面跳转,适用于传统JSP开发。

2.1.1 返回逻辑视图名(推荐)
/**
 * 返回逻辑视图名(默认跳转页面)
 */
@GetMapping("/toIndex")
public String toIndex(Model model) {
    model.addAttribute("title", "首页"); // 向视图传递数据
    return "index"; // 逻辑视图名,由视图解析器转为/WEB-INF/views/index.jsp
}
2.1.2 使用ModelAndView
/**
 * 使用ModelAndView跳转页面
 */
@GetMapping("/toDetail")
public ModelAndView toDetail() {
    ModelAndView mav = new ModelAndView();
    mav.setViewName("detail"); // 设置逻辑视图名
    mav.addObject("id", 1); // 添加数据(等价于Model.addAttribute)
    mav.addObject("name", "商品详情");
    return mav;
}

2.2 重定向与转发

2.2.1 重定向(redirect:)

重定向会发起新的请求,地址栏URL会变化,之前的Model数据会丢失:

/**
 * 重定向
 */
@GetMapping("/redirect")
public String redirect() {
    // 重定向到首页(可跳转至其他Controller接口)
    return "redirect:/toIndex";
}
2.2.2 转发(forward:)

转发是服务器内部跳转,地址栏URL不变,Model数据可共享:

/**
 * 转发
 */
@GetMapping("/forward")
public String forward() {
    // 转发到详情页(仅能跳转至当前应用内的路径)
    return "forward:/toDetail";
}

2.3 返回JSON数据(@ResponseBody)

适用于Ajax请求或前后端分离项目,通过@ResponseBody将对象转为JSON返回。

2.3.1 基础用法
@Controller
@RequestMapping("/api/user")
public class UserApiController {

    /**
     * 返回单个对象
     * URL:/api/user/1
     */
    @GetMapping("/{id}")
    @ResponseBody // 将返回值转为JSON
    public User getUser(@PathVariable Integer id) {
        // 模拟查询数据库
        User user = new User();
        user.setUsername("张三");
        user.setAge(25);
        user.setEmail("zhangsan@example.com");
        return user; // 自动转为JSON
    }

    /**
     * 返回集合
     * URL:/api/user/list
     */
    @GetMapping("/list")
    @ResponseBody
    public List<User> getUserList() {
        List<User> list = new ArrayList<>();
        list.add(new User("张三", 25, "zhangsan@example.com"));
        list.add(new User("李四", 28, "lisi@example.com"));
        return list; // 自动转为JSON数组
    }

    /**
     * 返回自定义结果(统一响应格式)
     * URL:/api/user/login
     */
    @PostMapping("/login")
    @ResponseBody
    public Result login(
            @RequestParam String username,
            @RequestParam String password) {
        if ("admin".equals(username) && "123456".equals(password)) {
            // 登录成功
            return Result.success("登录成功", new User(username, 0, null));
        } else {
            // 登录失败
            return Result.error("用户名或密码错误");
        }
    }
}

// 统一响应结果类
@Data
class Result {
    private int code; // 状态码(200成功,400失败)
    private String message; // 提示信息
    private Object data; // 数据

    // 成功响应
    public static Result success(String message, Object data) {
        Result result = new Result();
        result.code = 200;
        result.message = message;
        result.data = data;
        return result;
    }

    // 错误响应
    public static Result error(String message) {
        Result result = new Result();
        result.code = 400;
        result.message = message;
        return result;
    }
}

测试结果
访问/api/user/1,响应JSON:

{"username":"张三","age":25,"email":"zhangsan@example.com"}

访问/api/user/login?username=admin&password=123456,响应JSON:

{"code":200,"message":"登录成功","data":{"username":"admin","age":0,"email":null}}
2.3.2 @RestController简化配置

若控制器所有方法都返回JSON,可使用@RestController替代@Controller(自动为所有方法添加@ResponseBody):

// @RestController = @Controller + @ResponseBody
@RestController
@RequestMapping("/api/book")
public class BookApiController {

    // 无需添加@ResponseBody,自动返回JSON
    @GetMapping("/{id}")
    public Book getBook(@PathVariable Integer id) {
        return new Book(id, "SpringMVC教程", "技术书籍");
    }
}

三、实战案例:用户注册与查询

结合请求与响应的核心知识点,实现用户注册(表单提交)和查询(JSON响应)功能。

3.1 注册页面(register.jsp)

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>用户注册</title>
</head>
<body>
<form action="/user/register" method="post">
    用户名:<input type="text" name="username"><br>
    年龄:<input type="number" name="age"><br>
    邮箱:<input type="email" name="email"><br>
    <button type="submit">注册</button>
</form>
</body>
</html>

3.2 结果页面(result.jsp)

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>结果页</title>
</head>
<body>
<h1>${message}</h1>
</body>
</html>

3.3 Controller完整实现

@Controller
@RequestMapping("/user")
public class UserController {

    // 跳转注册页面
    @GetMapping("/toRegister")
    public String toRegister() {
        return "register";
    }

    // 处理注册(表单提交)
    @PostMapping("/register")
    public String register(User user, Model model) {
        // 模拟保存用户(实际项目中调用Service)
        model.addAttribute("message", "注册成功!用户信息:" + user);
        return "result";
    }

    // 按条件查询(返回JSON)
    @GetMapping("/api/query")
    @ResponseBody
    public Result query(
            @RequestParam(required = false) String username,
            @RequestParam(required = false) Integer minAge) {
        // 模拟查询
        List<User> users = new ArrayList<>();
        users.add(new User("张三", 25, "zhangsan@example.com"));
        users.add(new User("李四", 30, "lisi@example.com"));
        return Result.success("查询成功", users);
    }
}

3.4 测试流程

  1. 访问/user/toRegister,填写表单提交;
  2. 注册成功后跳转至结果页,显示用户信息;
  3. 访问/user/api/query?username=张三,获取JSON格式的查询结果。

四、常见问题与避坑指南

4.1 参数绑定失败(400 Bad Request)

错误信息Failed to convert value of type 'java.lang.String' to required type 'java.lang.Integer'

原因

  • 参数类型不匹配(如前端传递字符串,后端接收为Integer);
  • 缺少必填参数(@RequestParam默认必填)。

解决方案

  • 确保参数类型匹配(如年龄参数传递数字,而非字符串);
  • 非必填参数添加required=false
  • 若参数可能为空,使用包装类(Integer)而非基本类型(int)。

4.2 JSON解析失败(400 Bad Request)

错误信息HttpMessageNotReadableException: JSON parse error

原因

  • 请求头未设置Content-Type: application/json
  • JSON格式错误(如缺少引号、逗号);
  • JSON字段与对象属性不匹配(如拼写错误)。

解决方案

  • 发送JSON请求时,务必设置Content-Type: application/json
  • 检查JSON格式(可通过JSON校验工具验证);
  • 确保JSON字段名与对象属性名一致(区分大小写)。

4.3 @ResponseBody返回406 Not Acceptable

错误信息406 Not Acceptable

原因

  • 缺少Jackson依赖,无法将对象转为JSON;
  • 请求头Accept设置不当(如仅接受text/html,但返回JSON)。

解决方案

  • 添加Jackson依赖(jackson-databind);
  • 检查请求头Accept是否包含application/json(或不限制Accept)。

总结:请求与响应的核心要点

SpringMVC的请求与响应是前后端交互的核心:

  1. 请求处理

    • 普通参数用@RequestParam,路径参数用@PathVariable
    • 多参数用对象绑定,JSON参数用@RequestBody
    • 灵活使用可选参数和默认值,避免参数缺失错误。
  2. 响应处理

    • 页面跳转返回逻辑视图名,配合Model传递数据;
    • JSON响应用@ResponseBody@RestController
    • 重定向与转发需区分使用场景(重定向适合外部链接,转发适合内部跳转)。
  3. 避坑关键

    • 参数绑定注意类型匹配和必填性;
    • JSON处理确保依赖正确和格式规范;
    • 前后端约定参数名和数据格式,减少沟通成本。

若这篇内容帮到你,动动手指支持下!关注不迷路,干货持续输出!
ヾ(´∀ ˋ)ノヾ(´∀ ˋ)ノヾ(´∀ ˋ)ノヾ(´∀ ˋ)ノヾ(´∀ ˋ)ノ


网站公告

今日签到

点亮在社区的每一天
去签到