对应代码:
com.qcby.controller.BackValueController类上一级映射@RequestMapping("/hello")视图解析器配置:prefix = /WEB-INF/pages/ suffix = .jsp 即 return "suc" 最终跳转 /WEB-INF/pages/suc.jsp
总览
| 序号 | 返回值类型 | 关键点 | 访问路径 |
|---|---|---|---|
| 1 | String(视图名) | 走视图解析器拼接前后缀 | /hello/test |
| 2 | void | 使用 request response 原生 API 自行完成响应 | /hello/test1 |
| 3 | ModelAndView | 视图名和数据一次性返回 | /hello/test2 |
| 4 | Model + String | Model 存放数据 String 返回视图名 | /hello/test3 |
| 5 | String + forward: | 请求转发 可以访问 WEB-INF 资源 | /hello/test4 |
| 6 | String + redirect: | 重定向 浏览器地址发生改变 | /hello/test5 |
| 7 | @ResponseBody + Java 对象 | 对象转为 JSON 写入响应体 多用于 ajax 请求 | /hello/test6 |
1 返回 String 走视图解析器
这是最基础的返回方式 返回字符串会被识别为逻辑视图名 交由视图解析器拼接前缀后缀 完成页面跳转
@RequestMapping("/test")
public String sayhello() {
System.out.println("返回String走视图解析器");
return "suc";
}
注意事项
1 最终访问地址为类注解地址拼接方法注解地址 /hello/test
2 拼接规则 prefix + 返回值 + suffix 返回值不需要书写路径和后缀.jsp
3 底层本质是请求转发 浏览器地址栏不会变化 属于一次请求
2 返回 void 使用 Servlet 原生 API 响应
方法返回值为 void 时 SpringMVC 认为由开发者手动处理响应逻辑 有三种常用实现方式
@RequestMapping("/test1")
public void sayhello01(HttpServletRequest request, HttpServletResponse response) {
System.out.println("返回void第二种响应请求形式");
// 方式一 直接向页面输出文本数据
response.getWriter().write("asda");
// 方式二 请求转发 可以访问WEB-INF下资源
// request.getRequestDispatcher("/WEB-INF/pages/suc.jsp").forward(request, response);
// 方式三 重定向跳转
// response.sendRedirect("https://www.baidu.com");
}
注意事项
1 void 方法内如果已经执行 write 输出数据 不能再返回视图名 否则框架继续执行视图转发会清空缓冲区 页面内容丢失甚至抛出异常
2 请求转发和重定向只能选择一种 并且要在输出内容之前执行
3 该方式不会使用视图解析器的前后缀配置 资源路径必须写完整
3 返回 ModelAndView 视图和数据一起返回
@RequestMapping("/test2")
public ModelAndView sayhello02() {
ModelAndView mv = new ModelAndView();
mv.setViewName("suc");
mv.addObject("msg", "返回modelAndView对象成功");
return mv;
}
suc.jsp 页面使用 EL 表达式取值 ${msg}
注意事项
1 setViewName 填写逻辑视图名 会自动走视图解析器
2 addObject 等价于 request.setAttribute 数据存入 request 域
3 适合同时需要页面跳转和携带数据的场景 是早期比较常用写法
4 返回 String 搭配 Model 参数 数据视图分离
@RequestMapping("/test3")
public String sayhello03(Model model) {
System.out.println("返回String第四种响应请求形式");
model.addAttribute("msg", "返回model+String形式");
return "suc";
}
注意事项
1 Model 对象由 SpringMVC 自动注入 不需要手动 new 创建
2 和 ModelAndView 最终效果完全一致 写法更加简洁
3 Model Map 都可以用来向 request 域存放数据
5 返回 forward: 请求转发
@RequestMapping("/test4")
public String sayhello04() {
System.out.println("返回字符串第五种响应请求形式,是请求转发");
return "forward:/WEB-INF/pages/suc.jsp";
}
注意事项
1 返回字符串携带 forward 前缀时 不再经过视图解析器 路径必须写完整
2 WEB-INF 目录资源无法直接通过浏览器访问 只能依靠请求转发访问
3 浏览器地址栏不变 一次请求 request 域中的数据可以共享
4 不能转发到当前项目以外的外部地址
6 返回 redirect: 重定向
@RequestMapping("/test5")
public String sayhello05() {
System.out.println("返回字符串第六种响应请求形式,是重定向");
return "redirect:https://www.baidu.com";
}
注意事项
1 跳转到外部网址时 redirect 后不能添加前置 / 如果写 redirect:/百度一下,你就知道 Spring 会识别为项目内路径 出现 404
2 项目内部重定向路径开头加 / 代表从项目根路径匹配 例如 redirect:/hello/test
3 浏览器地址栏会更新 属于两次请求 request 域的数据会丢失
4 重定向不能访问 WEB-INF 内部资源
forward 与 redirect 对比
| 对比项 | forward 请求转发 | redirect 重定向 |
|---|---|---|
| 请求次数 | 1 次 | 2 次 |
| 地址栏状态 | 不变 | 改变 |
| request 域数据 | 可以共享 | 数据丢失 |
| 访问 WEB-INF | 支持 | 不支持 |
| 跳转外部地址 | 不支持 | 支持 |
| 书写格式 | return "forward:/ 路径" | return "redirect:/ 路径" |
7 @ResponseBody Java 对象转为 JSON 返回
多用于前后端分离或者 ajax 异步请求 返回值不再当做视图名称 直接写入响应体给到前端
@ResponseBody
@RequestMapping("/test6")
public User sayhello06(String username, Integer age) {
System.out.println("返回java对象转变为json数据第七种响应请求形式");
System.out.println(username);
System.out.println(age);
User user1 = new User();
user1.setUsername("小萌");
user1.setSex("女");
return user1;
}
前端 ajax 代码 index.jsp
$("#btn").click(function () {
$.ajax({
type: "post",
url: "/hello/test6",
data: {"username": "haha", "age": "20"},
dataType: "json",
success: function (d) {
alert(d.username + " - " + d.sex);
}
});
});
注意事项
1 需要引入 jackson 相关依赖 jackson-databind jackson-core jackson-annotations 缺少依赖会抛出 No converter found for return value of type 异常
2 实体类必须提供无参构造方法和 getter 方法 没有 getter 的字段不会序列化到 JSON
3 当前后端传递普通键值对 后端直接用普通形参接收 如果前端传递 application/json 格式 JSON 字符串 后端需要搭配 @RequestBody 接收 两种接收方式不能混用 混用会出现参数 null
4 方法添加 @ResponseBody 后 不会进入视图解析器 就算返回普通字符串 也会直接把文本输出到页面
5 在 Controller 类上添加 @ResponseBody 等价于 @RestController 该类全部方法都会直接返回数据 不再跳转视图
易错点速查
1 void 方法内执行 response.getWriter ().write 之后 不要再返回视图名
2 redirect 跳转外部地址不要加前置 / 项目内重定向路径需要加 /
3 forward 需要写完整路径 支持访问 WEB-INF redirect 不支持访问 WEB-INF
4 @ResponseBody 需要 jackson 依赖 实体类要有无参构造和 getter
5 application/json 请求搭配 @RequestBody 普通键值对使用普通参数接收 不要混用