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

Для этого нам понадобится Nginx с PHP, подойдёт даже работающий на локальном компьютере или же локально на виртуальной машине, а также любой shared хостинг, который поддерживает PHP (5.6 и новее).

Работает эта схема следующим образом: Nginx выступает в роли самого proxy сервера, который указываем в качестве прокси в браузере, PHP в связке с этим Nginx занимается приёмом запросов от браузера (или скрэппера/кроулера) и отправляет его на shared хостинг, где мы должны разместить файл Proxy.php из репозитория https://github.com/zounar/php-proxy

Этот скрипт можно немного по-вкусу модифицировать, например убрать аутентификаицю на уровне заголовков, передаваемых в скрипт (но можно и оставить для секьюрности), в своём примере я убрал для сокращения описания шагов. Но настройку http basic аутентификацию в nginx опишу.

Здесь не буду объяснять, как устанавливать nginx, а также PHP-FPM.

Настраиваем виртуальный хост nginx следующим образом:

server {
listen 3128;
server_name _;
root /home/user/webproxy;
index index.php;

auth_basic "Restricted";
auth_basic_user_file /home/user/web/.htpasswd; #файл с хешированным паролем для http basic аутентификации

location ~ \.php$ {
fastcgi_split_path_info ^(.+?\.php)(/.*)$;
if (!-f $document_root$fastcgi_script_name) {
return 404;
}
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_pass 127.0.0.1:9000;
}

location / {
rewrite ^/(.*)$ /index.php?url=$host$uri; #здесь передаём все запросы нашего браузера/скрэппера/кроулера путём get в переменную url
}
}

Скрипт, который нужно положить в /home/webproxy/index.php:

<?php

$url = $_GET['url'];

$request = curl_init('http://your-shared-hosting.xyz/Proxy.php'); //путь к файлу на shared хостинге

curl_setopt($request, CURLOPT_HTTPHEADER, array(
'User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:70.0) Gecko/20100101 Firefox/70.0',
'Proxy-Auth: SetInTheProxyPHPifEnabled',
'Proxy-Target-URL: https://'.$url
));

curl_exec($request);

?>

 

Менять можно по своему вкусу для сокрытия такого очевидного использования.

От хостинга требуется чтобы в PHP была поддержка libcurl, gzip и PHP safe_mode disabled (практически любой хостинг).

function returnStatus(req, status) {
//console.log(req);
if(status == 200) {
console.log("The url is available");
// send an event
}
else {
console.log("The url returned status code " + status);
// send a different event
}
}

function fetchStatus(address) {
var client = new XMLHttpRequest();
client.onreadystatechange = function() {
// in case of network errors this might not give reliable results
if(this.readyState == 4)
returnStatus(this, this.status);
}
client.open(“HEAD”, address);
client.send();
}


fetchStatus("/");

 

It will be upload files of any type in folder $uploaddir:

<!DOCTYPE HTML>
<HTML>
  <HEAD>
    <meta charset="utf-8">
    <title>upload</title>
  </HEAD>
  <BODY>
    <h1>Upload file service</h1>
    <hr>
<?php
$uploaddir = './files/';


if(isset($_FILES['userfile'])){
    foreach ($_FILES['userfile']['name'] as $key => $value) {
        echo "<b>".$value."</b>";
        $uploadfile = $uploaddir.basename($_FILES['userfile']['name'][$key]);
        if (copy($_FILES['userfile']['tmp_name'][$key], $uploadfile)){
            echo "OK<br>";
        }
        else {
            echo "Error";
            //exit;
        }
        echo "<p><b>Name</b>: ".$_FILES['userfile']['name'][$key]."</p>";
        echo "<p><b>Mime-type</b>: ".$_FILES['userfile']['type'][$key]."</p>";
        echo "<p><b>Size</b>: ".$_FILES['userfile']['size'][$key]."</p>";
        echo "<p><b>TMP Name</b>: ".$_FILES['userfile']['tmp_name'][$key]."</p>";
        echo "<hr>";
    }
}
?>
    <form method="post" enctype="multipart/form-data">
      <input type="file" name="userfile[]" multiple="true">
      <input type="submit" value="upload">
    </form>
  </BODY>
</HTML>


