100字范文,内容丰富有趣,生活中的好帮手!
100字范文 > SpringMVC的Controller中常用的三种返回值类型

SpringMVC的Controller中常用的三种返回值类型

时间:2022-12-03 15:15:29

相关推荐

SpringMVC的Controller中常用的三种返回值类型

SpringMVC 通过注解实现的 Controller 常用的返回值类型主要有三种:返回字符串,返回 ModelAndView,返回 void。

先看一下项目的目录结构:

再看一下 springmvc.xml 配置文件的内容:

<?xml version="1.0" encoding="UTF-8"?><beans xmlns="/schema/beans" xmlns:xsi="/2001/XMLSchema-instance" xmlns:context="/schema/context" xmlns:tx="/schema/tx" xmlns:aop="/schema/aop" xmlns:mvc="/schema/mvc" xsi:schemaLocation=" /schema/beans /schema/beans/spring-beans.xsd /schema/context /schema/context/spring-context.xsd /schema/tx /schema/tx/spring-tx.xsd /schema/aop /schema/aop/spring-aop.xsd /schema/mvc /schema/mvc/spring-mvc.xsd"> <!-- 开启spring的组件扫描,自动加载bean --> <context:component-scan base-package="com.lyu.qjl.interview.controller" /> <!-- 可以用mvc的注解驱动 --> <mvc:annotation-driven /> <!-- 配置视图解析器 --> <bean> <!-- 配置视图名的默认前缀 --> <property name="prefix" value="/"></property> <!-- 配置视图名的默认后缀 --> <property name="suffix" value=".jsp"></property> </bean></beans>1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

返回字符串

应用场景1:直接返回视图名称,例如跳转到某个功能主页。

下面的 Controller 是用来处理用户页面的请求,gotoUserEdit 方法是用来处理跳转到用户编辑页面的请求。

package com.lyu.qjl.interview.controller;import java.util.ArrayList;import java.util.List;import org.springframework.stereotype.Controller;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.servlet.ModelAndView;import com.lyu.qjl.interview.entity.User;import com.lyu.qjl.interview.vo.UserVO;/** * 类名称:处理用户请求的handler * 全限定性类名: com.lyu.qjl.interview.controller.UserController * @author 曲健磊 * @date 5月21日下午7:24:07 * @version V1.0 */@Controllerpublic class UserController{ /** * 跳转到编辑用户页面 * @return */ @RequestMapping("/gotoUserEdit") public String gotoUserEdit() { return "userEdit"; }}1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

这个 gotoUserEdit 方法匹配 /gotoUserEdit 请求。返回值为一个 userEdit 字符串,表示的是一个视图名,但是由于我们在 springmvc.xml 中已经配置了视图名的前缀和后缀,所以前端控制器实际上获得的视图名为 prefix配置的值 + returnStr(方法返回值) + suffix配置的值,即 /userEdit.jsp,所以页面最终会跳转到网站根目录下的 userEdit.jsp。

Question:我想访问某个页面我直接去输入这个页面的地址 /userEdit.jsp 不就可以了吗,为什么还要先去请求 SpringMVC,再由它返回?

Answer:对于 WebContent 这一层目录下面的页面,用户如果知道某个 jsp 页面可以直接访问。但是,通常情况下为了保证页面的安全,我们一般的做法是在 WebContent 这一层目录下只留一个引导页面(index.jsp)作为跳转,把网站相关的页面放入 WEB-INF 文件夹下保护起来。因为放在 WEB-INF 文件夹下的页面没有办法通过地址栏直接访问,只能通过后台的跳转来间接的访问,所以就需要请求 SpingMVC 来返回相应的页面。

实际应用中的 web 页面的目录结构:

注:login.jsp, main.jsp, userEdit.jsp, userList.jsp, userMain.jsp 都是放在 WEB-INF 这层目录下的,只有 index.jsp 是放在 WebContext 这一层下的。

