Как указано в моем комментарии, utm.gif больше не используется. Google Analytics полностью переключилась на протокол измерений, и данные теперь отправляются в конечную точку для протокола измерения на google-analytics.com/collect. На самом деле это все равно возвращает прозрачный пиксель, поскольку вызов изображения с параметрами является методом завещания передачи информации через границы домена.
Теперь вы можете просто измерить протокол для реализации своего собственного трекера Google Analytics.
К quote myself :
Каждый вызов включает в себя, по меньшей мере, идентификатор учетной записи, к которой вы хотите отправить данные, идентификатор клиента, который позволяет группировать взаимодействия в сеансах (поэтому он должен быть уникальным для каждого посетителя, но он не должен идентифицировать пользователя лично), тип взаимодействия (просмотр страницы, событие, время и т. д., некоторые типы взаимодействий требуют дополнительных параметров) и версию используемого вами протокола ( на данный момент есть только одна версия).
Таким образом, самый простой пример для записи просмотра страницы будет выглядеть так:
www.google-analytics.com/collect/v= 1 & amp; tid = UA-XXXXY & amp; cid = 555 & amp; t = pageview & amp; dp =% 2Fmypage
blockquote>Возможно, вы захотите добавить IP-адрес пользователей (будет анонимным ymized автоматически) и пользовательский агент.
Однако похоже, что вы предпочитаете использовать стандартный код Google Analytics для сбора данных и ретрансляции вызова отслеживания через собственный сервер. Хотя я не использовал следующее в производстве, я не вижу причин, почему это не сработает.
Сначала вам нужен файл analytics.js. Самостоятельный хостинг файла обескуражен, но данная причина заключается в том, что иногда код иногда обновляется Google, и если вы его размещаете самостоятельно, вы можете пропустить обновления. Это можно исправить, установив задание cron, которое регулярно загружает файл на ваш сервер, поэтому у вас всегда есть текущая версия.
Затем вы адаптируете функцию автозагрузки GA для загрузки кода с вашего собственного сервера :
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){ (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o), m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m) })(window,document,'script','//www.myserver.com/analytics.js','ga');
Теперь у вас есть код, но вызов отслеживания по-прежнему будет отправлен на сервер Analytics (т. е. в вашем случае он вообще не будет отправлен). Таким образом, вам необходимо перенаправить вызов через ваш сервер.
Чтобы это стало возможным, в Google (Universal) Analytics Code есть функция , называемая «задачи». Задачи - это функции внутри код отслеживания, в котором собирается вызов отслеживания.
Можно изменять задачи, используя функцию «set» объекта трекера, используя имя задачи как параметр и передавая функцию, которая перезаписывает / перегружает функция задачи.
Ниже приведен пример из документации Google (за исключением того, что я пропустил ту часть, где данные по-прежнему отправляются в Google - вам это не нужно в данный момент):
ga('create', 'UA-XXXXX-Y', 'auto'); ga(function(tracker) { tracker.set('sendHitTask', function(model) { var payLoad = model.get('hitPayload'); var gifRequest = new XMLHttpRequest(); var gifPath = "/__ua.gif"; gifRequest.open('get', gifPath + '?' + payLoad, true); gifRequest.send(); }); }); ga('send', 'pageview');
Теперь это отправляет данные в файл с именем __ua.gif на вашем собственном сервере (если вам нужно отправить данные по междоменному домену, вы можете просто сделать var ua = new Image; ua.src = gifPath + '?' + payLoad для создания запроса на изображение.
Параметр модели для функции
sendHitTask
содержит (помимо большого количества служебных данных) полезную нагрузку, то есть собранную строку запроса t hat содержит данные аналитики. Затем вы можете создать свой _ua.gif скрипт, который проксирует запрос на google-analytics.com/collect.В этот момент пользовательский агент будет вашим сценарием, а IP-адрес будет вашим адресом, поэтому вам нужно включить & amp; uip (переопределение пользовательского IP-адреса) и & amp; ua (переопределить агент пользователя) параметры ( https://groups.google.com/forum/#!msg/google-analytics-measurement-protocol/8TAp7_I1uTk/KNjI5IGwT58J ) для получения гео- и технической информации.
Если вы чувствуете себя более предприимчивым, вы можете переопределить
buildHitTask
вместо этого и попробовать и добавить дополнительные параметры там (больше хлопот, вероятно, так как вам нужно будет получить IP-адрес откуда-то).Дополнительный параметр см. в ссылке для analytics.js и протокола измерения .
Да, finally
будет назван после выполнения try
или catch
блоки кода.
Единственные времена finally
не будет назван:
System.exit()
Runtime.getRuntime().halt(exitStatus)
try
или catch
блокkill -9 <pid>
на UNIXfinally
блок будет выполняемым потоком демона и всем другим выходом потоков недемона прежде finally
названВ дополнение к точке о возврате в окончательной замене возврата в блоке попытки то же верно для исключения. Наконец блок, который выдает исключение, заменит возврат или исключение, выданное из блока попытки.
Это на самом деле верно на любом языке..., наконец будет всегда выполняться перед оператором возврата, неважно, где тот возврат находится в теле метода. Если бы это не имело место, наконец, то блок не имел бы большого значения.
Наконец блок всегда выполняется, если нет аварийное завершение программы, или следующее из катастрофического отказа JVM или от вызова до System.exit(0)
.
Вдобавок ко всему, любое значение, возвращенное из наконец блока, будет переопределять значение, возвращенное до выполнения наконец блок, так остерегаться проверки всех точек выхода при использовании попытки наконец.
Я попробовал вышеупомянутый пример небольшой модификацией -
public static void main(final String[] args) {
System.out.println(test());
}
public static int test() {
int i = 0;
try {
i = 2;
return i;
} finally {
i = 12;
System.out.println("finally trumps return.");
}
}
Вышеупомянутые выводы кода:
наконец возврат козырей.
2
Это вызвано тем, что когда return i;
выполняется i
имеет значение 2. После этого finally
блок выполняется, где 12 присваивают i
и затем System.out
выполняется.
После выполнения finally
заблокируйтесь try
блок возвращается 2, вместо того, чтобы возвратиться 12, потому что этот оператор возврата не выполняется снова.
При отладке этого кода в Eclipse затем, Вы получите чувство что после выполнения System.out
из finally
заблокируйтесь return
оператор try
блок выполняется снова. Но дело обстоит не так. Это просто возвращает значение 2.
Логический способ думать об этом:
наконец всегда выполняется, если нет аварийное завершение программы (как вызов System.exit (0)..). таким образом Ваш sysout будет распечатан
Также возврат в наконец выбросит любое исключение. http://jamesjava.blogspot.com/2006/03/dont-return-in-finally-clause.html
Кроме того, хотя это - плохая практика, если будет оператор возврата в наконец блок, то это превзойдет любой другой возврат из регулярного блока. Таким образом, следующий блок возвратил бы false:
try { return true; } finally { return false; }
То же самое с выдаванием исключения от наконец блока.
Да это назовут. Это - смысл наличия наконец ключевое слово. Если выпрыгивание из блока попытки/выгоды могло просто пропустить наконец блок, это совпало с помещением System.out.println вне попытки/выгоды.
Пример кода:
public static void main(String[] args) {
System.out.println(Test.test());
}
public static int test() {
try {
return 0;
}
finally {
System.out.println("finally trumps return.");
}
}
Вывод:
finally trumps return.
0
В дополнение к другим ответам важно указать, что 'finally' имеет право переопределить любое исключение / возвращаемое значение блоком try..catch. Например, следующий код возвращает 12:
public static int getMonthsInYear() {
try {
return 10;
}
finally {
return 12;
}
}
Аналогично, следующий метод не генерирует исключение:
public static int getMonthsInYear() {
try {
throw new RuntimeException();
}
finally {
return 12;
}
}
Хотя следующий метод выдает его:
public static int getMonthsInYear() {
try {
return 12;
}
finally {
throw new RuntimeException();
}
}
Наконец, всегда запускается, в этом вся суть, просто потому, что это появляется в коде после возврата, не означает, что это реализовано именно так. Среда выполнения Java отвечает за запуск этого кода при выходе из блока try
.
Например, если у вас есть следующее:
int foo() {
try {
return 42;
}
finally {
System.out.println("done");
}
}
Среда выполнения сгенерирует что-то вроде этого:
int foo() {
int ret = 42;
System.out.println("done");
return 42;
}
Если возникает неперехваченное исключение, запускается блок finally
, и исключение продолжает распространяться.
В этом и заключается вся идея блока finally. Он позволяет вам убедиться, что вы выполнили очистку, которая в противном случае могла бы быть пропущена из-за возврата, среди прочего, конечно.
Finally вызывается независимо от того, что происходит в блоке try (если только вы не вызываете System.exit(int)
или виртуальная машина Java не вылетает по какой-то другой причине).
Потому что блок finally будет вызываться всегда, пока вы не вызовете System.exit()
(или поток не завершится).
Вот официальные слова из спецификации языка Java.
14.20.2. Выполнение try-finally и try-catch-finally
Оператор
try
с блокомfinally
выполняется первым путем выполнения блокаtry
. Тогда есть выбор:
- Если выполнение блока
try
завершается нормально, [...]- Если выполнение блока
try
завершается внезапно из-за ошибкиthrow
значения V , [...]- Если выполнение блока
try
завершается внезапно по любой другой причине R , затем выполняется блокfinally
. Затем есть выбор:
- Если блок finally завершается нормально, то оператор
try
завершается внезапно по причине R .- Если блок
finally
завершается внезапно по причине S , то операторtry
завершается внезапно по причине S ( и причина R отброшена ).
Спецификация для return
фактически делает это явным:
ReturnStatement: return Expression (опт);
Оператор
return
безВыражение
пытается передать управление вызывающей стороне метода или конструктора, который его содержит.Оператор
return
с выражениемпытается передать управление вызывающей стороне метода, который его содержит; значение
Выражения
становится значением вызова метода.В предыдущих описаниях говорится, что « пытается передать управление », а не просто « передает управление », потому что, если есть какие-либо операторы
try
в пределах метод или конструктор, чьи блокиtry
содержат операторreturn
, тогда любые предложенияfinally
из этих операторовtry
будут выполнены по порядку, от внутреннего к самому внешнему, прежде чем управление будет передано вызывающей стороне метода или конструктора. Внезапное завершение предложенияfinally
может прервать передачу управления, инициированную операторомreturn
.
Это потому, что вы присвоили i значение 12, но не вернули значение i функции. Правильный код выглядит следующим образом:
public static int test() {
int i = 0;
try {
return i;
} finally {
i = 12;
System.out.println("finally trumps return.");
return i;
}
}
Вот некоторые условия, которые могут обойти наконец блок:
Последний пример выходов потока недемона:
public class TestDaemon {
private static Runnable runnable = new Runnable() {
@Override
public void run() {
try {
while (true) {
System.out.println("Is alive");
Thread.sleep(10);
// throw new RuntimeException();
}
} catch (Throwable t) {
t.printStackTrace();
} finally {
System.out.println("This will never be executed.");
}
}
};
public static void main(String[] args) throws InterruptedException {
Thread daemon = new Thread(runnable);
daemon.setDaemon(true);
daemon.start();
Thread.sleep(100);
// daemon.stop();
System.out.println("Last non-daemon thread exits.");
}
}
Вывод:
Is alive
Is alive
Is alive
Is alive
Is alive
Is alive
Is alive
Is alive
Is alive
Is alive
Last non-daemon thread exits.
Is alive
Is alive
Is alive
Is alive
Is alive
Потому что финал всегда вызывается в любых случаях, которые у вас есть. У вас нет исключения, оно по-прежнему вызывается, перехватывает исключение, оно по-прежнему называется
Рассмотрим это в нормальном ходе выполнения (т.е. без выброса исключения): если метод не является 'void', то он всегда явно возвращает что-то, но в конечном итоге всегда выполняется