我正在开发一个简单的Java应用程序。目前,我有两个视图,一个用于登录,另一个用于登录。
所以我的问题是,一旦用户登录,登录视图的控制器是否应该创建第二个视图?
问题是,第一个控制器需要知道第二个视图的每个依赖关系......
编辑:这是不一个Web应用程序。
答案 0 :(得分:1)
我认为LoginController根本不应该创建SecondView。一旦用户登录,LoginController就会触发登录成功的事件,任何关心该事件的Controller都应该采取适当的行动。
如果您正在使用DI,您最好将视图注入控制器。
不完全确定你对上一个陈述的意思,但是没有答案。
答案 1 :(得分:1)
如果您的对象需要实例化一个类,但您不希望它依赖于实例化该类的细节,请注入一个工厂(如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)。
答案 2 :(得分:0)
这是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,因为这样您就可以返回所需的任何内容。
答案 3 :(得分:0)
我认为工厂可能会这样做:
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());
您怎么看?
答案 4 :(得分:0)
你应该采用与Spring相同的方法,并让你的控制器返回一个视图名称。 然后让另一个类处理根据视图名称创建视图。
答案 5 :(得分:0)
我认为你的第一个“视图”(登录页面)可以被认为是一个静态页面,因为它通常是第一个可访问的页面,所以可能它背后没有控制器。
但是假设您的网络应用程序中还有其他一些页面,并且说您实际上有一个控制器A(一种DispatchController),它将用户引导到登录页面。
提交此页面后,您通常会有一个不同的控制器(比如LoginController),它将用户指向(如果登录成功)到第二个视图页面(登录页面)
所以底线是:对我而言,你看起来需要两个控制器,每个控制器都有不同的责任。
答案 6 :(得分:0)
如果您的登录是表格POST(应该是),我会在成功登录后重定向到主页。
这样,如果用户在登录后在主页上点击刷新,那么他们就不会收到有关重新提交POST的浏览器警告。
如果他们从主页单击链接然后单击后退按钮,则同样适用。
在Spring中,您可以使用此语法执行此操作。
return new ModelAndView(new RedirectView(homepage, true), model);
“homepage”参数将在spring配置中配置并作为参数注入 - 它应该是您网站主页的相对URL。
因为您正在重定向主页控制器,所以这会处理您的依赖项问题。