一、pojo

Spring mvc 會按請求引數名和pojo屬性名進行自動匹配,自動為該物件填充屬性值,並且支援級聯屬性

表單:

<form action="springmvc/testPojo" method="post">
username: <input type="text" name="username"/>
<br>
password: <input type="password" name="password"/>
<br>
email: <input type="text" name="email"/>
<br>
age: <input type="text" name="age"/>
<br>
city: <input type="text" name="address.city"/>
<br>
province: <input type="text" name="address.province"/>
<br>
<input type="submit" value="Submit"/>
</form>

pojo:

User類

private Integer id;

private String username;
private String password;

private String email;
private int age;

private Address address;

Address類

private String province;
private String city;

@RequestMapping("/testPojo")
public String testPojo(User user) {
System.out.println("testPojo: " + user);
return SUCCESS;
}

二、servlet API

Spring mvc 還支援原生的servlet API

可以使用servlet原生的API作為目標方法的引數 具體支援以下型別

HttpServletRequest
HttpServletResponse
HttpSession
java.security.Principal
Locale InputStream
OutputStream
Reader
Writer

@RequestMapping("/testServletAPI")
public void testServletAPI(HttpServletRequest request,
HttpServletResponse response) throws IOException {
System.out.println("testServletAPI, " + request + ", " + response);
return "success";
}

三、spring mvc 處理模型資料之ModelAndView

目標方法的返回值可以使ModelAndView型別。

其中可以包含檢視和模型資訊

spring mvc會把ModelAndView的model中資料放到request域物件中

@RequestMapping(value="/testModelAndView")
public ModelAndView testModelAndView(){
String viewName= "success";
ModelAndView modelAndView = new ModelAndView(viewName);
modelAndView.addObject("time",new Date());
return modelAndView;

}

jsp頁面取值:time:${requestScope.time}

四、spring mvc處理模型資料之Model

目標方法可以新增Map型別(實際上也可以是Model型別或者ModelMap型別的)的引數

@RequestMapping("/testMap")
public String testMap(Map<String, Object> map){
System.out.println(map.getClass().getName());
map.put("names", Arrays.asList("Tom", "Jerry", "Mike"));
return SUCCESS;
}

取值:names: ${requestScope.names }

與ModelAndView的關係是,Map型別也會轉化成ModelAndView型別,其中Map中的值存放到ModelAndView的modelMap中,而方法的返回值放在了ModelAndView的viewName中

五、SessionAttributes註解

除了可以通過屬性名指定需要放到會話中的屬性外(實際上使用的是 value 屬性值),還可以通過模型屬性的物件型別指定哪些模型屬性需要放到會話中(實際上使用的是 types 屬性值)

@SessionAttributes(value={"user"}, types={String.class})

注意: 該註解只能放在類的上面. 而不能修飾方法.

六、ModelAttribute註解(筆記)

/**
* 執行流程:
* 1. 執行 @ModelAttribute 註解修飾的方法: 從資料庫中取出物件, 把物件放入到了 Map 中. 鍵為: user
* 2. SpringMVC 從 Map 中取出 User 物件, 並把表單的請求引數賦給該 User 物件的對應屬性.
* 3. SpringMVC 把上述物件傳入目標方法的引數.
*
* 注意: 在 @ModelAttribute 修飾的方法中, 放入到 Map 時的鍵需要和目標方法入參型別的第一個字母小寫的字串一致!
*
* SpringMVC 確定目標方法 POJO 型別入參的過程
* 1. 確定一個 key:
* 1). 若目標方法的 POJO 型別的引數木有使用 @ModelAttribute 作為修飾, 則 key 為 POJO 類名第一個字母的小寫
* 2). 若使用了 @ModelAttribute 來修飾, 則 key 為 @ModelAttribute 註解的 value 屬性值.
* 2. 在 implicitModel 中查詢 key 對應的物件, 若存在, 則作為入參傳入
* 1). 若在 @ModelAttribute 標記的方法中在 Map 中儲存過, 且 key 和 1 確定的 key 一致, 則會獲取到.
* 3. 若 implicitModel 中不存在 key 對應的物件, 則檢查當前的 Handler 是否使用 @SessionAttributes 註解修飾,
* 若使用了該註解, 且 @SessionAttributes 註解的 value 屬性值中包含了 key, 則會從 HttpSession 中來獲取 key 所
* 對應的 value 值, 若存在則直接傳入到目標方法的入參中. 若不存在則將丟擲異常.
* 4. 若 Handler 沒有標識 @SessionAttributes 註解或 @SessionAttributes 註解的 value 值中不包含 key, 則
* 會通過反射來建立 POJO 型別的引數, 傳入為目標方法的引數
* 5. SpringMVC 會把 key 和 POJO 型別的物件儲存到 implicitModel 中, 進而會儲存到 request 中.
*
* 原始碼分析的流程
* 1. 呼叫 @ModelAttribute 註解修飾的方法. 實際上把 @ModelAttribute 方法中 Map 中的資料放在了 implicitModel 中.
* 2. 解析請求處理器的目標引數, 實際上該目標引數來自於 WebDataBinder 物件的 target 屬性
* 1). 建立 WebDataBinder 物件:
* ①. 確定 objectName 屬性: 若傳入的 attrName 屬性值為 "", 則 objectName 為類名第一個字母小寫.
* *注意: attrName. 若目標方法的 POJO 屬性使用了 @ModelAttribute 來修飾, 則 attrName 值即為 @ModelAttribute
* 的 value 屬性值
*
* ②. 確定 target 屬性:
* > 在 implicitModel 中查詢 attrName 對應的屬性值. 若存在, ok
* > *若不存在: 則驗證當前 Handler 是否使用了 @SessionAttributes 進行修飾, 若使用了, 則嘗試從 Session 中
* 獲取 attrName 所對應的屬性值. 若 session 中沒有對應的屬性值, 則丟擲了異常.
* > 若 Handler 沒有使用 @SessionAttributes 進行修飾, 或 @SessionAttributes 中沒有使用 value 值指定的 key
* 和 attrName 相匹配, 則通過反射建立了 POJO 物件
*
* 2). SpringMVC 把表單的請求引數賦給了 WebDataBinder 的 target 對應的屬性.
* 3). *SpringMVC 會把 WebDataBinder 的 attrName 和 target 給到 implicitModel.
* 近而傳到 request 域物件中.
* 4). 把 WebDataBinder 的 target 作為引數傳遞給目標方法的入參.
*/

