Контроллер создает новые представления? - PullRequest
3 голосов
/ 01 июня 2009

Я работаю над простым приложением Java. В настоящее время у меня есть два вида, один для входа в систему и другой, как только вы вошли в систему.

Итак, мой вопрос: после входа в систему должен ли контроллер представления входа в систему создавать второе представление?

Проблема в том, что первый контроллер должен знать все зависимости второго представления ...

Редактировать: это , а не веб-приложение.

Ответы [ 7 ]

1 голос
/ 03 июня 2009

Если вашему объекту необходимо создать экземпляр класса, но вы не хотите, чтобы он зависел от деталей создания экземпляра класса, введите фабрику (как вы предложили ).

Мне нравится использовать интерфейсы, чтобы я мог подключать различные реализации моих зависимостей. Вот пример:

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 предлагает ), если вам не нужна сложная логика создания экземпляров и ваша инфраструктура знает, как получить зависимости для вас по имени.

1 голос
/ 03 июня 2009

Я не думаю, что LoginController вообще должен создавать SecondView. После того как пользователь вошел в систему, LoginController должен запустить событие, если вход был успешным, и любой контроллер, который заботится об этом, должен предпринять соответствующее действие.

Если вы используете DI, в идеале вы хотите добавить View в контроллер.

Не совсем уверен, что вы имеете в виду под своим последним утверждением, хотя и оставил это без ответа.

0 голосов
/ 03 июня 2009

Если ваш логин представляет собой форму POST (что и должно быть), я сделаю перенаправление на домашнюю страницу после успешного входа в систему.

Это так, что если пользователь нажимает кнопку "Обновить" на домашней странице после входа в систему, он не получает предупреждение браузера о повторной отправке POST.
То же самое применяется, если они нажимают на ссылку с домашней страницы, а затем нажимают кнопку "Назад".

В Spring вы можете сделать это с помощью этого синтаксиса.

return new ModelAndView(new RedirectView(homepage, true), model);

Параметр "homepage" будет настроен в вашем весеннем конфиге и введен как параметр - это должен быть относительный URL к домашней странице вашего сайта.

Поскольку вы перенаправляете контроллер домашней страницы, выполняется, так что это решает проблему ваших зависимостей.

0 голосов
/ 03 июня 2009

Я думаю, что ваше первое «представление» (страница входа в систему) может рассматриваться скорее как статическая страница, так как обычно это будет первая доступная страница, поэтому, вероятно, за ней нет контроллера.

Но предположим, что в вашем веб-приложении есть некоторые другие страницы и говорят, что у вас действительно есть контроллер A (тип DispatchController), который направляет пользователя на страницу входа в систему.

После отправки этой страницы у вас обычно будет другой контроллер (скажем, LoginController), который направит (в случае успешного входа) пользователя на вашу вторую страницу просмотра (авторизованную на странице)

Итак, суть в том, что мне кажется, что вам нужны два контроллера, каждый с разной ответственностью.

0 голосов
/ 03 июня 2009

вы должны использовать тот же подход, что и в Spring, и ваш контроллер должен вернуть имя представления. А затем еще один класс обрабатывает создание представления на основе имени представления.

0 голосов
/ 01 июня 2009

Я думаю, что фабрика может добиться цели:

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());

Что ты думаешь?

0 голосов
/ 01 июня 2009

Это с 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, я бы вместо этого рекомендовал использовать Spring MVC на основе аннотаций , потому что тогда вы можете вернуть любой желаемый фрик. *

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...