我正在研究一個簡單的Java應用程序。目前,我有兩個視圖,一個用於登錄和另一個登錄。控制器是否創建新視圖?
所以我的問題是,一旦用戶登錄,登錄視圖的控制器應該創建第二個視圖?
的問題是,第一控制器需要知道第二種觀點的每一個依賴...
編輯:這是不是一個 Web應用程序。
我正在研究一個簡單的Java應用程序。目前,我有兩個視圖,一個用於登錄和另一個登錄。控制器是否創建新視圖?
所以我的問題是,一旦用戶登錄,登錄視圖的控制器應該創建第二個視圖?
的問題是,第一控制器需要知道第二種觀點的每一個依賴...
編輯:這是不是一個 Web應用程序。
如果你的對象需要實例化一個類,但你不希望它依賴實例化類的細節,請注入一個工廠(如you've suggested)。
我喜歡使用接口,所以我可以插入我的依賴項的不同實現。這裏有一個例子:
public class RealLoginController implements LoginController {
private LoginViewFactory viewFactory;
public LoginController(LoginViewFactory viewFactory) {
this.viewFactory = viewFactory;
}
public ModelAndView handleRequest(HttpServletRequest request,
HttpServletResponse response) {
if (isLoggedIn()) {
return viewFactory.createLoggedInView();
} else {
return viewFactory.createLoggedOutView();
}
}
// ...
}
public class RealLoggedInView implements LoginView {
// Implementation for rendering stuff
}
public class RealLoggedOutView implements LoginView {
// Implementation for rendering stuff
}
public interface LoginViewFactory {
public LoginView createLoggedInView();
public LoginView createLoggedInView();
}
public class RealLoginViewFactory implements LoginViewFactory {
private FooModel fooEngine;
private BarConfig barConfig;
public RealLoginViewFactory(FooModel fooLayer, BarConfig barConfig) {
this.fooEngine = fooEngine;
this.barConfig = barConfig;
}
public LoginView createLoggedInView() {
if (fooEngine.hasBaz()) {
return new RealLoginView(barCongig.getQux());
} else {
return new RealLoginView(barCongig.getQux(),
fooEngine.getBaz());
}
}
public LoginView createLoggedOutView() {
// ...
}
}
public class RealLoginController implements LoginController {
private LoginViewFactory viewFactory;
public LoginController(LoginViewFactory viewFactory) {
this.viewFactory = viewFactory;
}
public ModelAndView handleRequest(HttpServletRequest request,
HttpServletResponse response) {
if (isLoggedIn()) {
return viewFactory.createLoggedInView();
} else {
return viewFactory.createLoggedOutView();
}
}
// ...
}
然後,您可以使用任何意見控制器你喜歡:
public class LoginControllerTest {
public void testSomething() {
// ...
controller = new RealLoginController(fakeViewFactory);
assertHasTag("td#row1", controller.getRenderedStuff());
// ...
}
}
您可能能夠避免這些問題(如bpappa suggests)如果您並不需要複雜的實例邏輯和你的框架知道如何通過名字獲得你的依賴關係。
這是與Spring MVC?
如果您使用Spring MVC 2.5或更低版本而沒有註釋,則在handleRequest方法結束時返回ModelAndView對象。這包含視圖信息(不管它是視圖本身,如在重定向視圖中,還是視圖的名稱)。您可以根據某種邏輯有條件地返回不同的視圖。例如 -
handleRequest(HttpServletRequest request, HttpServletResponse response) {
// get user from session
if (user.isLoggedIn())
return new ModelAndView("loggedInView");
else
return new ModelAndView("notLoggedInView");
}
如果這是一個新的項目,雖然,你必須訪問Java 1.5,我反而建議使用annotations-based Spring MVC,因爲這樣你可以返回任何你想要的弗裏克。
對不起,沒有。這不是一個網絡應用程序。 – subb 2009-05-31 23:40:26
我認爲,一個工廠可能做的伎倆:
public class LoginViewFactory
{
private depA;
private depB;
public LoginViewFactory(dependencyA, dependencyB)
{
depA = dependencyA;
depB = dependencyB;
}
LoginView create()
{
return new LoginView(depA, depB);
}
}
//and then pass this factory to my controller
new Controller(new LoginViewFactory(new A(), new B());
你覺得呢?
你應該採用與Spring相同的方法,讓你的控制器返回一個視圖名稱。 然後讓另一個類根據視圖名稱處理創建視圖。
我認爲你的第一個「視圖」(登錄頁面)可以被認爲是一個靜態頁面,因爲通常它會成爲第一個可訪問的頁面,因此可能沒有控制器。
但是,假設您的網絡應用程序中還有一些其他頁面,並說您確實有一個控制器A(一種DispatchController),它將用戶引導至登錄頁面。
一旦這個頁面被提交,通常你將會有一個不同的控制器(說的LoginController),將引導(如果登錄成功)的用戶到你的第二個視圖頁面(頁面登錄)
那麼底線是:對我來說,看起來你需要兩個控制器,每個控制器都有不同的責任。
我不認爲LoginController應該創建SecondView。一旦用戶登錄,LoginController應該發出登錄成功的事件,任何關心該事件的Controller都應該採取適當的措施。
如果您使用DI,您最好將視圖注入控制器。
不太清楚你的意思與你最後的聲明,儘管如此留下未答覆。
好吧,假設我的第二個視圖的構造函數需要一個模型,負責創建這個視圖的對象(這裏是我的控制器)需要知道這個模型,繼承視圖的依賴關係。 – subb 2009-06-07 12:25:09
如果您的登錄名是表單POST(它應該是),我會在成功登錄後重定向到主頁。
這樣,如果用戶在登錄後在主頁上點擊刷新,那麼他們不會得到有關重新提交POST的瀏覽器警告。
如果他們單擊主頁上的鏈接,然後單擊後退按鈕,則同樣適用。
在春天你可以用這個語法來做到這一點。
return new ModelAndView(new RedirectView(homepage, true), model);
的「主頁」參數會在你的Spring配置進行配置,並注入作爲參數 - 它應該是一個相對URL在您的網站主頁。
因爲你重定向的主頁控制器執行,所以這處理你的依賴問題。
添加了java標記。 – 2009-06-01 03:18:46