/**
* 1. 有 @ModelAttribute 標記的方法, 會在每個目標方法執行之前被 SpringMVC 呼叫!
* 2. @ModelAttribute 註解也可以來修飾目標方法 POJO 型別的入參, 其 value 屬性值有如下的作用:
* 1). SpringMVC 會使用 value 屬性值在 implicitModel 中查詢對應的物件, 若存在則會直接傳入到目標方法的入參中.
* 2). SpringMVC 會一 value 為 key, POJO 型別的物件為 value, 存入到 request 中.
*/

@ModelAttribute
public void getUser(@RequestParam(value="id",required=false) Integer id,
Map<String, Object> map){
System.out.println("modelAttribute method");
if(id != null){
//模擬從資料庫中獲取物件
User user = new User(1, "Tom", "123456", "[email protected]", 12);
System.out.println("從資料庫中獲取一個物件: " + user);

map.put("user", user);
}
}

@RequestMapping("/testModelAttribute")
public String testModelAttribute(User user){
System.out.println("修改: " + user);
return SUCCESS;
}

七、檢視和檢視解析器

執行流程:請求方法執行完成之後,不管返回的是一個String、Model或ModelMap型別的,Spring mvc會在內部將他們裝配成一個ModelAndView物件,Spring mvc藉助於檢視解析器,得到真正的物理檢視,一個view物件,最終呼叫view render方法得到相應結果。常用的檢視InternalResourceView,檢視解析器InternalResourceViewResolver,InternalResourceView用來建立jsp,InternalResourceViewResolver是支援InternalResourceView的解析器,InternalResourceView是用來建立在同一個web應用下用來轉發的結果

八、JSTL

若專案中匯入了

jstl.jar
standard.jar

兩個jar包,則spring mvc會自動把檢視由InternalResourceView 轉為 JstlView

若使用JSTL的fmt標籤,則需要在Spring MVC的配置檔案中配置國際化資原始檔

<!-- 配置國際化資原始檔 -->
<bean id="messageSource"
class="org.springframework.context.support.ResourceBundleMessageSource">
<property name="basename" value="i18n"></property>
</bean>

使用方法:①匯入jar包②編寫國際化檔案i18n.properties③在Spring MVC的配置檔案中配置國際化資原始檔

④在jsp中匯入ftm標籤:<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>

⑤使用ftm標籤:<fmt:message key="i18n.username"></fmt:message>

九、<mvc:view-controller/>的使用

<!-- 配置直接轉發的頁面 -->
<!-- 可以直接相應轉發的頁面, 而無需再經過 Handler 的方法. -->
<mvc:view-controller path="/success" view-name="success"/>

<!-- 在實際開發中通常都需配置 mvc:annotation-driven 標籤 -->
<mvc:annotation-driven></mvc:annotation-driven>

十、BeanNameViewResolver解析器

①自定義一個檢視,實現view介面

@Component
public class HelloView implements View {

@Override
public String getContentType() {
// TODO Auto-generated method stub
return "text/html";
}

@Override
public void render(Map<String, ?> model, HttpServletRequest request,
HttpServletResponse response) throws Exception {
// TODO Auto-generated method stub
response.getWriter().print("hello view , time:"+new Date());

}

將此檢視交給IOC容器管理

②在spring mvc 的配置檔案中配置解析器

<bean class="org.springframework.web.servlet.view.BeanNameViewResolver">
<property name="order" value="100"></property>
</bean>

注意優先順序

<!-- 通過 order 屬性來定義檢視解析器的優先順序, order 值越小優先順序越高 -->

<!--InternalResourceViewResolver解析器的order值最大-->

③方法

<!-- 配置檢視 BeanNameViewResolver 解析器: 使用檢視的名字來解析檢視 -->

@RequestMapping(value="/testView")
public String testView(){
System.out.println("testView");
return "helloView";
}

④呼叫

<a href=springmvc/testView>testView</a>

十一、重定向

只需要在返回的名字前面加上redirect:就可以了