Создаём в корне сайта out.php

В неё внутри PHP-тегов пишем такой код:

    if ((isset($_GET['link'])) AND (preg_match( '/^(http|https)://[a-z0-9]+([-.]{1}[a-z0-9]+)*.[a-z]{2,5}'.'((:[0-9]{1,5})?/.*)?$/i' ,$_GET['link']))){
        header("Location: ".$_GET['link']."");
    }

После сохранения, заменяем все ссылки на сайте на подобные: /out.php?link-http://itblog.pp.ua. Это позволяет поисковым системам не считать эти ссылки за внешние, тем самым повышает, а точнее не снижает тИЦ и PR сайта.

Чтобы в WordPress скрипте были относительные ссылки, вместо привязанных к одному домену, необходимо в начало файла wp-config.php добавить следующие строки:

define('WP_SITEURL', '/');
define('WP_HOME', '/');

Работа с JTable в Java SE построена на основе паттерна MVC, поэтому работать мы будем с моделью компонента jTable.

package example.Models;

import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.sql.Types;
import java.util.ArrayList;
import javax.swing.table.AbstractTableModel;

public class DbTableModel extends AbstractTableModel {

    private Object[][] content;     //хранит данные
    private String[] columnNames;   //хранит названия заголовков
    private Class[] columnClasses;  //хранит типы полей (столбцов)

    public DbTableModel(Connection con, String query, String tableName) throws SQLException {
        //super();
        getTableContent(con, query, tableName);
    }

    private void getTableContent(Connection conn, String query, String tableName) throws SQLException {
        DatabaseMetaData md = conn.getMetaData();
        ResultSet rs = md.getColumns(null, null, tableName, null);

        ArrayList colNamesList = new ArrayList();
        ArrayList colTypesList = new ArrayList();

        while (rs.next()) {
            colNamesList.add(rs.getString("COLUMN_NAME"));

            int dbType = rs.getInt("DATA_TYPE");
            switch (dbType) {
                case Types.INTEGER:
                    colTypesList.add(Integer.class);
                    break;
                case Types.FLOAT:
                    colTypesList.add(Float.class);
                    break;
                case Types.DOUBLE:
                case Types.REAL:
                    colTypesList.add(Double.class);
                    break;
                case Types.DATE:
                case Types.TIME:
                case Types.TIMESTAMP:
                    colTypesList.add(java.sql.Date.class);
                    break;
                default:
                    colTypesList.add(String.class);
                    break;
            }
        }

        columnNames = new String[colNamesList.size()];
        colNamesList.toArray(columnNames);

        columnClasses = new Class[colTypesList.size()];
        colTypesList.toArray(columnClasses);

        Statement st = conn.createStatement();
        rs = st.executeQuery(query);

        ArrayList rowList = new ArrayList();

        while (rs.next()) {
            ArrayList cellList = new ArrayList();
            for (int i = 0; i < columnClasses.length; i++) {
                Object cellValue = null;
                if (columnClasses[i] == String.class) {
                    cellValue = rs.getString(columnNames[i]);
                }
                else if (columnClasses[i] == Integer.class) {
                    cellValue = new Integer(rs.getInt(columnNames[i]));
                }
                else if (columnClasses[i] == Float.class) {
                    cellValue = new Float(rs.getInt(columnNames[i]));
                }
                else if (columnClasses[i] == Double.class) {
                    cellValue = new Double(rs.getDouble(columnNames[i]));
                }
                else if (columnClasses[i] == java.sql.Date.class) {
                    cellValue = rs.getDate(columnNames[i]);
                }
                else {
                    System.out.println("Can't define column type " + columnNames[i]);
                }
                cellList.add(cellValue);

            }// for
            Object[] cells = cellList.toArray();
            rowList.add(cells);
        }// while
        content = new Object[rowList.size()][];
        for (int i = 0; i < content.length; i++) {
            content[i] = (Object[]) rowList.get(i);
        }
        rs.close();
        st.close();
    }

    @Override
    public int getRowCount() {
        return content.length;
    }

    @Override
    public int getColumnCount() {
        if (content.length == 0) {
            return 0;
        } else {
            return content[0].length;
        }
    }

