处理完传参和业务逻辑处理后,最后就是带着处理完的数据做页面跳转了,在JavaWeb中做页面跳转分两步,第一步是使用作用域传递、存储数据,第二步是做页面跳转,页面跳转一般又分为forward跳转和redirect跳转。
1. 核心区别
forward:
1. 一次请求
2. 地址栏不变
3. 可以通过request作用域传递数据
redirect:
1. 多次请求
2. 地址栏改变
3. 不能通过request作用域传递数据
4. 可以跨域跳转
2. 如何选择
1. 如果本次功能需求,已经完成,则使用redirect跳转
2. 如果本次功能需求,没有完成,则使用forward 跳转
redirect跳转是用url?拼接的方式传递数据的,例:
package com.jin;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* @author jinyunlong
* @date 2022/2/14 11:16
* @profession ICBC锅炉房保安
*/
public class AServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("AServlet.service");
resp.sendRedirect("/view/BServlet?name=90900&password=12234");
}
}
package com.jin;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* @author jinyunlong
* @date 2022/2/14 11:16
* @profession ICBC锅炉房保安
*/
public class BServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("BServlet.service");
String name = req.getParameter("name");
String password = req.getParameter("password");
System.out.println("name = " + name);
System.out.println("password = " + password);
}
}
如上在JavaWeb中还需要基于HttpServlet来处理,有耦合,SpringMVC中有接口处理了这个问题。
一、SpringMVC的四种跳转形式
1. 四种跳转指的是:在SpringMVC中控制器与JSP或者控制器与控制器之间的跳转。
1. Controller -- forward --> JSP
2. Controller -- redirect --> JSP
3. Controller -- forward --> Controller
4. Controller -- redirect --> Controller
2. SpringMVC的四种跳转,底层上就是对Servlet跳转的封装。
3. 默认情况下SpringMVC中控制器通过视图解析器跳转到JSP页面,通过的是forward形式。
注意第三点,默认SpringMVC通过视图解析器跳转到JSP页面通过的是forward形式。
forward Controller-->JSP 跳转编码:
package com.jin;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
/**
* @author jinyunlong
* @date 2022/2/16 17:06
* @profession ICBC锅炉房保安
*/
@Controller
@RequestMapping("/view1")
public class ViewController {
@RequestMapping("/view1")
public String view1(){
return "result";
}
// 结合ViewResolver的前缀(prefix)、后缀(suffix)进行拼接成完整的页面,并进行forward跳转
@RequestMapping("/view2")
public String view2(){
return "forward:/result.jsp";
}
}
// 使用了forward:关键字,视图解析器的拼接会失效。所以必须写完整路径。
redirect Controller-->JSP 跳转编码:
package com.jin;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
/**
* @author jinyunlong
* @date 2022/2/16 17:06
* @profession ICBC锅炉房保安
*/
@Controller
@RequestMapping("/view1")
public class ViewController {
@RequestMapping("/view3")
public String view3(){
return "redirect:/result.jsp";
}
}
forward Controller-->Controller 跳转编码:
由forward1跳到forward2,再由forward2跳到jsp页面:
package com.jin;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
/**
* @author jinyunlong
* @date 2022/2/16 17:21
* @profession ICBC锅炉房保安
*/
@Controller
@RequestMapping("/forwardController")
public class ForwardController {
@RequestMapping("/forward1")
public String forward1(){
return "forward:/forwardController/forward2";
}
@RequestMapping("/forward2")
public String forward2(){
return "forward:/forward2.jsp"; //forward2
}
}
redirect Controller-->Controller 跳转编码:
由redirect1跳到redirect2,再由redirect2跳到jsp页面:
package com.jin;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
/**
* @author jinyunlong
* @date 2022/2/17 14:59
* @profession ICBC锅炉房保安
*/
@Controller
@RequestMapping("/redirectController")
public class RedirectController {
@RequestMapping("/redirect1")
public String redirect() {
return "redirect:/redirectController/redirect2";
}
@RequestMapping("/redirect2")
public String redirect2() {
return "redirect:/redirect2.jsp"; //redirect2
// return "redirect2";
}
}
JavaWeb中的三种作用域:
1. HttpServletRequest[简称request作用域]
用于组件间跳转时传递数据
组件指的是 控制器 视图(JSP)
使用方式:
request.setAttribute("name","value");
request.getAttribute("name");
2. HttpSession [简称session作用域]
不用于组件间跳转时传递数据
用于用户会话追踪,只能存储与用户相关的个人数据
如:登录状态、令牌、购物车等
使用方式:
session.setAttribute("name","value");
session.getAttribute("name");
3. ServletContext [简称application作用域]
全局唯一,框架底层使用,多用于存储全局唯一的对象
如:Spring的工厂(容器)、Hibernate(JPA)的SessionFactory、MyBatis的SqlSessionFactory等。
使用方式:
application.setAttribute("name","value");
application.getAttribute("name");
二、SpringMVC中作用域处理
问题:如果还是用HttpServlet,会与ServletAPI耦合,同时也与视图模板技术耦合,在SpringMVC中不建议使用。
1、SpringMVC中request作用域的处理
可以基于Model的方式,或者基于ModelMap的方式:
package com.jin;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import javax.servlet.http.HttpServletRequest;
/**
* @author jinyunlong
* @date 2022/2/17 15:40
* @profession ICBC锅炉房保安
*/
@Controller
@RequestMapping("/view2")
public class View2Controller {
@RequestMapping("/view1")
public String view1(HttpServletRequest request){
System.out.println("View2Controller.view1");
request.setAttribute("name","fuckyou");
// return "view1";
return "redirect:/view1.jsp";
}
@RequestMapping("/view2")
public String view2(Model model){
model.addAttribute("name","shit");
// return "view1";
return "redirect:/view1.jsp";
}
@RequestMapping("/view3")
public String view3(ModelMap modelMap){
modelMap.addAttribute("name","shit");
return "view1";
}
}
<%@ page pageEncoding="utf-8" contentType="text/html; charset=utf-8" %>
<html>
<head></head>
<body>
<h2>fuck you leather man ${requestScope.name}</h2>
</body>
</html>
Model、ModelMap相关细节分析
2、SpringMVC中session作用域的处理
只需使用@SessionAttributes,删除Session作用只需引入SessionStatus对象,执行对应方法即可:
package com.jin;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.SessionAttributes;
import org.springframework.web.bind.support.SessionStatus;
/**
* @author jinyunlong
* @date 2022/2/18 16:56
* @profession ICBC锅炉房保安
*/
@Controller
@RequestMapping("/view3")
@SessionAttributes(value = {"name","address"})
public class View3Controller {
@RequestMapping("/view1")
public String view1(Model model){
model.addAttribute("age",10);
model.addAttribute("name","shit");
return "forward:/view3/view2";
}
@RequestMapping("/view2")
public String view2(SessionStatus sessionStatus){
if (!sessionStatus.isComplete()) {
sessionStatus.setComplete();
}
return "view2";
}
}
<%@ page pageEncoding="utf-8" contentType="text/html; charset=utf-8" %>
<html>
<head></head>
<body>
<h2>fuck you leather man ${sessionScope.name}</h2>
<h2>fuck you leather man ${requestScope.name}</h2>
<h2>fuck you leather man ${requestScope.age}</h2>
</body>
</html>
可见存到session的key为name的内容已经获取不到了。
注意:
1、在modelMap或者model没把adress放到request作用域,@SessionAttributes注解中声明adresss,没有问题,不会报错
2、request作用域和session作用域共用同一对象。
3、SpringMVC中application作用域的处理
全局唯一,框架底层使用,多用于存储全局唯一的对象,实际业务处理场景使用较少,略。