RequestDispatcher.forward () по сравнению с HttpServletResponse.sendRedirect ()

Между чем концептуальное различие forward() и sendRedirect()?

119
задан BalusC 27 April 2016 в 20:07
поделиться

3 ответа

Несмотря на то, что он работает так, как ожидалось, я думаю, что он проваливается двумя счетчиками:

  1. Ваш код не будет плавно масштабироваться, потому что вы считываете весь файл в память, и это может быть или не обязательно то, что вы хотите.
  2. Согласно Zen of Python (попробуйте импортировать этот в подсказке Python для его получения) «явный лучше, чем неявный» и, не сумев явно закрыть файл, вы можете запутать кого-то, кто по дороге останется с вашим кодом для обслуживания.

Это действительно помогает быть явным! Python поощряет явный стиль.

Кроме этого, для сценария броска ваш стиль имеет смысл.

Возможно, вы выиграете от этого ответа .

-121--2879287-

Во-первых, некоторые определения из стандарта C++ 03:

1.3.5 Поведение, определенное реализацией

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

1.3.12 неопределенное поведение

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

1,3,13 неопределенное поведение

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

Хотя неопределенное поведение можно назвать UB, я никогда этого не видел, и UB всегда означает неопределенное поведение. Во всем стандарте есть операторы, похожие на «делать X - неопределенное поведение», но иногда вы сталкиваетесь с случаем, который просто не охвачен.

Если в любом месте имеется неопределенное поведение, то все ставки выключены . Что касается стандарта, ваша программа может сделать что угодно, от приглашения тещи на выходные SuperBowl до запуска nethack . Из-за самой природы UB вы не можете проверить на него, и вы не можете ожидать никакой помощи от компилятора.

Обычно что-то определяется как UB, потому что это просто не имеет смысла логически (например, доступ к массиву вне границ), но также часто потому, что это потребует реализации слишком много работы, чтобы предотвратить - часто во время выполнения. Помните, что C++ происходит от C, и быть возможность создавать высокооптимизированные программы является главной целью обоих языков. С этой целью языки передают программисту, чтобы убедиться в правильности кода в этих ситуациях, связанных с принципом «вы не платите за то, что не используете».

Итак, наконец, UB плохой, очень плохой; избегайте его любой ценой. Однако твердая часть UB не знает, что это такое или при каких обстоятельствах это происходит;жесткая часть распознает, когда вы вызываете UB. Например:

std::string s = "abc";
char& c = s[0];
cout.write(s.data(), s.length());
c = '-';

Выглядит вполне разумно, верно? Нет, это UB, но он будет работать так, как вы ожидаете на всех популярных реализациях.

-121--4594703-

Любой из этих методов может быть «лучше», т.е. более подходящим, в зависимости от того, что вы хотите сделать.

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

Перенаправление со стороны клиента является более универсальным, поскольку оно может отправить вас на совершенно другой сервер или изменить протокол (например, с HTTP на HTTPS), или и то и другое. И браузер знает о новом URL. Но для этого требуется дополнительный обмен данными между сервером и клиентом.

4
ответ дан 24 November 2019 в 01:47
поделиться

В мире веб-разработки термин «перенаправить» является акт отправления клиента пустой HTTP-ответ с лишним в заголовке в заголовке , содержащий новый URL, к которому Клиент должен отправить совершенно новый запрос GET. Таким образом, в основном:

  • Клиент отправляет HTTP-запрос на uvery.jsp .
  • Сервер отправляет ответ HTTP обратно с Местоположение: orject.jsp Заголовок
  • Клиент посылает HTTP-запрос на orject.jsp (это отражено в адресной строке браузера!)
  • Сервер отправляет ответ HTTP обратно с содержанием ord.jsp .

Вы можете отслеживать его с помощью настроек веб-браузера / набора инструментов разработчика веб-браузера. Нажмите F12 в Chrome / IE9 / Firebug и проверьте раздел «Сеть», чтобы увидеть его.

Точно вышеизложенное достигается со стороны Sendreredirect («ord.jsp») . RequestDiSpatcher # Forward () не отправляет перенаправление. Вместо этого он использует контент целевой страницы как ответ HTTP.

  • Клиент отправляет HTTP-запрос на uvery.jsp .
  • Сервер отправляет ответ HTTP обратно с содержанием ord.jsp .

Однако, поскольку оригинальный HTTP-запрос был на uvery.jsp , URL в адресной строке браузера остается неизменным.