    @Override
    public Object getValueAt(int row, int col) {
        return content[row][col];
    }

    @Override
    public Class getColumnClass(int col) {
        return columnClasses[col];
    }

    @Override
    public String getColumnName(int col) {
        return columnNames[col];
    }

    @Override
    public boolean isCellEditable(int rowIndex, int colIndex) {
        if (colIndex == 1) {
            return false;
        } else {
            return true;
        }
    }
}

В конструкторе класса, или методе getTableContent() есть 3 параметра:
con типа Connection, строковый query и строковый tableName.

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

В параметр query мы передаём SQL запрос, в ответ на который хотим получить необходимые данные (напоминаю, здесь поля можно представлять используя AS, чтобы заголовки можно было сделать и на русском языке, понятными пользователю Вашей программы, либо использовать представления — VIEW). Если необходимо выбрать все поля, то можно воспользоваться запросом, «SELECT * FROM tableName«, при этом третий параметр конструктора/метода tableName также обязательно необходимо заполнять именем таблицы.

В программе мы делаем следующее:

MySQLConnect myConnect = new MySQLConnect(Host, dbName, login, pass);

DbTableModel myTableModel = new DbTableModel(myCon.getConnection(), «SELECT * FROM tableName», «tableName»);

jTable1.setModel(myTableModel);

Пришлось мне как-то разрабатывать на Java проект, который был завязан на работе с базой данных MySQL. Я нашёл в Сети класс, который удобно работает с SQLite, и переделал его для работы с MySQL, собственно сделать это было нетрудно, дополнительно в этот класс можно добавить несколько методов для удобной работы, но это уже на Ваше пожелание. Собственно, для своих задач эти методы я создавал, а Вам они будут скорее всего не пригодятся, оставлю самые общие лишь.

Добавлены некоторые методы, возвращающие массив объектов из базы данных, переделать можно по своему усмотрению.

Уточняю, этот класс работает с базой данных минуя ORM, т.е. не использует ORM.

package example.Database;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;

public class MySQLConnect {

    private Connection con = null;

    public MySQLConnect() {
        //для того, чтобы подключение можно было сделать позже
    }

    public MySQLConnect(String url, String port, String dbName, String login, String pass) {
        setConnection(url, port, dbName, login, pass);
    }

    public MySQLConnect(String url, String dbName, String login, String pass) {
        setConnection(url, "3306", dbName, login, pass);
    }

    public void setConnection(String url, String port, String dbName, String login, String pass) {
        try {
            if (port == null) {
                port = "3306"; // если порт не указан, то порт по умолчанию
            }
            Class.forName("com.mysql.jdbc.Driver");
            con = DriverManager.getConnection("jdbc:mysql://" + url + ":" + port + "/" + dbName, login, pass);
        } catch (ClassNotFoundException ex) {
            System.err.println("MySQLdb: Cannot find this db driver classes. Install com.mysql.jdbc driver!");
        } catch (SQLException e) {
            System.err.println("MySQLdb: Cannot connect to " + dbName);
        }
        if (con != null) {
            System.out.println("Connection to DB established successfully.");
        }
    }

    public Connection getConnection() {
        return con;
    }

/*	метод, выполняющий просмотр базы данных, по сути не нужный,
*	т.к возвращает лишь успешно ли выполнена операция, но для
*	примера выполнения запроса, оставлю 
*/
    public boolean executeQuery(String query) {
        try {
            Statement st = con.createStatement();
            ResultSet rs = st.executeQuery(query);
            rs.close();
            st.close();
            return true;
        } catch (SQLException e) {
            System.err.println("There are problems with the query " + query + " in method "executeQuery"");
            e.printStackTrace();
            return false;
        }
    }

    public void executeUpdate(String query) { //метод, выполняющий изменения в БД
        try {
            PreparedStatement statement = con.prepareStatement(query);
            statement.executeUpdate();
        } catch (SQLException e) {
            System.err.println("There are problems with the query " + query + " in method "executeUpdate"");
            e.printStackTrace();
        }
    }

