Истинной точкой входа в любое приложение является статический метод. Если бы язык Java поддерживал метод экземпляра в качестве «точки входа», то среда выполнения должна была бы реализовывать его внутри как статический метод, который создавал экземпляр объекта с последующим вызовом метода экземпляра.
С учетом этого, я рассмотрю обоснование выбора конкретного из следующих трех вариантов:
static void main()
, как мы видим это сегодня. void main()
вызвал только что созданный объект. Program
, то выполнение будет состоять из new Program()
). static void main()
main()
. void main()
new ClassName()
. main()
. new ClassName()
Я пойду в обратном порядке для этого.
Имейте в виду, что одной из целей разработки Java было подчеркнуть (требовать, когда это возможно) хорошие практики объектно-ориентированного программирования. В этом контексте конструктор объекта инициализирует объект, но не должен отвечать за поведение объекта. Следовательно, спецификация, которая давала точку входа в new ClassName()
, могла бы запутать ситуацию для новых разработчиков Java, вынудив сделать исключение из конструкции «идеального» конструктора в каждом приложении.
Сделав main()
метод экземпляра, вышеуказанная проблема, безусловно, решена. Однако это создает сложность, требуя, чтобы спецификация перечисляла подпись конструктора класса входа, а также подпись метода main()
.
В итоге, , специфицируя static void main()
, создает спецификацию с наименьшей сложностью, придерживаясь принципа помещения поведения в методы . Учитывая простоту реализации метода main()
, который сам создает экземпляр класса и вызывает метод экземпляра, нет никакого реального преимущества в определении main()
в качестве метода экземпляра.
Одна мысль, которая возникла у меня, заключалась в том, чтобы встроить уникальный идентификатор (возможно, случайную строку) как скрытое поле формы в форму, которая отправляется POST. Строку идентификатора можно поместить в базу данных как «идентификатор транзакции». Теперь, когда вы переходите к обновлению базы данных, сначала проверьте, есть ли существующая запись с отправленным идентификатором транзакции, и если да, предположите, что это дубликат, и не меняйте базу данных.
Конечно, как я сказал, это это просто мысль. Я не знаю, какие методы реально используются на практике. (Я подозреваю, что многие менее важные сайты просто игнорируют проблему и надеются, что их пользователи будут сообразительными ... проигрышное предложение, если я когда-либо его видел; -)
EDIT : как указано в комментариях , хранение идентификаторов транзакций в базе данных может занять много места, но если это проблема, вы можете хранить в памяти кеш всех транзакций, обработанных за последние 5 минут / 1 час / 1 день / что угодно. Это должно сработать, если вы не столкнетесь с решительным хакером ...
Давайте посмотрим на классическое закрытие 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 (запрос)
,
Я не уверен, хорошо это или нет.
Но ваше решение « вертикальный кеш ответа » звучит неплохо
Этот символ замены Unicode появляется только тогда, когда кодировка неверна. Итак, в вашем случае вы объявили свои данные как закодированные в UTF-8, но это не так (по крайней мере, та часть, которую вы процитировали). ü , закодированный в ISO 8859-1, - это 0xFC, но это недопустимый октет в UTF-8.
Поэтому вам нужно убедиться, что ваши данные действительно закодированы в UTF-8. Существуют функции, которые могут проверять, соответствует ли данная строка UTF-8, например mb_detect_encoding
или , эта is_utf8
функция .
Этот метод требует, чтобы любой хакер знал оба идентификатора сеанса и случайный ключ.
Этот подход может показаться излишним, но для таких ситуаций, как сброс пароля, можно использовать механизм с усиленным перенаправлением.
Этот метод требует, чтобы любой хакер знал как идентификатор сеанса, так и случайный ключ.
Такой подход может показаться излишним, но механизм с усиленным перенаправлением может использоваться для таких ситуаций, как сброс пароля.
Этот метод требует, чтобы любой хакер знал как идентификатор сеанса, так и случайный ключ.
Такой подход может показаться излишним, но механизм с усиленным перенаправлением может использоваться для таких ситуаций, как сброс пароля.
Да, я считаю, что вам следует выполнять перенаправление после 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.
Если вас это действительно беспокоит, вы можете включить подпись сообщения с истекающим сроком действия в качестве дополнительного параметра. Если подпись недействительна или срок ее действия истек, просто не отображайте это сообщение.