如何将Spring-Rest响应传递至JSP视图?
嘿,这个问题我之前也碰到过,其实核心是搞懂@RestController的本质就好办了!
首先明确一点:@RestController 其实是 @Controller + @ResponseBody 的组合注解——它会给类里的所有方法默认加上@ResponseBody,意思是把方法的返回值直接序列化成JSON/XML写入HTTP响应体,而不是把返回值当作视图名去解析渲染JSP。这就是为什么你直接用它的时候没法返回JSP视图的原因。
那怎么同时兼顾REST接口和JSP视图呢?给你两个实用方案:
方案一:用@Controller混合REST和视图返回(最推荐)
放弃类上的@RestController,改用@Controller,然后给需要做REST接口的方法单独加上@ResponseBody。这样同一个控制器里既能输出JSON,又能返回JSP视图,完美结合两者的能力。
举个代码例子:
@Controller @RequestMapping("/user") public class UserController { // 这是一个REST接口,返回JSON数据 @GetMapping("/api/detail") @ResponseBody public User getUserDetail() { User user = new User(); user.setId(1); user.setUsername("Kishore"); user.setEmail("kishore@example.com"); return user; } // 这个方法返回JSP视图,同时把REST接口的数据传递给视图 @GetMapping("/view/detail") public String getUserView(Model model) { // 直接调用上面的业务方法获取数据(不用走HTTP请求,更高效) User user = getUserDetail(); // 把数据放到Model里,JSP就能直接取用 model.addAttribute("userInfo", user); // 返回JSP视图名(假设你的视图解析器配置的前缀是/WEB-INF/views/,后缀是.jsp) return "user-detail"; } }
对应的JSP视图(user-detail.jsp)可以这样写:
<%@ page contentType="text/html;charset=UTF-8" %> <html> <head> <title>User Detail</title> </head> <body> <h2>用户详情</h2> <p>ID:${userInfo.id}</p> <p>用户名:${userInfo.username}</p> <p>邮箱:${userInfo.email}</p> </body> </html>
这样你既能通过/user/api/detail拿到JSON响应,又能通过/user/view/detail访问渲染好的JSP页面,完全满足你的需求。
方案二:保留@RestController,通过转发/内部调用传递数据
如果你不想改已有的@RestController类,可以额外写一个负责视图的@Controller,在里面调用REST接口的逻辑获取数据,再传递给JSP视图。
比如先保留你的REST控制器:
@RestController @RequestMapping("/api/user") public class UserRestController { @GetMapping("/detail") public User getUserDetail() { User user = new User(); user.setId(1); user.setUsername("Kishore"); user.setEmail("kishore@example.com"); return user; } }
然后新增一个视图控制器:
@Controller @RequestMapping("/user") public class UserViewController { // 注入REST控制器,直接调用其方法(内部调用,不走HTTP) @Autowired private UserRestController userRestController; @GetMapping("/view/detail") public String getUserView(Model model) { // 获取REST接口的数据 User user = userRestController.getUserDetail(); model.addAttribute("userInfo", user); return "user-detail"; } }
这种方式适合已经有成熟的REST接口,不想改动原有代码的场景,本质是复用REST层的业务逻辑,再传递给视图层渲染。
为什么Ajax不行?
你提到Ajax只能在当前页面获取响应,这是因为Ajax是客户端异步请求,拿到数据后只能在当前页面用JS渲染,没法触发服务器端的视图跳转或直接返回新的JSP页面。而上面的方案都是服务器端直接返回渲染好的视图,适合需要跳转页面或直接展示完整页面的场景。
总结一下:最省心的方式是用@Controller替代@RestController,按需给方法加@ResponseBody;如果要保留@RestController,就用额外的视图控制器来复用其逻辑。两种方式都能实现你要的Spring-Rest+JSP视图结合的效果。
内容的提问来源于stack exchange,提问作者K Kishore Kumar Reddy