    public Object[][] getQueryResultByParam(String query, String idColumnName, String param) {
        try {
            Statement st = con.createStatement();
            ResultSet rs = st.executeQuery(query);

            ArrayList idArrayList = new ArrayList();
            ArrayList dataArrayList = new ArrayList();

            while (rs.next()) {
                idArrayList.add(rs.getString(idColumnName));
                dataArrayList.add(rs.getString(param));
            }

            Object[][] result = new Object[2][];

            result[0] = idArrayList.toArray();
            result[1] = dataArrayList.toArray();

            rs.close();
            st.close();
            return result;
        } catch (SQLException e) {
            System.err.println("There are problems with the query " + query + " in method "getQueryResultByParam"");
            e.printStackTrace();
            return null;
        }
    }

    public Object[][] getQueryResultByParam(String query, String param) {
        return this.getQueryResultByParam(query, "id", param);
    }

    public Object[][] getParam(String tableName, String param) {
        return this.getQueryResultByParam("SELECT id, " + param + " FROM " + tableName + " WHERE deleted = '0' ORDER BY id", "id", param);
    }
}

Часто на сайтах, которые используют баннеры, можно видеть как при прокрутке страницы, где содержимое боковых панелей уже закончилось, а центральная панель ещё продолжается, реклама остаётся вверху, и никто по ней не переходит.

Ситуацию с этим поможет решить зафиксированный блок.

 

<div id=»myAd» style=»position: fixed; top: 10px; right: 2.78%; width: 170px; background: #ffffff; z-index: 1; visibility: hidden;»> 

Здесь код баннера

</div>

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

position: fixed;

как видите из кода DIV’а, этот элемент изначально скрыт. Для того чтобы при прокрутке он отобразился, необходимо добавить JavaScript:

window.onscroll = function() {

	var scrolled = window.pageYOffset || document.documentElement.scrollTop;

	if (scrolled>2850){
		document.getElementById('myAd').style.visibility = 'visible';
	}
	else{
		document.getElementById('myAd').style.visibility = 'hidden';
	}
}

В html коде страницы создаём в любом месте в пределах тега body (лишь бы не внутри любого другого контейнера),

<div id="scrollBack" onClick="scrollBack()"></div>

в пределах тегов <head></head> пишем следующий код:
var oldPos;
window.onscroll = function() {

	var scrolled = window.pageYOffset || document.documentElement.scrollTop;

	if (scrolled>0){
		document.getElementById('scrollBack').style.visibility = 'visible';
		document.getElementById('scrollBack').innerHTML = 'Up'; //здесь можно подставить например картинку со стрелкой вверх
	}
	else
	{
		document.getElementById('scrollBack').innerHTML = 'Down';// а здесь можно подставить например картинку со стрелкой ввниз
	}
}

function scrollBack(){

	if (window.pageYOffset || document.documentElement.scrollTop > 0){
		oldPos = window.pageYOffset || document.documentElement.scrollTop;
		window.scrollTo(0,0);
	}
	else{
		window.scrollTo(0,oldPos);
	}
}

а в стилях настраиваем нашу панельку с id scrollBack таким образом, чтобы она была слева, зафиксированна, и необходимой длины (я для примера использовал 100%ную высоту)

вот содержимое моего css:

#scrollBack {
			position: fixed;
			left: 1px;
			top: 0px;
			width: 80px;
			height: 100%;
			opacity: 0;
			font-family: sans-serif;
			font-weight: bold;
			font-size: 0.5em;
			color: #000088;
			background: #e0e0ff;
			border: 1px solid #fff;
			padding: 2px;}
#scrollBack:hover {opacity: 0.8;}

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

Для начала идём на сайт http://dev.mysql.com/downloads/connector/j/ и скачиваем архив с библиотекой.

Распаковываем архив, берём оттуда только файл mysql-connector-java-x.x.xx-bin.jar (где x.x.xx — версия библиотеки).

После чего есть 2 способа подключения библиотеки к проекту:

1-й способ: Заходим в свойства проекта, ищем раздел «библиотеки» — в разных средах разработки по разному, но принцип тот же, и нажимаем «добавить jar файл», где указываем путь к файлу.

2-й способ: Копируем данный .jar файл в директорию, где у Вас установлена Java/jre7/lib/ext и также через свойства проекта в разделе «библиотеки», нажимаем «добавить библиотеку», где выбираем MySQLConnector.

Thats all folks.