Springmvc知識二細節[email protect
舉例說明
對於@modelattribute註解比較吃力。現在我們先考慮一個問題,關於資料的修改。
假設我們需要修改一個User物件,但是我們規定某一個或者幾個欄位不能修改,我們會利用表單填寫相關資訊,然後提交給後臺,然後 在後臺會new出一個物件,並將表單提交的資料賦值到這個表單的屬性中,然後執行update操作,但是由於有些欄位不能被修改,所以我們在前臺傳遞的物件有些屬性為空,所以在更新的時候,那些不能被修改的欄位就會被預設為空值。
解決:1、我們可以利用隱藏域,在使用者進行修改的時候,將對應的不能修改的欄位進行隱藏,這樣的話,可以解決,但是如果對應的欄位的敏感度比較高,例如密碼不適合利用隱藏域進行記錄,這種方法是不合適的。
2、我們可以在資料更新之前,先從資料庫中將使用者資訊給讀取出來,然後將不能修改的欄位重新進行賦值然後更新。
引出:
對於上述兩種方式都有對應的缺點,但是對於更新資料比較小的可以使用,所以我們可以利用我們的這個ModelAttribute註解進行處理。
注意 這裡的物件不是new出來的,而是從資料庫獲取出來的,這就是ModelAttribute的作用之一。
在沒有利用@ModelAttribute修飾前演示
<!-- POJO類ModelAttributes屬性 -->
private int id;
private String name;
private int age;
private String email;
private String password; // 不能被修改
<!--
模擬修改操作 前臺頁面
1.原始資料為 1 tom 12 [email protected] 12345
2.密碼不能修改
3.表單回顯 ,模擬操作直接在表單填寫對應的屬性值
在使用者修改資料時,有些資料不能修改,所以在修改時我們把這些子段不給顯示,
我們應該是從資料庫中先獲取,然後 利用ModelAttribute註解進行 覆蓋,
會比我們自己手動利用覆蓋的效果高
-->
<form action="TestModelArributes" method="post" >
<input type="hidden" name="id" value="1">
name:<input type="text" name="name" value="tom">
age:<input type="text" name="age" value="12" >
email:<input type="text" name="eamil" value="[email protected]" >
<input type="submit" value="submit">
</form>
<!-- 後臺處理 -->
@RequestMapping("/TestModelArributes")
public String TestModelArributes(User user){
System.out.println("修改:"+user);
// 執行更新操作 省略
return SUCCESS;
}
<!-- 控制檯列印結果 -->
修改:User[id=1, name=tom, age=13, [email protected], password=null]
注意:在這裡我們的原始資料 帶有密碼,但是從前臺到後臺處理的時候,這個密碼由於沒有在表單之中,所以傳過來的POJO 的密碼為空。即利用方法一所造成的。
然後我們在後臺處理中新增加一個方法,注意是被@ModelAttribute修飾的。
@ModelAttribute
public void getUser(@RequestParam(value="id",required=false) Integer id,
Map<String, Object> maps){
if(id != null){ // id不為空,說明是使用者執行了修改操作
// 模擬從資料庫中獲取物件 我們是生成的
User user =new User(1,"tom", 12,"[email protected]", "1234");
System.out.println("從資料庫中獲取一個物件:"+user );
maps.put("user", user);
}
}
<!-- 控制檯列印結果 -->
從資料庫中獲取一個物件:User[id=1, name=tom, age=12, [email protected]163.com, password=1234]
修改:User[id=1, name=tom, age=13, [email protected]163.com, password=1234]
當被@ModelAttribute修飾一個方法之後,結果就變成了password有值了,而且也應該注意到,被@ModelAttribute修飾的方法給提前執行了,這就是@ModelAttribute的作用。這樣的話,再做修改操作的話,就能將原始密碼給帶進入修改操作了。為什麼被@ModelAttribute修飾一個方法之後就會有這樣的結果呢?
下面我們抽出主要程式碼進行分析
<!-- 第一種方式 -->
@ModelAttribute
public void getUser(@RequestParam(value="id",required=false) Integer id,
Map<String, Object> maps){
if(id != null){
User user =new User(1,"tom", 12,"[email protected]", "1234");
maps.put("user", user);
}
}
@RequestMapping("/TestModelArributes")
public String TestModelArributes(User user){
System.out.println("修改:"+user);
return SUCCESS;
}
=============================
<!--第二種方式 -->
@ModelAttribute
public void getUser(@RequestParam(value="id",required=false) Integer id,
Map<String, Object> maps){
if(id != null){
User user=new User(1,"tom", 12, "1234");
maps.put("change", user);
}
@RequestMapping("/TestModelArributes")
public String TestModelArributes(@ModelAttribute( value="change") User user){
System.out.println("修改:"+user);
return SUCCESS;
}
注意
1、@ModelAttribute修飾的方法會被Springmvc提前執行,執行在每個目標方法之前。
2、在@ModelAttribute修飾的方法中,【map存入的鍵需要和目標方法入參型別的第一個字母小寫的字串一致】方式一所示,否則的話,在目標的請求引數方法中不能匹配到從資料庫中提取出來的資料,或者就是你也將目標方法的引數用利用註解ModelAttribute修飾且設定value屬性值指向你的map中的鍵名,上述程式碼的第二種方式
分析流程
執行流程:
我們上述程式碼可以分為三個步驟:
1、 執行ModelArribute修飾的方法,從資料庫中取出物件,把物件放到Map 中,鍵為user。
2、springmvc 從Map 中取出User 物件 ,並把表單的請求引數賦給該User物件的對應屬性。
3、springmvc 把上述物件傳入到目標方法的引數。
@ModelAttribute原始碼分析流程
原始碼分析流程:對應上面的執行流程。
1、呼叫@ModelAttribute 註解修飾的方法,實際上把@ModelAttribute方法中 Map中的資料放在了implicitModel中。
2、解析請求處理器的目標引數,實際上該目標引數來自於WebDataBinder物件的target屬性。
2.1、建立WebDataBinder物件。
a) 確定objectName屬性:若傳入的attrName屬性值為空”“,則objectName為類名第一個字母小寫。需要注意的是:attrName。如果目標方法的POJO引數屬性使用了@ModelAttribute來修飾,則attrName值即為@ModelAttribute的value屬性值(對應我們的第二種寫法)
b)確定target屬性:在implicitModel 中查詢attrName對應的屬性值,如果存在,進行利用。如果不存在,則驗證當前Handler是否使用了@SessionAttribute進行修飾類。如果使用了@SessionAttribute,則嘗試從HttpSession中獲取attrName所對應的值,若Session中沒有所對應的值,則會丟擲異常。【這也是SessionAttribute與ModelAttribute共同使用時造成的一個常見問題】,如果當前Handler沒有使用@SessionAttribute修飾類,且@SessionAttribute中沒有使用value值指定的key和attrName相匹配,則通過反射機制進行建立POJO 物件。
2.2、Springmvc把表單的請求引數賦值給WebDataBinder 的target對應的屬性。
2.3、Springmvc 會把WebDataBinder的attrName和target給到implicitModel,進而傳遞到request域物件中。
3、把WebDataBinder的target作為引數傳遞給目標方法。
POJO入參流程
從而我們也可以得出Springmvc進行傳遞POJO型別作為引數的流程:
1、確定一個key:
1.1、若目標方法的POJO型別的引數沒有使用@ModelAttribute 作為修飾,則key為POJO類名第一個字母的小寫。
1.2、如果使用了@ModelAttribute 來修飾,則key為@ModelAttribute 註解的value屬性值。
2、在implicitModel中查詢key對應的物件,如果存在則作為入參傳入。
2.1、如在@ModelAttribute標記的方法中儲存過,且key值與上述1中key一致,也可以進行獲取(這就是上述程式碼為什麼可以獲取@ModelAttribute修飾的方法中map中的值)
3、若implicitModel 中不存在key對應的物件,則檢查當前Handler是否使用了@SessionAttribute進行修飾類,如果使用了@SessionAttribute,且@SessionAttribute註解的value屬性值中包含了key,則會從HttpSession中來獲取key所對應的value值,若不存在則會丟擲異常。
4、如果當前Handler沒有使用@SessionAttribute修飾類,且@SessionAttribute中value屬性值中不包含key,則通過反射機制進行建立POJO 物件。作為目標的方法引數物件。
5、Springmvc會把key和pojo型別的物件報錯到implicitModel 中,進而儲存到Request中。
使用總結
1、註解在沒有返回值的方法上面
就如上面的例子註解在沒有返回值的方法上面,用在POJO入參上面,或者我們可以在這裡設定一些Request域中的物件,在前臺可以直接使用。
@ModelAttribute
public void getUser(){
maps.put("name", "zhangsan");
}
2、註解在有返回值的方法上面,
這裡要用value屬性進行資料儲存,會將返回值儲存在value屬性的值中,可以在前臺直接獲取。
@ModelAttribute(value="user00")
public User testModelAttribute(){
User user =new User(1,"tom00", 12,"[email protected]", "123400");
return user;
}
3、在方法引數上使用@ModelAttribute
在方法的引數中使用必須是修飾POJO類,這樣的話,才能從相應的域中獲取資料
@RequestMapping("/TestModelArributes")
public String TestModelArributes(@ModelAttribute( value="change") User user){
System.out.println("列印"+user);
return SUCCESS;
}
這樣的話,會從implicitModel 隱藏域中查詢此型別物件,就猶如上面分析的傳遞POJO流程,其實這裡的作用只是可以使用change標記我們的user物件。
4、尤其要注意ModelAttribute與SessionAttribute同時使用會產生的異常丟擲,以及原因。
5、一定要理解POJO傳遞引數的流程
對於原始碼分析不理解的建議去看尚矽谷的佟剛的Springmvc教程,本例項就是根據他的視訊寫的筆記。
相關推薦
Springmvc知識二細節<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="7a57575757573a37151e1f163b0e0e0813180f0e1f">[email160;protect
舉例說明 對於@modelattribute註解比較吃力。現在我們先考慮一個問題,關於資料的修改。 假設我們需要修改一個User物件,但是我們規定某一個或者幾個欄位不能修改,我們會利用表單填寫相關資訊,然後提交給後臺,然後 在後臺會new出一個物件,並將表單
springMVC @<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="9eddf1f3eef1f0fbf0eab3deccfbedf1ebecfdfbb3">[email160;protected]
作用: @Component------------------------泛指元件,當元件不好歸類的時候,我們可以使用這個註解進行標註。(Component-------成分; 組分; 零件) @Resource------------------------(資源) @Autowired------
springMVC原始碼分析<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="35181875665046465c5a5b744141475c57404150">[email160;protected
@SessionAttribute作用於處理器類上,用於在多個請求之間傳遞引數,類似於Session的Attribute,但不完全一樣,一般來說@SessionAttribute設定的引數只用於暫時的傳遞,而不是長期的儲存,長期儲存的資料還是要放到Session中。通過@Se
SpringMVC基礎<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="b39ef3e1d6c2c6d6c0c7fbd6d2d7d6c1">[email160;protected]a>
1.概述 從Http請求頭中提取指定的某個請求頭.等價於HttpServletRequest.getHeader(String) 2.配置 (1)value(default ""):引數名例如: Accept (2)required(default true):是否請求
SpringMVC基礎<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="ad80ede0c2c9c8c1ecd9d9dfc4cfd8d9c8">[email160;protected]a>註解&P
在總結@ModelAttribute註解功能配合PUT請求方式使用之前,先來總結一下POJO類作為入參接收form表單POST提交方式提交資料。 POJO類接收引數 總的來說POJO類還是與普通的Java Bean類還是特別的相似的,私有的屬性,需要
SpringMVC(1)<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="7954545454392b1c080c1c0a0d29180b1814">[email160;protected]a>和
1、@RequestParam 使用@RequestParam接收前段引數比較方便,前端傳參的URL: url = “${ctx}/main/mm/am/edit?Id=${Id}&name=${name}” 後端使用集合來接受引數,靈活性較好,如
springMVC原始碼分析<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="65484825280a010009241111170c07101100">[email160;protected]a
這一篇部落格我們簡單的介紹一下ModelAttribute的使用和執行原理。1、首先@ModelAttribute是使用在方法或者上的,當使用在方法上時其作用於本身所在的Controller,在訪問Controller中的所有請求時都會執行到@ModelAttribute所註
shell腳本中的$# $0 <a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="f8dcb8">[email160;protected]a> $* $$ $! $?的意義
腳本 $* width 上一個 pre shell int .cn height 轉載自:http://www.cnblogs.com/davygeek/p/5670212.html 今天學寫腳本遇到一些變量不認識,在此做下記錄。 變量 含義 $0 當前腳本的文件
shell中$*與<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="b296f2">[email160;protected]a>的區別
劃分 位置 一個 這也 差異 獨立 [email protected] 情況 雙引號 $*所有的位置參數,被作為一個單詞 註意:"$*"必須被""引用 [email protected] 與$*同義,但是每個參數都是一個獨立的""引用字串,這就意味著參數
Spring4.0系列<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="aa9f87eae9c5c4cec3dec3c5c4cbc6">[email160;protected]a>
one window 標識 cto ace ted ada bsp 布爾 這篇文章介紹Spring 4的@Conditional註解。在Spring的早期版本你可以通過以下方法來處理條件問題: 3.1之前的版本,使用Spring Expression Langua
Spring高級話題<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="b29ff2f7dcd3d0ded7">[email160;protected]a>***註解的工作原理
sso metadata bool logs tcl task ota -c ann 出自:http://blog.csdn.net/qq_26525215 @EnableAspectJAutoProxy @EnableAspectJAutoProxy註解 激活Aspe
<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="297a595b40474e69685c5d465e405b4c4d">[email160;protected]a>註解與自動裝配(轉發)
配置 調用方法 support autowired 信息 ann over 反射機制 test 1 配置文件的方法我們編寫spring 框架的代碼時候。一直遵循是這樣一個規則:所有在spring中註入的bean 都建議定義成私有的域變量。並且要配套寫上 get 和 se
linux bash Shell特殊變數:Shell $0, $#, $*, <a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="8aaeca">[email160;protected]a>, $?
在linux下配置shell引數說明 前面已經講到,變數名只能包含數字、字母和下劃線,因為某些包含其他字元的變數有特殊含義,這樣的變數被稱為特殊變數。 例如,$ 表示當前Shell程序的ID,即pid,看下面的程式碼: [[email protected] /]$ ec
spring <a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="62000d0d16222103010a0703000e07">[email160;protected]a>中value的理解
先看原始碼 /** * Names of the caches in which method invocation results are stored. * <p>Names may be used to determine the target cache (or cac
{<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="733e3c3f3f2a342136363d203323213c273c3d3e323a3f5d303c3e">[email160;protecte
近日,復旦解密安全團隊發現GandCrab4.0活躍度提升,跟蹤到多起GandCrab4.0變種勒索事件,現釋出安全預警,提醒廣大使用者預防GandCrab4.0勒索。 目前復旦解密已經可以成功解密GandCrab4.0變種採用RSA+AES加密演算法 mg中毒檔案可以在一個小時解決.電話151691214
Springboot註解<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="260b0b666549485254494a4a4354">[email160;protected]a>和@RestCon
1.使用@Controller 註解,在對應的方法上,檢視解析器可以解析return 的jsp,html頁面,並且跳轉到相應頁面;若返回json等內容到頁面,則需要加@ResponseBody註解 [email protected]註解,相當於@[email protected
<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="5b2c3e391b33">[email160;protected]a>,c小總結
問題0:元素內聯元素,行內元素,行內塊元素. 內聯: 寬高M,P都有效 行內元素:無寬高,內容撐開,M,P左右有效
SQL Server資料庫mdf檔案中了勒索病毒<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="fc9f8e858c889998a39d8f9d9293bc9f939f97">[email160;p
SQL,資料庫,勒索病毒,mdf檔案中毒,[email protected]_email *SQL Server資料庫mdf檔案中了勒索病毒[email protected]_email。副檔名變為[email protected]_email SQL Serv
<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="5400313a273b2632383b2379142032">[email160;protected]a>_export詳解
Tensorflow經常看到定義的函式前面加了“@tf_export”。例如,tensorflow/python/platform/app.py中有: @tf_export('app.run') def run(main=None, argv=None): """Runs the progr
手把手教你搭建React Native 開發環境 - ios篇 (React <a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="eda38c99849b88adddc3d8d8c3d9">[email
由於之前我是h5的,沒接觸過ios和安卓, 也不瞭解xcode配置,所以 建議學reace-native之前還是先去了解一下ios和安卓開發環境搭建等問題。 環境下載及配置 nodejs:https://nodejs.org/en/download/ 設定淘寶映象 $ npm con