Страницы

Поиск по вопросам

понедельник, 4 февраля 2019 г.

Как узнать время сервера из присланного ответа POST запроса?

Как вытащить время сервера из ответа, который пришел на POST запрос? Для отправки POST запроса с Android используется библиотека OKHTTP.
String post(String...url) throws IOException { FormEncodingBuilder form = new FormEncodingBuilder(); RequestBody formBody =form.build(); Request request = new Request.Builder() .header("Cookie", x) .url(url[0]) .post(formBody) .build(); Response response = client.newCall(request).execute(); return response.body().string(); }


Ответ

В Response есть параметр Date, в котором передается текущее время сервера.
Пример Response Headers
Date: Fri, 13 Nov 2015 23:24:28 GMT Content-Type: application/json Transfer-Encoding: chunked Connection: keep-alive
Но в вашем методе post() возвращается только body, тогда как Date хранится в headers
Соответственно пример кода для получения даты:
Date post(String...url) throws IOException { FormEncodingBuilder form = new FormEncodingBuilder(); RequestBody formBody =form.build(); Request request = new Request.Builder() .header("Cookie", x) .url(url[0]) .post(formBody) .build(); Response response = client.newCall(request).execute(); //return response.body().string(); //Возвращается только Body. return response.headers().getDate("Date"); //Возвращаем объект Date. }

Сессии и DAO классы в Hibernate

Здравствуйте.
Есть маленький проектик работающий с БД. В качестве ORM решения выбран Hibernate 4.
Попутно обуздывая фреймворк, создал классы сущностей, связал аннотациями, использовал DAO pattern. Но: в имплементации ДАО классов в каждом изменяющем БД методе сессия открывалась и закрывалась прямо в методе (как и в этой туториал ссылочке http://javaxblog.ru/article/java-hibernate-1/). Пример
Session session = null; try { session = HibernateUtil.getSessionFactory().openSession(); session.beginTransaction(); // Здесь добавляю, обновляю или удаляю // ... session.getTransaction().commit(); } catch (Exception e) { // Обрабатываю // rollback() } finally { // Закрываю if (session != null && session.isOpen()) { session.close(); } }
Но что-то подсказывает, что это как-то, мягко говоря, не правильно. Порыв немного интернет, наткнулся на статейку (https://developer.jboss.org/wiki/GenericDataAccessObjects), где говорится, что ДАО имплементации не должны создавать сессию внутри, а на неё нужно лишь ссылаться. Если я правильно понял, ДАО имплементаций не должно волновать создание сессий.
You could also use constructor injection. How you set the Session and what scope this Session has is of no concern to the actual DAO implementation. A DAO should not control transactions or the Session scope.
Интересует вопрос опытных разработчиков: создавать ли сессию один раз на всё приложение и просто в сеттере давать ссылочку ДАО классам (при этом сессию не закрывать), или же в каждом методе ДАО класса создавать и закрывать сессию?


Ответ

Использование ссылки на SessionFactory внутри реализации DAO и создание сессии на каждый вызов дао методов. Для массивных изменений рекомендуется batch update.

Многопоточный веб сервер на C++

Здравствуйте. Интересует правильная реализация многопоточности веб сервера на C++. Проблема в следующем: Раньше я думал что для того чтобы сервер был многопоточным, достаточно лишь после принятия запроса от клиента создать для него новый поток, с помощью CreateThread, и так для каждого клиента.
Но позже узнал, что нет смысла создавать потоков больше чем количество логических процессоров в системе, так как будут потери при переключении между потоками, и программа будет работать медленнее.
Так как же быть? С одной стороны, на всяких хабрах и блогах пишут что достаточно создать поток функцией CreateThread. С другой стороны некий гуру пишет, что 100-200 потоков одновременно очень сильно снижают производительность на обычном компьютере.


Ответ

В целом, вы все верно пишете, но я бы сместил акценты. Машину действительно можно загрузить двумя сотнями потоков, но это не значит, что они ее обязательно загрузят или что это решение будет грузить меньше других - у любого сервиса есть предел, после которого он превращается в тыкву. В принципе, у вас три основных варианта: синхронная обработка запросов, которая будет очень медленной, многопоточная обработка запросов, и, наконец, асинхронная обработка запросов в том или ином виде, под которой я прячу всякие модели типа event loop и всё остальное. Последний вариант наиболее производительный, но очень сложный, и нужный только в таких монстрах, как nginx - вам для ваших целей наверняка хватит простой многопоточной обработки. Скорее всего, у вас внутри сервера не раз встретится такая штука, как блокирующее ожидание, во время которого процессор ждет ответа от внешнего сервера (базы данных) или файловой системы - в это время другие ОС передаст управление другим потокам, и вы окажетесь только в выигрыше. Единственная проблема, которую вносит многопоточная схема - это момент, при котором количество приходящих запросов начинает превышать количество запросов, которые может обработать сервер, и появляющиеся снова потоки начинают отбирать процессорное время, ухудшая производительность. Здесь, наконец, и появляется то, ради чего я писал весь этот ответ.
Вам не стоит делать createThread(). Создавать поток на каждый запрос печально по двум причинам - во-первых, это ненужные расходы на новый тред, а во-вторых - отсутствие контроля за количеством тредов, которое решило бы вышеозвученную проблему с переполнением сервера. Вам нужно реализовать пул тредов фиксированной величины; максимальная вместимость пула - это то, сколько одновременных запросов готов обработать сервер, а свежепришедшие запросы будут вынуждены ждать освобождения рабочего треда, что позволит сервису не превратиться-таки в тыкву. При этом размер пула может быть как равен числу процессоров, так и ичисляться сотнями - тут сложно посоветовать что-то конкретное, но в текущем проекте поднятие лимита с двадцати до пятисот тредов во встроенном сервере дало прирост производительности в десять раз (на самом деле не прирост, а более эффективное использование ресурсов, да и число в пятьсот было взято с потолка, и, наверное, стоит его уменьшить).
В общем, не волнуйтесь так сильно за модель, она более чем рабочая. Не забывайте только ограничивать возможности сервиса сверху.

Как разобрать matrix на scale, rotate, translate, skew?

Дело такое, getComputedStyle(element).getPropertyValue("transform") возвращает matrix(a, c, b, d, tx, ty). C translate всё вроде бы просто: translateX = tx, translateY = ty. А вот как вытащить scale, rotate, skew я немного не понимаю потому как во первых в rotate и scale должны быть градусы, во вторых: вроде как skewX = b, skewY = c, а scaleX = a, scaleY = d, но при этом что бы повернуть элемент в матрице a = cos(x), b = sin(x), c = -sin(x), d cos(x). Вообщем из набора параметров matrix я бы ещё составил а вот из matrix вытащить параметры вообще не понимаю как. Подскажите пожалуйста как перевести матрицу в понятный простому человеку язык или подскажите как можно получить свойство transform не в matrix, а в scale, rotate, translate, skew?


Ответ

В черновике спецификации описано какие значения, что означают.
Трансформации осуществляются с помощью матрицы трансформаций, в общем случае (3D) матрица 4х4

Матрица, которую вы получаете matrix(a, c, b, d, tx, ty) представляется в следующем виде:

Как вы правильно отметили: tx, ty - отвечают за перемещение.
За масштабирование отвечают значения лежащий на главной диагонали, в нашем случае это a,d, при это a - масштабирование по ширине, d - по высоте.
c,b - отвечают за наклон
и все вместе a,b,c,d - за поворот.
Подробнее можно увидеть на картинке

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

Как в консоли указать начальное значение при вводе?

Дефолтное значение - это хорошо. Но что, когда дефолтное значение - это длинная строка, а у нее надо изменить 1 символ? Не хотелось бы набирать его вручную полностью (тем более это повышает шанс допустить опечатку)
Есть ли возможность сделать ввод через Console.ReadLine так, чтобы уже было введено какое то значение?


Ответ

Вариант без SendKeys, из аналогичного вопроса на английском
// write the initial buffer char[] buffer = "Initial text".ToCharArray(); Console.WriteLine(buffer);
// ensure the cursor starts off on the line of the text by moving it up one line Console.SetCursorPosition(Console.CursorLeft + buffer.Length, Console.CursorTop - 1);
// process the key presses in a loop until the user presses enter // (this might need to be a bit more sophisticated - what about escape?) ConsoleKeyInfo keyInfo = Console.ReadKey(true); while (keyInfo.Key != ConsoleKey.Enter) {
switch (keyInfo.Key) { case ConsoleKey.LeftArrow: ... // process the left key by moving the cursor position // need to keep track of the position in the buffer
// if the user presses another key then update the text in our buffer // and draw the character on the screen
// there are lots of cases that would need to be processed (backspace, delete etc) } keyInfo = Console.ReadKey(true); }

Необходимо ли папки 'packages' в C# проекте хранить в git-репозитории проекта?

У меня есть два два проекта HelloWorld и HelloWorld.UnitTests. Во втором применив nuget я установил NUnit, в результате чего создана папка packages. Использую Visual Studio 2013.
Сейчас репозиторий выглядит так:
.\HelloWorld\ .\HelloWorld.UnitTests\ .\HelloWorld.UnitTests\packages.config .\packages\ .\HelloWorld.sln
Папка packages появилась после того как сделал активным проект HelloWorld.UnitTests и применил команду Install-Package NUget в консоли.
В Python-е, есть так называемые файлы зависимостей и можно применить команду pip install -r requirements.txt. Но в C# такого решения не нашел. Меня смущает, что видимо придется хранить множество dll-файлов, хотя логичнее было бы в репозитории хранить файл зависимостей, аналогичный python-овскому решению с requirements.txt файлом.
Правильно ли я понимаю, что мне все-таки придется эту папку хранить в репозитории проекта?


Ответ

Основной способ подключения/удаления зависимостей в проект является nuget. В папке проекта у вас должен быть файл packages.config. В нем хранятся данные об используемых в проекте nuget-пакетах. Добавлять в VCS нужно именно его. На основании содержащихся в нем данных будут скачаны необходимые пакеты. Dll'ки же включать необязательно. Пример:

Операция :: c++

Где и как можно использовать операцию :: ?


Ответ

:: - это оператор, который используется для уточнения (квалификации) имен.
Бинарный оператор :: уточняет область видимости в которой находится имя. С левой стороны должна быть указана область видимости, с правой стороны - уточняемое имя. В качестве области видимости может быть использовано пространство имен (namespace) или тип.
namespace NamespaceName { struct TypeName { typedef int NestedType; }; } NamespaceName::TypeName a; // имя TypeName находится в пространстве имен NamespaceName NamespaceName::TypeName::NestedType b; // имя NestedType находится в типе NamespaceName::TypeName decltype(a)::NestedType c; // имя NestedType находится в типе-результате decltype(a)
Унарный оператор :: указывает что имя находится в глобальном пространстве имен.
int x; int main() { int x; return ::x; // Глобальная переменная }
Также как и для операторов и ->, после :: может быть указано ключевое слово template, чтобы показать что далее в коде идет использование шаблона:
struct X { template static void f(); }; template void g() { T::f<1>(); // Ошибка: "<" означает оператор меньше T::template f<1>(); // ОК, используется шаблон f<1> }