requestDivatcher чрезвычайно полезен в парадигме MVC и / или когда вы хотите скрыть JSP от прямого доступа. Вы можете поставить JSP в папку / Web-INF и использовать сервлете , которые контролируют, предварительно обработаны и постпроцессные запросы. JSP в папке / Web-inf непосредственно не доступен до URL, но сервлете могут получить доступ к ним с помощью RequestDiSpatcher # Forvert () .

Вы можете, например, иметь файл JSP в /web-inf/login.jsp и loginservlet , который отображается на URL-шаблоне / Войти . Когда вы призываете http://example.com/context/login , затем будет вызван сервлетой Doget () . Вы можете сделать любой PRE , обработанные там, и, наконец, вперед Запрос, как:

request.getRequestDispatcher("/WEB-INF/login.jsp").forward(request, response);

, когда вы отправляете форму, вы обычно хотите использовать POST :

<form action="login" method="post">

Таким образом, сервлет DOPOST () , и вы можете сделать любой POST , обработавщую там, обработанную там (например, валидацию, бизнес-логику, логин пользователя, и т. Д.).

Если есть какие-либо ошибки, то вы обычно хотите вперед запрос обратно на ту же страницу и отобразить ошибки рядом с полями ввода и т. Д. Вы можете использовать RequestDispatcher для этого.

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

User user = userDAO.find(username, password);
if (user != null) {
    request.getSession().setAttribute("user", user); // Login user.
    response.sendRedirect("home"); // Redirects to http://example.com/context/home after succesful login.
} else {
    request.setAttribute("error", "Unknown login, please try again."); // Set error.
    request.getRequestDispatcher("/WEB-INF/login.jsp").forward(request, response); // Forward to same page so that you can display error.
}

А Redirect Таким образом, инструктирует клиента устрелить новое . Get запрос на данный URL. Освежающий запрос будет только обновить перенаправленную запрос, а не первоначальный запрос. Это позволит избежать «двойных отправок» и путаницы и плохого пользовательского опыта. Это также называется шаблоном Post-Redirect-get .

157
ответ дан 24 November 2019 в 01:47
поделиться

Можно использовать стандартный системный вызов Unix fork , как os.fork () . fork () создаст новый процесс с тем же сценарием. В новом процессе он возвращает 0, в то время как в старом процессе возвращает идентификатор нового процесса.

child_pid = os.fork()
if child_pid == 0:
  print "New proc"
else:
  print "Old proc"

Для библиотеки более высокого уровня, которая обеспечивает поддержку многопроцессорной обработки, которая обеспечивает переносимую абстракцию для использования нескольких процессов, существует модуль многопроцессорной обработки . Статья о IBM DeveloperWorks, Мультипроцессинг с Python , содержит краткое введение в оба метода.

-121--1029730-

Что я делаю, так это то, что мой контроллер просмотра настраивает вид прокрутки:

[scrollView setCanCancelContentTouches:NO];
[scrollView setDelaysContentTouches:NO];

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

- (void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
    // Hand tool or two or more touches means a pan or zoom gesture.
    if ((selectedTool == kHandToolIndex) || (event.allTouches.count > 1)) {
        [[self parentScrollView] setCanCancelContentTouches:YES];
        [firstTouchTimer invalidate];
        firstTouchTimer = nil;
        return;
    }

    // Use a timer to delay first touch because two-finger touches usually start with one touch followed by a second touch.
    [[self parentScrollView] setCanCancelContentTouches:NO];
    anchorPoint = [[touches anyObject] locationInView:self];
    firstTouchTimer = [NSTimer scheduledTimerWithTimeInterval:kFirstTouchTimeInterval target:self selector:@selector(firstTouchTimerFired:) userInfo:nil repeats:NO];
    firstTouchTimeStamp = event.timestamp;
}

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

-121--1151870-

Интерфейс RequestDispatcher позволяет пересылать/включать серверную сторону, тогда как sendRedirect () перенаправляет клиентскую сторону. При перенаправлении со стороны клиента сервер отправляет обратно код состояния HTTP 302 (временное перенаправление), который заставляет веб-браузер выдать новый запрос HTTP GET для содержимого в перенаправленном расположении. Напротив, при использовании интерфейса RequestDispatcher include/forward to the new resource обрабатывается полностью на стороне сервера.

19
ответ дан 24 November 2019 в 01:47
поделиться
Другие вопросы по тегам:

Похожие вопросы: