響應(yīng)數(shù)據(jù)和結(jié)果視圖
一、返回值分類
1). 字符串
Controller方法返回字符串可以指定邏輯視圖名,通過(guò)視圖解析器解析為物理視圖地址。
- index.jsp
<a href="${pageContext.request.contextPath}/user/testReturnString">訪問(wèn)測(cè)試</a>
- 控制器
/** 指定邏輯視圖名,經(jīng)過(guò)視圖解析器解析為jsp物理路徑:/WEB_INF/pages/success.jsp */
@RequestMapping("/testReturnString")
public String testReturnString(Model model) {
/** model接口的實(shí)現(xiàn)類是將數(shù)據(jù)存放到request域中!
* 只需要在方法參數(shù)上加上該接口聲明即可,后面的事就交給底層了 */
System.out.println("返回值為字符串");
model.addAttribute("result", "返回值為字符串!");
return "success";
}
- 返回視圖success.jsp
<h1>操作成功!</h1>
<hr>
回饋信息:${result}
2). void
默認(rèn)情況下會(huì)訪問(wèn)視圖解析路徑下對(duì)應(yīng)訪問(wèn)路徑的uri加上".jsp" 的文件,如果不存在將會(huì)報(bào)404錯(cuò)誤!
Servlet原始API可以作為控制器中方法的參數(shù)??梢允褂迷糀PI做一些操作??梢栽?code>controller方法形參上可以定義
request和response,使用request或者response指定響應(yīng)結(jié)果
1. jsp
<%-- 返回值為void --%>
<a href="/springmvc/testReturnVoid">void測(cè)試</a>
2. 控制器代碼
/** 返回值為void,依靠原生Servlet API完成這些操作 */
@RequestMapping("testReturnVoid")
public void testReturnVoid(HttpServletRequest request,
HttpServletResponse response) throws Exception {
/** == 下面的代碼可以寫在此處 == */
}
- 使用request轉(zhuǎn)向頁(yè)面,如下:
使用轉(zhuǎn)發(fā)不會(huì)經(jīng)過(guò)視圖解析器
/* 使用request轉(zhuǎn)向頁(yè)面 */
request.getRequestDispatcher("/WEB-INF/pages/success.jsp").forward(request, response);
- 通過(guò)response頁(yè)面重定向
二次請(qǐng)求
response.sendRedirect("otherPages");
- 通過(guò)response指定響應(yīng)結(jié)果,例如響應(yīng)json數(shù)據(jù)
response.setCharacterEncoding("utf-8");
response.setContentType("application/json;charset=utf-8");
response.getWriter().write("[{name:'lc',age:'23'},{name:'xq',age:'22'}]");
3). ModelAndView
ModelAndView是SpringMVC為我們提供的一個(gè)對(duì)象,該對(duì)象可以作為控制器方法返回值。該對(duì)象中有兩個(gè)方法。
1. ModelAndView源碼分析
- 添加對(duì)象數(shù)據(jù)的方法,底層還是調(diào)用的
ModelMap這個(gè)域?qū)ο?,在?yè)面上可以使用el表達(dá)式${ "attributeName" }獲取域中的數(shù)據(jù)
public ModelAndView addObject(String attributeName, Object attributeValue) {
this.getModelMap().addAttribute(attributeName, attributeValue);
return this;
}
- 用于設(shè)置【邏輯視圖】的名稱,視圖解析器會(huì)根據(jù)名稱前往指定的視圖
public void setViewName(@Nullable String viewName) {
this.view = viewName;
}
2. 案例演示
底層肯定是放到一個(gè)域?qū)ο笾械?,各個(gè)域?qū)ο蠖伎梢匀??太神奇?/p>
- index.jsp
<%-- 返回值為ReturnModelAndView --%>
<a href="/springmvc/testReturnModelAndView">ReturnModelAndView</a>
- 控制器代碼
@Controller
@RequestMapping("/springmvc")
public class AnnotationTestController {
/** 返回 ModeAndVies */
@RequestMapping("/testReturnModelAndView")
public ModelAndView testReturnModelAndView() {
ModelAndView mv = new ModelAndView();
// 添加數(shù)據(jù)到域?qū)ο笾? mv.addObject("username", "弼馬溫");
// 設(shè)置跳轉(zhuǎn)的邏輯視圖
mv.setViewName("success");
return mv;
}
}
- success.jsp
<h3>操作成功!</h3>
username: ${ username }
requestScope.username: ${ requestScope.username } // 使用此種方式,瀏覽器跳轉(zhuǎn)只能是請(qǐng)求轉(zhuǎn)發(fā)。
sessionScope.username: ${ sessionScope.username }
二、使用關(guān)鍵字轉(zhuǎn)發(fā)和重定向【了解】
1). forward轉(zhuǎn)發(fā)
controller方法在提供了String類型的返回值之后,默認(rèn)就是請(qǐng)求轉(zhuǎn)發(fā)。 也可以寫成下面這種形式,了解即可,不推薦使用
- jsp代碼
<%-- 轉(zhuǎn)發(fā) --%>
<a href="springmvc/testForward">testForward</a>
- 控制器代碼
注意,如果使用了
forward:路徑必須寫成實(shí)際視圖的url,不能寫邏輯視圖。使用請(qǐng)求轉(zhuǎn)發(fā),可以轉(zhuǎn)發(fā)到j(luò)sp,也可以轉(zhuǎn)發(fā)到其他的控制器方法。
@Controller
@RequestMapping("/springmvc")
public class AnnotationTestController {
/** 轉(zhuǎn)發(fā)消息 */
@RequestMapping("/testForward")
public String testForward() {
System.out.println("testForward");
return "forward:/WEB-INF/pages/success.jsp";
/* 等效于
request.getRequestDispatcher("/WEB-INF/pages/success.jsp")
.forward(request, response);
*/
}
}
2). Redirect重定向
controller方法提供了個(gè)String類型返回值之后,需要在返回值里面使用
redirect:它相當(dāng)于response.sendRedirect(url),需要注意的是,如果重定向到j(luò)sp頁(yè)面,則jso頁(yè)面不能寫在WEB-INF目錄下,否則無(wú)法找到。
- jsp代碼
<%-- 重定向 --%>
<a href="/springmvc/testRedirect">重定向測(cè)試</a>
- 控制器代碼
框架底層會(huì)自動(dòng)加上項(xiàng)目虛擬路徑,開發(fā)者可以不用寫
@Controller
@RequestMapping("/springmvc")
public class AnnotationTestController {
/** 重定向 */
@RequestMapping("/testRedirect")
public String testRedirect() {
System.out.println("我要開始轉(zhuǎn)發(fā)了");
return "redirect:testForward";
}
}
三、ResponseBody響應(yīng)json數(shù)據(jù)
1). 功能介紹
該注解用于將Controller大方法返回的對(duì)象,通過(guò)HttpMessageConverter接口轉(zhuǎn)換為指定格式的數(shù)據(jù),如json,xml等,通過(guò)Response響應(yīng)給客戶端。
2). 使用案例
SpringMVC模式用MappingJacksonHttpMessageConverter對(duì)json數(shù)據(jù)進(jìn)行轉(zhuǎn)換,需要導(dǎo)入jackson的坐標(biāo)
- 需求:使用@ResponseBody注解實(shí)現(xiàn)將controller方法返回對(duì)象轉(zhuǎn)換為json響應(yīng)給客戶端。
- 需要導(dǎo)入的maven坐標(biāo)
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>2.9.0</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.0</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.9.0</version>
</dependency>
- jsp核心代碼
注意,json數(shù)據(jù)封裝時(shí),變量名得加上雙引號(hào)
"",而且整個(gè)數(shù)據(jù)都必須以字符串的形式上傳!否則會(huì)報(bào)415或者400錯(cuò)誤;只能使用$.ajax的形式,如果使用$.get或者$.post,底層提交的還是表單的形式
<input type="button" value="測(cè)試ajax請(qǐng)求json和響應(yīng)json" id="submit">
</body>
<script src="${pageContext.request.contextPath}/js/jquery-3.3.1.min.js"></script>
<script type="text/javascript">
$(function () {
$("#submit").click(function () {
$.ajax({
type: "post",
url: "${pageContext.request.contextPath}/springmvc/testResponseJson",
contentType: "application/json; charset=utf-8",
data:'{"id":1,"name":"test","money":999.0,"address":{"provinceName": "四川","cityName": "成都" }}',
dataType: "json",
success: function (data) {
console.log(data)
}
})
})
})
</script>
- 控制器代碼
前端發(fā)送的請(qǐng)求體是json格式的字符串,后臺(tái)中使用對(duì)應(yīng)的pojo進(jìn)行封裝。
@Controller
@RequestMapping("/springmvc")
public class AnnotationTestController {
/**
json請(qǐng)求 @RequestBody 注解
json響應(yīng) @ResponseBody 注解*/
@RequestMapping("/testResponseJson")
public @ResponseBody Account testResponseJson(@RequestBody Account account) {
System.out.println("異步請(qǐng)求:" + account);
return account;
}
}