Вы всегда ПЕРЕНАПРАВЛЯЕТЕ после POST? Если да, Как Вы управляете им?

Истинной точкой входа в любое приложение является статический метод. Если бы язык Java поддерживал метод экземпляра в качестве «точки входа», то среда выполнения должна была бы реализовывать его внутри как статический метод, который создавал экземпляр объекта с последующим вызовом метода экземпляра.

С учетом этого, я рассмотрю обоснование выбора конкретного из следующих трех вариантов:

  1. A static void main(), как мы видим это сегодня.
  2. Экземпляр метода void main() вызвал только что созданный объект.
  3. Использование конструктора типа в качестве точки входа (например, если класс входа был назван Program, то выполнение будет состоять из new Program()).

Разбивка:

static void main()

  1. Вызывает статический конструктор класса включения.
  2. Вызывает статический метод main().

void main()

  1. Вызывает статический конструктор класса включения.
  2. Создает экземпляр окружающего класса путем эффективного вызова new ClassName().
  3. Вызывает метод экземпляра main().

new ClassName()

  1. Вызывает статический конструктор класса включения.
  2. Создает экземпляр класса (затем ничего не делает с ним и просто возвращает).

Обоснование:

Я пойду в обратном порядке для этого.

Имейте в виду, что одной из целей разработки Java было подчеркнуть (требовать, когда это возможно) хорошие практики объектно-ориентированного программирования. В этом контексте конструктор объекта инициализирует объект, но не должен отвечать за поведение объекта. Следовательно, спецификация, которая давала точку входа в new ClassName(), могла бы запутать ситуацию для новых разработчиков Java, вынудив сделать исключение из конструкции «идеального» конструктора в каждом приложении.

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

В итоге, , специфицируя static void main(), создает спецификацию с наименьшей сложностью, придерживаясь принципа помещения поведения в методы . Учитывая простоту реализации метода main(), который сам создает экземпляр класса и вызывает метод экземпляра, нет никакого реального преимущества в определении main() в качестве метода экземпляра.

15
задан Joel Coehoorn 28 November 2011 в 18:08
поделиться

4 ответа

Одна мысль, которая возникла у меня, заключалась в том, чтобы встроить уникальный идентификатор (возможно, случайную строку) как скрытое поле формы в форму, которая отправляется POST. Строку идентификатора можно поместить в базу данных как «идентификатор транзакции». Теперь, когда вы переходите к обновлению базы данных, сначала проверьте, есть ли существующая запись с отправленным идентификатором транзакции, и если да, предположите, что это дубликат, и не меняйте базу данных.

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

EDIT : как указано в комментариях , хранение идентификаторов транзакций в базе данных может занять много места, но если это проблема, вы можете хранить в памяти кеш всех транзакций, обработанных за последние 5 минут / 1 час / 1 день / что угодно. Это должно сработать, если вы не столкнетесь с решительным хакером ...

1
ответ дан 1 December 2019 в 04:10
поделиться

Давайте посмотрим на классическое закрытие add-n из Что такое замыкание .

(define (add a)
  (lambda (b)
    (+ a b)))

(define add3 (add 3))

(add3 4) returns 7

В приведенном выше лямбда-выражении a является свободная переменная , которая определена в ссылке в Википедии как:

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

Возвращаясь к

def filesEnding(query: String) =
  filesMatching(_.endsWith(query))

Неявная функция x => x.endsWith (query) - это функция первого класса, которой присваивается значение первого класса сопоставитель и _ .ndsWith () закрывается по запросу , аналогично тому, как 3 закрывает a в ( добавить 3) . (add3 4) эквивалент выполняется сопоставителем (file.getName) .

Править : Сложная часть - это функция в Scala, называемая анонимными функциями синтаксиса заполнителя. Используя _ вместо отправителя или параметра, Scala автоматически создает анонимную функцию, которую мы можем рассматривать как лямбда-выражение.

Например,

_ + 1              creates       x => x + 1
_ * _              creates       (x1, x2) => x1 * x2
_.endsWith(query)  creates       x => x.endsWith(query)

Внутри функции x => x.endsWith (запрос) , Я не уверен, хорошо это или нет.

Но ваше решение « вертикальный кеш ответа » звучит неплохо

1
ответ дан 1 December 2019 в 04:10
поделиться

Этот символ замены Unicode появляется только тогда, когда кодировка неверна. Итак, в вашем случае вы объявили свои данные как закодированные в UTF-8, но это не так (по крайней мере, та часть, которую вы процитировали). ü , закодированный в ISO 8859-1, - это 0xFC, но это недопустимый октет в UTF-8.