测试:直接访问 WEB-INF 文件夹下的 login.jsp 页面的结果如下:

这样我们就没有办法直接从地址栏去访问 WEB-INF 下的 login.jsp 页面了,只能通过 SpringMVC 来进行页面的跳转了。

这里还需要注意一点:由于页面已经放到了 WEB-INF 目录下,所以 springmvc.xml 配置文件中的视图解析器中的前缀也要对应的有所改动:

<?xml version="1.0" encoding="UTF-8"?><beans xmlns="/schema/beans" xmlns:xsi="/2001/XMLSchema-instance" xmlns:context="/schema/context" xmlns:tx="/schema/tx" xmlns:aop="/schema/aop" xmlns:mvc="/schema/mvc" xsi:schemaLocation=" /schema/beans /schema/beans/spring-beans.xsd /schema/context /schema/context/spring-context.xsd /schema/tx /schema/tx/spring-tx.xsd /schema/aop /schema/aop/spring-aop.xsd /schema/mvc /schema/mvc/spring-mvc.xsd"> ... <!-- 配置视图解析器 --> <bean> <!-- 配置视图名的默认前缀 --> <property name="prefix" value="/WEB-INF/"></property> <!-- 配置视图名的默认后缀 --> <property name="suffix" value=".jsp"></property> </bean></beans>1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

扩展:

大家注意到那个放在 WebContent 那一层目录下的 index.jsp 页面了吗?它在实际应用中有什么作用呢?

它一般配置为项目的欢迎页面,即 web.xml 中的 welcome-file。当我们在地址栏输入 localhost:8080/interview 的时候,首先就会访问该页面,然后由该页面向后台发请求,通过后台的 Controller 跳转到被 WEB-INF 文件夹保护起来的登录页面 login.jsp,最后,展现在我们面前的就是一个登录页面。

index.jsp 中的内容如下:

<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8"%><%// 转发一个 "/login" 请求给后台的 Controller,由 Controller 返回 WEB-INF 目录下的 login.jsp 页面request.getRequestDispatcher("/login").forward(request, response);%>1

2

3

4

5

应用场景2:在登录成功的时候重定向到主页面,登录失败的时候转发回登录页面

String 类型的返回值除了返回一个可以被视图解析器解析的视图名以外,还可以返回 含有 redirect 或 forward 标签的字符串,如下:

package com.lyu.qjl.interview.controller;import org.springframework.stereotype.Controller;import org.springframework.ui.Model;import org.springframework.web.bind.annotation.RequestMapping;/** * 类名称:用于处理登录请求的处理器 * 全限定性类名: com.lyu.qjl.interview.controller.LoginController * @author 曲健磊 * @date 5月21日下午7:02:03 * @version V1.0 */@Controllerpublic class LoginController{ @RequestMapping("/loginUser") public String login(String username, String password, Model model) throws Exception { if (username != null && password != null) { if ("admin".equals(username) && "123".equals(password)) { // 登录成功,重定向到主页面 return "redirect:/main"; } else { // 向 request 域中设置错误提示信息 model.addAttribute("loginFlag", "用户名或密码错误"); // 登录失败,转发到登录页面 return "forward:/login"; } } else { // 只是把模型放到request域里面,并没有真正的安排好 model.addAttribute("loginFlag", "用户名或密码错误"); // 登录失败,转发到登录页面 return "forward:/login"; } } @RequestMapping("/login") // 对外部提供接口的时候需要指定某些参数 public String login() { return "login"; } @RequestMapping("/main") public String main() { return "main"; }}1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

redirect:/main 表示这是一个重定向到 /main 的请求, forward:/login 表示这是一个转发到 /login 的请求。

注意:如果在返回的字符串前加上了 redirect 或者 forward 标签,就不会走视图解析器,而是直接转发或重定向到指定的路径,所以对于重定向标签后面就不能加 WEB-INF ,因为重定向是客户端重新发送的请求,WEB-INF 目录下的页面仍然访问不到,但是对于转发标签的话后面可以跟 WEB-INF。

以上就是 Controller 的返回值为 String 时的另一种常见用途。

Question:为什么登录成功需要重定向到主页面?

Answer:因为转发客户端只发送了一次请求,如果登录成功转发到主页面的话,浏览器的地址栏中的 url 保留的是提交表单的请求,此时如果按 F5 刷新,就会造成二次提交表单,增大服务端的压力不说,还影响用户的体验,所以登录成功时要重定向到主页面,这样浏览器的地址栏保留的就是当前主页面的 url,无论怎么刷新都没事。

Question:为什么登录失败需要转发回登录页面?

Answer:用户登录失败,我们需要给用户提供相应的提示信息,如:“用户名密码不匹配”。如果重定向到登录页面,用户就没有办法获取到服务端设置在 request 域里面的错误提示信息,因为重定向的本质是客户端发送了两次请求,在第二次请求里面获取不到第一次请求中的数据,所以没有办法给用户相应的提示信息。而转发只发送了一次请求,转发回登录页面的时候可以获取到请求中的数据,所以登录失败时需要转发会登录页面。

返回ModelAndView

应用场景:其实这种返回值的应用场景比较随意,既可以用来做页面的跳转,也可以在跳转到页面的时候携带一些数据,例如:查询用户列表。

package com.lyu.qjl.interview.controller;import java.util.ArrayList;import java.util.List;import org.springframework.stereotype.Controller;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.servlet.ModelAndView;import com.lyu.qjl.interview.entity.User;import com.lyu.qjl.interview.vo.UserVO;/** * 类名称:处理用户请求的handler * 全限定性类名: com.lyu.qjl.interview.controller.UserController * @author 曲健磊 * @date 5月21日下午7:24:07 * @version V1.0 */@Controllerpublic class UserController{ @RequestMapping("/getUserList") public ModelAndView getUserList() { System.out.println("进入getUseList"); ModelAndView modelAndView = new ModelAndView(); List<User> userList = new ArrayList<User>(); User user1 = new User("arry", 18, "男"); user1.setUserId(1L); User user2 = new User("cc", 28, "女"); user2.setUserId(2L); User user3 = new User("dd", 38, "男"); user3.setUserId(3L); userList.add(user1); userList.add(user2); userList.add(user3); // 将数据放入modelAndView对象 modelAndView.addObject("userList", userList); // 将返回的逻辑视图名称放入modelAndView对象 modelAndView.setViewName("userList"); return modelAndView; }}1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

如果想在跳转到某个页面的时候携带一些数据,调用 ModelAndView 对象的 addObject 方法设置一些属性即可,不想带数据也可以不设置,但是必须得设置视图名 setViewName ,要不然它哪知道返回到哪个页面去呢?

返回void

如果是返回 void 会,就必须要在方法的参数中添加 HttpServletRequest 和 HttpServletResponse 来进行页面的跳转,代码如下:

public void test(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 转发到指定页面 request.getRequestDispatcher("xxx").forward(request, response); // 或者重定向到指定页面 response.sendRedirect("/xxx");}1

2

3

4

5

6

其实,从本质上来说前面两种方法(String,ModelAndView)就是间接调用的 request 和 response 这个两个对象来进行页面的跳转,以及数据的存储。

稍微的总结一下,这篇文章主要讲了 SpringMVC 的 Controller 的三种返回值类型:String,ModelAndView,void。在讲 String 的时候扩展了一些 redirect 和 forward 标签,提了一下在实际应用中转发和重定向的用处,以及实际项目中需要把页面放入 WEB-INF 目录里保护起来。ModelAndView 可以携带数据也可以不携带数据,以及前两种方法本质上都是在操作 request 和 response 对象。希望文章对大家能有所帮助。

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。