1.SpringMVC 和 Struts2 的優略分析
共同點:
-
它們都是表現層框架,都是基於 MVC 模型編寫的。
-
它們的底層都離不開原始 ServletAPI。
-
它們處理請求的機制都是一個核心控制器。
區別:
-
Spring MVC 的入口是 Servlet, 而 Struts2 是 Filter。
-
Spring MVC 是基於方法設計的,而 Struts2 是基於類,Struts2 每次執行都會創建一個動作類。所以 Spring MVC 會稍微比 Struts2 快些。
-
Spring MVC 使用更加簡潔,同時還支持 JSR303, 處理 ajax 的請求更方便。
(JSR303 是一套 JavaBean 參數校驗的標准,它定義了很多常用的校驗注解,我們可以直接將這些注解加在我們 JavaBean 的屬性上面,就可以在需要校驗的時候進行校驗了。)
-
Struts2 的 OGNL 表達式使頁面的開發效率相比 Spring MVC 更高些,但執行效率並沒有比 JSTL 提升,尤其是 struts2 的表單標簽,遠沒有 html 執行效率高。
2.SpringMVC不同返回值類型的響應
准備工作:在webapp下創建一個response.jsp頁面
在WEB-INF/pages目錄下創建一個success.jsp頁面
創建一個User類(username,password,age三個屬性)
創建一個UserController
2.1.返回值是String類型的響應
controller 方法返回字符串可以指定邏輯視圖名,通過視圖解析器解析為物理視圖地址。
使用這種方法會通過視圖解析器解析出對應地址:WEB-INF/pages/xxx.jsp
2.1.1.在response.jsp頁面寫一個超鏈接
<a href="user/testString" >testString</a>
2.1.2.在UserController寫返回值是String類型的方法
//指定邏輯視圖名,經過視圖解析器解析為 jsp 物理路徑:/WEB-INF/pages/success.jsp @RequestMapping("/testString") public String testString(Model model){ System.out.println("testString方法執行了..."); // 模擬從數據庫中查詢出User對象 User user = new User(); user.setUsername("美美"); user.setPassword("123"); user.setAge(30); // model對象 model.addAttribute("user",user); return "success"; }
2.1.3.在success.jsp頁面通過el表達式取值
<h3>執行成功</h3>
${user.username}
${user.password}
2.2.返回值是void類型的響應
2.2.1.在response.jsp頁面寫一個超鏈接
<a href="user/testVoid" >testVoid</a>
2.2.2.在UserController寫返回值是void類型的方法
因為是void類型,不能像上一個String類型一樣直接返回一個字符串(一個jsp頁面),所以需要用到servlet的原始API,在Controller方法的形參上定義request和response,使用 request 或 response 指定響應結果。
@RequestMapping("/testVoid")
public void testVoid(HttpServletRequest request, HttpServletResponse response) throws Exception {
System.out.println("testVoid方法執行了...");
// 1.使用request轉向頁面,編寫請求轉發的程序
// request.getRequestDispatcher("/WEB-INF/pages/success.jsp").forward(request,response);
// 2.使用response進行頁面重定向
//response.sendRedirect(request.getContextPath()+"/index.jsp");
// 設置中文亂碼
response.setCharacterEncoding("UTF-8");
response.setContentType("text/html;charset=UTF-8");
// 3.直接進行響應,但是在這之前需要設置中文亂碼
response.getWriter().print("你好");
return;
}
注意:請求轉發是一次請求,使用request對象會調用視圖解析器,所以會進入WEB-INF/pages/目錄下
重定向是兩次請求,且不會進入WEB-INF/pages/目錄下
2.3.返回值是ModelAndView類型的響應
2.3.1.在response.jsp頁面寫一個超鏈接
<a href="user/testModelAndView" >testModelAndView</a>
2.3.2.在UserController寫返回值是ModelAndView類型的方法
這個與最前面的返回值是String類型的類似
ModelAndView是SpringMVC提供的一個對象,也會調用視圖解析器幫我們跳轉到xxx.jsp頁面
/** * 返回ModelAndView對象 * 可以傳入視圖的名稱(即跳轉的頁面),還可以傳入對象。 * @return * @throws Exception */ @RequestMapping("/testModelAndView") public ModelAndView testModelAndView(){ // 創建ModelAndView對象 ModelAndView mv = new ModelAndView(); System.out.println("testModelAndView方法執行了..."); // 模擬從數據庫中查詢出User對象 List<User> users = new ArrayList<>(); User user1 = new User(); user1.setUsername("小鳳"); user1.setPassword("456"); user1.setAge(30); User user2 = new User(); user1.setUsername("智障"); user1.setPassword("789"); users.add(user1); users.add(user2); // 把users對象存儲到mv對象中,也會把user對象存入到request對象 mv.addObject("users",users); // 跳轉到哪個頁面(設置邏輯視圖名,視圖解析器會根據名稱前往指定的視圖) mv.setViewName("success"); return mv; }
2.3.3.在success.jsp頁面通過el表達式取值
<h3>執行成功</h3>
${user.username}
${user.password}
2.4.響應之使用關鍵字forword和redirect進行頁面跳轉
controller 方法在提供了 String 類型的返回值之后,默認就是請求轉發。
/** * 使用關鍵字的方式進行轉發或者重定向 * @return */ @RequestMapping("/testForwardOrRedirect") public String testForwardOrRedirect(){ System.out.println("testForwardOrRedirect方法執行了..."); // 請求的轉發 // return "forward:/WEB-INF/pages/success.jsp"; // 重定向 return "redirect:/index.jsp"; }
注意:如果用了 formward:則路徑必須寫成實際視圖 url,不能寫邏輯視圖。
使用請求轉發,它相當於於“request.getRequestDispatcher("url").forward(request,response)”。使用請求 轉發,既可以轉發到 jsp,也可以轉發到其他的控制器方法。
如果是重定向到 jsp 頁面,則 jsp 頁面不 能寫在 WEB-INF 目錄中,否則無法找到。
3.ResponseBody響應json數據
前面所記錄的不管通過何種方式,都要先跳轉到一個jsp頁面進行響應,如果頁面發送的是一個ajax請求,則可以通過ResponseBody進行響應。
ResponseBody注解(獲得請求體的全部內容):該注解用於將 Controller 的方法返回的對象,通過 HttpMessageConverter 接口轉換為指定格式的 數據如:json,xml 等,通過 Response 響應給客戶端
3.1.首先需要在webapp下建立js/jquery.min.js文件
3.2.在response.jsp頁面引入該文件
<script src="${pageContext.request.contextPath}/js/jquery.min.js"></script>
3.3.配置靜態文件不攔截
由於之前在web.xml中配置前端控制器的時候攔截了所有資源,導致一個問題就是靜態資源(img、css、js)也會被攔截到,不能被使用,
所以此時需要配置不攔截靜態資源。
mvc:resource標簽配置不過濾
location元素表示webapp目錄下的包下的所有文件
mapping元素表示以/static開頭的所有請求路徑,如/static/a 或者/static/a/b
<!-- 設置靜態資源不過濾 -->
<mvc:resources location="/css/" mapping="/css/**"/> <!-- 樣式 -->
<mvc:resources location="/images/" mapping="/images/**"/> <!-- 圖片 -->
<mvc:resources location="/js/" mapping="/js/**"/> <!-- javascript -->
3.4.在response.jsp頁面寫ajax請求
<script>
// 頁面加載,綁定單擊事件
$(function(){
$("#btn").click(function(){
// alert("hello btn");
// 發送ajax請求
$.ajax({
// 編寫json格式,設置屬性和值
url:"user/testAjax", //請求地址,必須與controller層請求地址相對應
contentType:"application/json;charset=UTF-8",//發送數據給服務器端時的編碼類型,此處為json類型
data:'{"username":"hehe","password":"123","age":30}',//發送到服務器端的數據內容,key值與Javabean中的屬性名相同,才能封裝到對象
dataType:"json", //服務器返回的數據類型
type:"post", //請求方式,默認get
success:function(data){//請求成功后的回調函數
// data服務器端響應的json的數據,進行解析
alert(data);//彈出對象
alert(data.username);//彈出用戶名
alert(data.password);//彈出密碼
alert(data.age);//彈出年齡
}
});
});
});
</script>
注意:發送到服務器的內容那塊,將key值與Javabean中的屬性一一對應,才可以進行封裝,除此之外,還需要用到幾個jar包:
<dependency>
<goupId>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>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>2.9.0</version>
</dependency>
3.5.編寫controller方法
/** * 模擬異步請求響應 */ @RequestMapping("/testAjax") public @ResponseBody User testAjax(@RequestBody User user){ System.out.println("testAjax方法執行了..."); // 客戶端發送ajax的請求,傳的是json字符串,后端把json字符串封裝到user對象中 System.out.println(user); // 做響應,模擬更新數據庫,將用戶名和年齡改了,密碼沒有更改 user.setUsername("haha"); user.setAge(40); // 做響應,只需返回一個User對象即可 return user; }
注意:由於key值和對象屬性一一對應,封裝到對象中去了,所以@RequestBody后邊就直接寫User,
