32、Action是如何獲得參數(shù)的?
Struts 2用戶處理用戶請(qǐng)求的Action實(shí)例,并不是用戶實(shí)現(xiàn)的業(yè)務(wù)邏輯控制器,而是Action代理----因?yàn)橛脩魧?shí)現(xiàn)的業(yè)務(wù)邏輯控制器并沒(méi)有與Servlet API耦合,顯然無(wú)法處理用戶請(qǐng)求.而Struts 2框架提供了系列攔截器,該系列攔截器負(fù)責(zé)將HttpServletRequest請(qǐng)求中的請(qǐng)求參數(shù)解析出來(lái),傳入到Action中,并回調(diào)Action的execute方法來(lái)處理用戶的請(qǐng)求.
顯然,上面的處理過(guò)程是典型的AOP處理方式.
用戶實(shí)現(xiàn)的Action類僅僅是Struts 2的Action代理的代理目標(biāo).用戶實(shí)現(xiàn)的業(yè)務(wù)控制器則包含了對(duì)用戶請(qǐng)求的處理.用戶的請(qǐng)求數(shù)據(jù)包含在HttpServletRequest對(duì)象里,而用戶的Action類無(wú)需訪問(wèn)HttpServletRequest對(duì)象.攔截器負(fù)責(zé)將HttpServletRequest里的請(qǐng)求數(shù)據(jù)解析出來(lái),并傳給邏輯組件Action實(shí)例.
33、Request對(duì)象的getRemoteAddr()方法
在開(kāi)發(fā)過(guò)程中使用request對(duì)象的getRemoteAddr()方法時(shí),返回的是0:0:0:0:0:0:0:1,而不是127.0.0.1(回送地址,指本地機(jī),一般用于測(cè)試)。那為什么返回的不是我們看到的127.0.0.1呢?實(shí)際上0:0:0:0:0:0:0:1是IPv6協(xié)議的表示形式,而127.0.0.1是IPv4的表示形式。用于我用的是Win7操作系統(tǒng),它支持IPv6,所以顯示的時(shí)候就用IPv6顯示出來(lái)了,解決的辦法是找到C:\Windows\system32\drivers\etc\ hosts這個(gè)文件,如果看到是這樣
# localhost name resolution is handled within DNS itself.
# 127.0.0.1 localhost
# ::1 localhost
那就把上面一個(gè)的“#”去掉,如果下面一個(gè)沒(méi)有“#”,那么就加上。
33、Struts 2中的ActionContext何ServletActionContext
Struts 2的Action并未直接與任何的Servlet API耦合,這是Struts 2的一個(gè)改良之處,因?yàn)锳ction類不再與Servlet API耦合,從而能夠更輕松地測(cè)試該Action。
但對(duì)于Web應(yīng)用的控制器而言,不訪問(wèn)Servlet API幾乎是不可能的,例如跟蹤HTTP Session狀態(tài)等。Struts 2 框架提供一種更輕松地方式訪問(wèn)Servlet API。Web應(yīng)用中通常需要訪問(wèn)的Servlet API就是HttpServletRequest、HttpSession和ServletContext,這三個(gè)類分別代表JSP內(nèi)置對(duì)象中的request、session和application。
Struts 2提供了一個(gè)ActionContext類,Struts 2的Action可以通過(guò)該類來(lái)訪問(wèn)Servlet API。
ServletActionContext繼承ActionContext,它提供了直接與Servlet容器交互的路徑。
ActionContext和ServletActionContext有著一些重復(fù)的功能,在我們的Action中,該如何去抉擇呢?我們遵循的規(guī)則是:如果ActionContext能夠?qū)崿F(xiàn)我們的功能,那最好就不要使用ServletActionContext,讓我們的Action盡量不要直接去訪問(wèn)Servlet相關(guān)的對(duì)象。
注意:在使用ActionContext時(shí)有一點(diǎn)要注意: 不要在Action的構(gòu)造函數(shù)里使用ActionContext.getContext(),因?yàn)檫@個(gè)時(shí)候ActionContext里的一些值也許沒(méi)有 設(shè)置,這時(shí)通過(guò)ActionContext取得的值也許是null;同樣,HttpServletRequest req = ServletActionContext.getRequest()也不要放在構(gòu)造函數(shù)中,也不要直接將req作為類變量給其賦值。至于原因,我想是因 為前面講到的static ThreadLocal actionContext = new ActionContextThreadLocal(),從這里我們可以看出ActionContext是線程安全的,而 ServletActionContext繼承自ActionContext,所以ServletActionContext也線程安全,線程安全要求每 個(gè)線程都獨(dú)立進(jìn)行,所以req的創(chuàng)建也要求獨(dú)立進(jìn)行,所以ServletActionContext.getRequest()這句話不要放在構(gòu)造函數(shù) 中,也不要直接放在類中,而應(yīng)該放在每個(gè)具體的方法體中(eg:login()、queryAll()、insert()等),這樣才能保證每次產(chǎn)生對(duì)象 時(shí)獨(dú)立的建立了一個(gè)req。
struts2中獲得request、response和session
(1)非IoC方式
方法一:使用org.apache.struts2.ActionContext類,通過(guò)它的靜態(tài)方法getContext()獲取當(dāng)前Action的上下文對(duì)象。
ActionContext ctx = ActionContext.getContext();
ctx.put("liuwei", "andy"); //request.setAttribute("liuwei", "andy");
Map session = ctx.getSession(); //session
HttpServletRequest request = ctx.get(org.apache.struts2.StrutsStatics.HTTP_REQUEST);
HttpServletResponse response = ctx.get(org.apache.struts2.StrutsStatics.HTTP_RESPONSE);
細(xì)心的朋友可以發(fā)現(xiàn)這里的session是個(gè)Map對(duì)象, 在Struts2中底層的session都被封裝成了Map類型. 我們可以直接操作這個(gè)Map對(duì)象進(jìn)行對(duì)session的寫入和讀取操作, 而不用去直接操作HttpSession對(duì)象.
方法二:使用org.apache.struts2.ServletActionContext類
public class UserAction extends ActionSupport {
//其他代碼片段
private HttpServletRequest req;
// private HttpServletRequest req = ServletActionContext.getRequest(); 這條語(yǔ)句放在這個(gè)位置是錯(cuò)誤的,同樣把這條語(yǔ)句放在構(gòu)造方法中也是錯(cuò)誤的。
public String login() {
req = ServletActionContext.getRequest(); //req的獲得必須在具體的方法中實(shí)現(xiàn)
user = new User();
user.setUid(uid);
user.setPassword(password);
if (userDAO.isLogin(user)) {
req.getSession().setAttribute("user", user);
return SUCCESS;
}
return LOGIN;
}
public String queryAll() {
req = ServletActionContext.getRequest(); //req的獲得必須在具體的方法中實(shí)現(xiàn)
uList = userDAO.queryAll();
req.getSession().setAttribute("uList", uList);
return SUCCESS;
}
//其他代碼片段
聯(lián)系客服