Предисловие
Обратите внимание, что для сохранения кода httpservletrequest не был объявлен в корпусе метода, а просверленная яма была непосредственно введена автофией.
Заключение: для тех, кто обеспокоен. Объявите httpservletrequest непосредственно на переменную члена контроллера с помощью @autowire, что является безопасным потоком!
@Controllerpublic class testcontroller {@autowire httpservletrequest запрос; @Requestmapping ("/") public void test () {request.getAttribute ("uid"); }}Вывод, как указано выше.
фон
Это верно. Поскольку я добавил информацию о аутентификации в главу запроса в проекте, и после того, как перехватчик перехватывает информацию и передаст проверку, я добавлю личность текущего пользователя к атрибуту запроса, что удобно для повторного использования его в уровне контроллера.
Вопрос: Почему бы не использовать @requestheader, чтобы получить его непосредственно на контроллере? Поскольку заголовок содержит зашифрованные данные и требует некоторой сложной аутентификации и суждения, этот шаг прямо брошен в перехватчик для выполнения.
Таким образом, после расшифровки я установил информацию пользователя (например, UID) в request.setAttribute() чтобы извлечь ее в контроллер.
Если вам нужно использовать запрос, вам, как правило, нужно объявить его на методе, например:
Сохранить общественный результат (httpservletrequest request) {// dosomething ();}Итак, если я использую UID для каждого метода, разве каждый метод не объявит параметр запроса, чтобы сохранить избыточный шаг? Я написал базовый класс.
Public Class CommonController {@autowire httpservletreqeust запрос; public String getUID () {return (string) request.getAttribute ("uid"); }}Позже я волновался, что, поскольку контроллер является синглтоном, это приведет к последующему Reqeust, охватывающему предыдущий запрос, и в условиях параллелистики существуют проблемы безопасности потоков. Поэтому я задал вопрос о Segmentfault, и большинство пользователей сети сказали, что действительно есть проблема с потоком! Адрес проблемы Segmentfault ### Процесс проверки Поскольку мнения большинства пользователей сети состоит в том, что они могут объявлять их только с точки зрения методов, я, естественно, не хочу отказываться от написания столько кода только сейчас, поэтому я начал свой процесс проверки. Энтузиастические программисты предоставили мне несколько решений. Поскольку я приложил усилия, чтобы доказать это, я помесчу результаты здесь и поделюсь ими с вами.
Метод 1
Первый метод состоит в том, чтобы отобразить объявление httpservletreqeust в методе контроллера, код выглядит следующим образом:
@RequestMapping ("/test")@restControllerPublic Class Ctest {logger logger = loggerFactory.getLogger (getClass ()); @Requestmapping ("/iiii") public String Test (httpservletrequest) {logger.info (request.hashcode () + ""); вернуть ноль; }}Нажмите F5 в браузере
Выход
В то время я был смущен, ** Я согласился быть безопасностью нитью! ** Разве это не такой же запрос? Ты шутишь, что ли! Я давно искал запрос на переписывание HashCode ()!
Ах, это правда, потому что я нажимаю F5 с моим браузером, и как бы я ни нажимал, я не могу моделировать параллелизм. Это эквивалентно серверу с использованием того же потока для обработки моего запроса. Что касается хэшкода этого запроса, согласно JDK, он рассчитывается на основе виртуального адреса OBJ в JVM. Я думаю, что произошло дальше. Если вы знаете, чего действительно хотите, я скажу мне!
предполагать
Пространство памяти запроса, применяемое для каждого потока на сервере, исправлено при запуске сервера. Затем каждый раз, когда я прошу, он создаст новый запрос в пространстве памяти, который он просил (возможно, структура, похожая на массив). (Подобно отправной точке массива всегда один и тот же адрес памяти). Затем я изначаю запрос, и он создаст новый запрос в начальной позиции и передаст его сервю и начнет обработку. После завершения обработки она будет уничтожена. Затем новый запрос, созданный его следующим запросом, уничтожен, поэтому он начинается с стартового адреса. Таким образом, все будет объяснено!
Предположение закончено
Проверьте гипотезу:
Я не дам ему времени уничтожить его, могу ли я проверить код
@RequestMapping ("/test")@restControllerPublic Class Ctest {logger logger = loggerFactory.getLogger (getClass ()); @Requestmapping ("/ooooo") public String testa (httpservlectrequest) бросает исключение {thread.sleep (3000); logger.info (request.hashcode () + ""); logger.info (reqeust.getheader ("uid"); return null;} @requestmapping ("/iiii") public String test (httpservletrequest) {logger.info (request.hashcode () + ""); logger.info (requust.getheader ("uid");Как упомянуто выше, я сплю в интерфейсе/OOOO в течение 3 секунд. Если он разделяет Requust, то последующий запрос будет перезаписать Reqeust во сне, а входящий UID является адресом интерфейса. Сначала стартовать /ооооо, а затем запустить /iiii
Выход
Controller.ctest: 33 - 364716268Controller.ctest: 34 - IIIICONTROLLER.CTEST: 26 - 1892130707CONTROLLER.CTEST: 27 - OOOOOOOO
Заключение: 1. Инициированное /III, инициированное позже, не перезаписывает предыдущие данные /OOOO, и не возникает проблемы безопасности потока. 2. Хашкод запроса отличается. Поскольку блокировка /оооо, заставляет другой поток необходимо его обрабатывать, он создает новый запрос вместо того же хэшкода, что и раньше.
Второй раунд проверки
открытый класс httptest {public static void main (string [] args) бросает исключение {for (int i = 300; i> 0; i--) {final int finali = i; new Thread () {@Override public void run () {System.out.println ("v ###" + finali); Httprequest.get ("http: // localhost: 8080/test/iiii?") .Header ("uid", "v ###" + finali) .send (); } }.начинать(); }}}При смоделированных условиях параллелизма UID300 в заголовке полностью принимает без переоценки
Таким образом, нет проблем с безопасностью потока.
Метод 2
В CommonController используйте @modelattribute для обработки.
Public Class CommonController {// @Autowired защищен httpservletrequest запрос; @Modelattribute public void bindreq (httpservletrequest) {this.request = request; } защищенный string getUID () {System.out.println (request.tostring ()); return request.getattribute ("uid") == null? null: (string) request.getattribute ("uid"); }}У этого есть проблемы с безопасностью нити! Последующий запрос может охватить предыдущий!
Проверочный код
@Restcontroller@requestmapping ("/test") открытый класс ctest extends commoncontroller {logger logger = loggerFactory.getLogger (getClass ()); @Requestmapping ("/iiii") public String test () {logger.info (request.getheader ("uid")); вернуть ноль; }} открытый класс httptest {public static void main (string [] args) бросает исключение {for (int i = 100; i> 0; i--) {final int finali = i; new Thread () {@Override public void run () {System.out.println ("v ###" + finali); Httprequest.get ("http: // localhost: 8080/test/iiii") .header ("uid", "v ###" + finali) .send (); } }.начинать(); }}}Результаты частичных выходных результатов были перехвачены
Controller.ctest: 26 - v ### 52controller.ctest: 26 - V ### 13Controller.ctest: 26 - V ### 57Controller.ctest: 26 - V ### 57Controller.ctest: 26 - V ### 21Controller.ctest: 26 - v ## 10Controller.ctest: 26 -v#v#v#v#v#v#v#v ## #ctest. v ### 82controller.ctest: 26 - v ### 93controller.ctest: 26 - v ### 71controller.ctest: 26 - v ### 71controller.ctest: 26 - v ### 71controller.ctest: 26 - v ### 71controller.ctest: 26 - v###########. v ### 71controller.ctest: 26 - v ### 85controller.ctest: 26 - v ### 85controller.ctest: 26 - v ### 14Controller.ctest: 26 - V ### 47controller.ctest: 26 - V ### 47controller.ctest: 26 -v#################controll v ### 22Controller.ctest: 26 - V ### 55Controller.ctest: 26 - V ### 61
Вы можете видеть, что 57, 71, 85 и 47 покрыты, и некоторые запросы потеряны!
Это несоблюдение темы!
Метод 3
Используйте CommonController в качестве базового класса для запроса Autowire.
Public Class CommonController {@Autowired защищен httpservletrequest запрос; Защищенная string getUID () {System.out.println (request.tostring ()); return request.getattribute ("uid") == null? null: (string) request.getattribute ("uid"); }}Испытательный интерфейс такой же, как и выше, и результаты удовлетворяют! Там нет покрытия для 100 запросов. Я увеличил масштаб и проверил его пять или шесть раз, и никаких покрытий для тысяч запросов. Это может доказать, что в этом методе письма нет проблем с безопасностью потока!
Другое интересное, что независимо от того, сколько параллелизма используется, хешкод запроса всегда одинакова. Более того, при тестировании разных интерфейсов в одном и том же контроллере это то же самое. При использовании сна для принудительного блока хэшкод одинаково. Тем не менее, хэшкод отличается при доступе к различным контроллерам, поэтому я не продолжал углубляться в то, как его реализовать.
Но вывод вышел, как говорится в статье в начале.
Суммировать
Вышеуказанное - все содержание этой статьи. Я надеюсь, что содержание этой статьи имеет определенную справочную ценность для каждого обучения или работы. Если у вас есть какие -либо вопросы, вы можете оставить сообщение для общения. Спасибо за поддержку Wulin.com.