Поэтому вам нужно убедиться, что ваши данные действительно закодированы в UTF-8. Существуют функции, которые могут проверять, соответствует ли данная строка UTF-8, например mb_detect_encoding или , эта is_utf8 функция .

) в качестве первичного ключа. (без отдельной индексации для RANDOMKEY.
  • Используйте как RANDOMKEY, так и SHA-1 в качестве поиска в базе данных.
  • Не сохраняйте идентификатор сеанса (избегайте проблем с конфиденциальностью, связанных с возможностью сопоставлять множество записей одному и тому же пользователю)
  • Срок действия результатов истекает через 2-3 дня. (Позволяет ежедневному пакетному заданию выполнять очистку и предотвращает создание проблем для пользовательских сеансов, которые являются полудлительными)
  • Этот метод требует, чтобы любой хакер знал оба идентификатора сеанса и случайный ключ.

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

  • Не сохранять идентификатор сеанса (избегайте проблем с конфиденциальностью, связанных с возможностью сопоставлять множество записей с одним и тем же пользователем)
  • Срок действия результатов истекает через 2-3 дня. (Позволяет выполнять ежедневное пакетное задание по очистке и предотвращает создание проблем для пользовательских сеансов, которые являются полудлительными)
  • Этот метод требует, чтобы любой хакер знал как идентификатор сеанса, так и случайный ключ.

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

  • Не сохранять идентификатор сеанса (избегайте проблем с конфиденциальностью, связанных с возможностью сопоставлять множество записей с одним и тем же пользователем)
  • Срок действия результатов истекает через 2-3 дня. (Позволяет выполнять ежедневное пакетное задание по очистке и предотвращает создание проблем для пользовательских сеансов, которые являются полудлительными)
  • Этот метод требует, чтобы любой хакер знал как идентификатор сеанса, так и случайный ключ.

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

    1
    ответ дан 1 December 2019 в 04:10
    поделиться

    Да, я считаю, что вам следует выполнять перенаправление после POST, за исключением запросов API. Без этого вам не только придется беспокоиться о получении дубликатов POST, когда пользователь использует кнопку «Назад», но браузер также будет выводить раздражающие диалоги пользователя, когда они пытаются использовать кнопку «Назад».

    Response.sendRedirect работает на практике , но технически говоря, это отправка неправильного кода ответа HTTP для этой цели. sendRedirect отправляет 302, но правильный код для преобразования POST в GET - 303. (однако большинство браузеров будут рассматривать 302 так же, как 303, если они получат его в ответ на POST)

    В общем, вы хотите, чтобы перенаправление отправляло пользователя в любое представление, в котором будет отображаться эффект их изменения. Например, если они редактируют виджет, они должны быть перенаправлены на представление этого виджета. Если они удаляют виджет, они должны быть перенаправлены в представление, в котором виджет должен был появиться, когда он существовал (например, список виджетов).

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

    /widget?id=12345&msg=Widget+modified.
    

    Здесь параметр «msg» содержит сообщение «Виджет изменен». Единственным недостатком этого подхода является то, что вредоносные сайты могут отправлять вашим пользователям запутанные / вводящие в заблуждение сообщения. например:

    /account?msg=Foo+Corp.+hates+you.
    

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

    они должны быть перенаправлены в представление, в котором виджет появился бы, когда он существовал (возможно, список виджетов).

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

    /widget?id=12345&msg=Widget+modified.
    

    Здесь параметр «msg» содержит сообщение «Виджет изменен». Единственным недостатком этого подхода является то, что вредоносные сайты могут отправлять вашим пользователям запутанные / вводящие в заблуждение сообщения. например:

    /account?msg=Foo+Corp.+hates+you.
    

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

    они должны быть перенаправлены в представление, в котором виджет появился бы, когда он существовал (возможно, список виджетов).

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

    /widget?id=12345&msg=Widget+modified.
    

    Здесь параметр «msg» содержит сообщение «Виджет изменен». Единственным недостатком этого подхода является то, что вредоносные сайты могут отправлять вашим пользователям запутанные / вводящие в заблуждение сообщения. например:

    /account?msg=Foo+Corp.+hates+you.
    

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

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

    /widget?id=12345&msg=Widget+modified.
    

    Здесь параметр «msg» содержит сообщение «Виджет изменен». Единственным недостатком этого подхода является то, что вредоносные сайты могут отправлять вашим пользователям запутанные / вводящие в заблуждение сообщения. например:

    /account?msg=Foo+Corp.+hates+you.
    

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

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

    /widget?id=12345&msg=Widget+modified.
    

    Здесь параметр «msg» содержит сообщение «Виджет изменен». Единственным недостатком этого подхода является то, что вредоносные сайты могут отправлять вашим пользователям запутанные / вводящие в заблуждение сообщения. например:

    /account?msg=Foo+Corp.+hates+you.
    

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

    Параметр содержит сообщение «Виджет изменен». Единственным недостатком этого подхода является то, что вредоносные сайты могут отправлять вашим пользователям запутанные / вводящие в заблуждение сообщения. например:

    /account?msg=Foo+Corp.+hates+you.
    

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

    Параметр содержит сообщение «Виджет изменен». Единственным недостатком этого подхода является то, что вредоносные сайты могут отправлять вашим пользователям запутанные / вводящие в заблуждение сообщения. например:

    /account?msg=Foo+Corp.+hates+you.
    

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

    12
    ответ дан 1 December 2019 в 04:10
    поделиться
    Другие вопросы по тегам:

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