2016-05-14 1 views
0

У меня есть приложение, написанное на JavaFX для управления некоторыми огнями в театре с очень простым интерфейсом. В основном две кнопки, одна из которых загорается, загорается на 3 секунды, а другая - на 3 секунды. Приложение подключается к серверу Ethernet к серверу (Sealevel Sealink 4104) для управления огнями.встроенный веб-сервер Java скрывает интерфейс приложения

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

https://www.youtube.com/watch?v=G4Z2PQfOHdY

Трассы приложение, и я могу получить веб-страницу, я искал в браузере. Однако мой интерфейс приложения никогда не появляется. Идея заключается в том, что интерфейс приложения всегда присутствует, чтобы указать, что он запущен. Интерфейс веб-страницы будет доступен для расширения параметров управления на мобильном устройстве.

Главный вопрос на этом этапе - как заставить веб-сервер работать в фоновом режиме, не мешая функционированию интерфейса приложения?

код сервера веб:

package lightcontrol2; 

import java.io.BufferedReader; 
import java.io.DataOutputStream; 
import java.io.FileInputStream; 
import java.io.FileNotFoundException; 
import java.io.InputStream; 
import java.io.InputStreamReader; 
import java.io.OutputStream; 
import java.net.ServerSocket; 
import java.net.Socket; 
import java.util.StringTokenizer; 


public final class JavaWebserver { 

public final void StartServer() throws Exception { 
    // Set port number. 
    int port = 9000; 

    // Establish the listening socket. 
    ServerSocket serverSocket = new ServerSocket(port); 

    // Process HTTP sevice requests in an infinite loop. 
    while (true) { 
     // Listen for TCP connection request. 
     Socket connectionSocket = serverSocket.accept(); 

     // Construct an object to process the HTTP request message. 
     HttpRequest request = new HttpRequest(connectionSocket); 

     // Create a new thread to process the request. 
     Thread thread = new Thread(request); 

     // Start the thread. 
     thread.start(); 
    } 
} 
} 

final class HttpRequest implements Runnable { 

// Return carriage return (CR) and line feed (LF). 
final static String CRLF = "\r\n"; 
Socket socket; 

// Constructor. 
public HttpRequest(Socket socket) throws Exception { 
    this.socket = socket; 
} 

// Implement the run() method of the Runnable interface. 
// Within run(), explicitly catch and handle exceptions 
// with try/ catch block. 

@Override 
public void run() { 
    try { 
     processRequest(); 
    } catch (Exception e){ 
     System.out.println(e); 
    } 
} 

private void processRequest() throws Exception { 
    // Get a reference to the socket's input and output streams. 
    InputStream instream = socket.getInputStream(); 
    DataOutputStream os = new DataOutputStream(socket.getOutputStream()); 

    // Set up input stream filters. 
    // Page 169, 10th line down or so . . . 
    // Reads the input data. 
    BufferedReader br = new BufferedReader(new InputStreamReader(instream)); 

    // Get the request line of the HTTP request message. 
    // Get path/file.html version of http 
    String requestLine = br.readLine(); 

    // Display the request line. 
    System.out.println(); 
    System.out.println(requestLine); 

    // Deal with the request. 
    // Extract the filename from the request line. 
    // This is an input method with deliminators. 
    StringTokenizer tokens = new StringTokenizer(requestLine); 

    // Skip over the method, which should be 'GET'. 
    tokens.nextToken(); 
    String fileName = tokens.nextToken(); 

    // Root of the server. 
    String root = "/www/"; 
    fileName = root + fileName; 

    // Open the requested file. 
    FileInputStream fis = null; 
    boolean fileExists = true; 

    try { 
     fis = new FileInputStream(fileName); 
    } catch (FileNotFoundException e) { 
     fileExists = false; 
    } 

    // Construct the response message. 
    String statusLine = null; 
    String contentTypeLine = null; 
    String entityBody = null; 

    if (fileExists) { 
     statusLine = "HTTP/1.0 200 OK" + CRLF; 
     contentTypeLine = "Content-type: " + contentType(fileName) + CRLF; 
    } 
    else { 
     statusLine = "HTTP/1.0 404 Not Found" + CRLF; 
     contentTypeLine = "Content-type: " + "text/html" + CRLF; 
     entityBody = "<HTML>" + 
       "<HEAD><TITLE>Not Found</TITLE></HEAD>" + 
       "<BODY>NOt Found</BODY></HTML>"; 
    } 

    //Send the status line. 
    os.writeBytes(statusLine); 

    // Sent the content type line. 
    os.writeBytes(contentTypeLine); 

    // Send a blank line to indicate the end of the header lines. 
    os.writeBytes(CRLF); 

    // Send the entity body. 
    if (fileExists) { 
     sendBytes(fis, os); 
     os.writeBytes(statusLine); 
     fis.close(); 
    } else { 
     os.writeBytes(statusLine); 
     os.writeBytes(entityBody); 
     os.writeBytes(contentTypeLine); 
    } 

    System.out.println("*****"); 
    System.out.println(fileName); 
    System.out.println("*****"); 

    // Get and display the header lines. 
    String headerLine = null; 
    while ((headerLine = br.readLine()).length() != 0) { 
     System.out.println(headerLine); 
    } 

    // Close streams and socket. 
    os.close(); 
    br.close(); 
    socket.close(); 
}  

private static String contentType(String fileName) { 
    if (fileName.endsWith(".htm") || fileName.endsWith(".html")) { 
     return "text/html"; 
    } 
    if (fileName.endsWith(".jpg") || fileName.endsWith(".jpeg")) { 
     return "image/jpeg"; 
    } 
    if (fileName.endsWith(".gif")) { 
     return "image/gif"; 
    } 

    return "application/octet-stream"; 
} 

private static void sendBytes(FileInputStream fis, OutputStream os) throws Exception { 
    // Construct 1K buffer to hold bytes on way to the socket. 
    byte[] buffer = new byte[1024]; 
    int bytes = 0; 

    // Copy requested file into the socket's output stream. 
    // read() returns -1, indicating end of file. 
    while ((bytes = fis.read(buffer)) != -1) { 
     os.write(buffer, 0, bytes); 
    } 
} 
} 

Вот код интерфейса:

package lightcontrol2; 

import javafx.application.Application; 
import javafx.event.ActionEvent; 
import javafx.geometry.Insets; 
import javafx.geometry.Pos; 
import javafx.scene.Scene; 
import javafx.scene.control.Button; 
import javafx.scene.layout.BorderPane; 
import javafx.scene.layout.GridPane; 
import javafx.stage.Stage; 


public class LightControl2 extends Application { 

@Override 
public void start(Stage primaryStage) throws Exception { 
    GridPane grid = createGrid(); 

    SealinkConnect connect = new SealinkConnect(); 
    JavaWebserver webserver = new JavaWebserver(); 

    Button btnOn = new Button(); 
    grid.add(btnOn, 0, 1); 
    btnOn.setText("3 Sec On");   
    btnOn.setOnAction((ActionEvent event) -> { 
     System.out.println("3N:100:A"); 
     connect.sendCommand("3N:100:A"); 
    }); 

    Button btnOff = new Button(); 
    grid.add(btnOff, 0, 2); 
    btnOff.setText("3 Sec Off"); 
    btnOff.setOnAction((ActionEvent event) -> { 
     System.out.println("3F:A"); 
     connect.sendCommand("3F:A"); 
    }); 

    BorderPane root = new BorderPane(); 
    root.setPadding(new Insets(10)); 
    root.setCenter(grid); 

    Scene scene = new Scene(root, 365, 300); 

    primaryStage.setTitle("Light Control Test"); 
    primaryStage.setScene(scene); 

    scene.getStylesheets().add 
     (LightControl2.class.getResource("style.css").toExternalForm()); 

    primaryStage.show(); 

    connect.socketConnect(); 
    webserver.StartServer(); 
} 

private GridPane createGrid() { 
    GridPane grid = new GridPane(); 
    grid.setAlignment(Pos.CENTER); 
    grid.setHgap(5); 
    grid.setVgap(10); 
    grid.setPadding(new Insets(10)); 
    return grid; 
} 

/** 
* @param args the command line arguments 
*/ 
public static void main(String[] args) { 
    launch(args); 

} 

} 
+0

Как приложение, представленной на веб-странице? JNLP приходит на ум, но это будет означать, что все приложение передается с сервера клиенту, а мобильный - в этом случае, который не выглядит мне хорошим подходом. – hotzst

+0

Пользователь открывает браузер и вводит IP-адрес компьютера, на котором запущено приложение. Например, 192.168.1.16:9000/www/light control.html. – CelestialCoyote

ответ

0

Я собираюсь предположить, что JavaFX нуждается в нитку обратно. Он вызывает start(), в котором вы вызываете webserver.StartServer(), который по очереди остается в бесконечном цикле while(true). Вы должны также выполнять цикл приема сокета в отдельном потоке (и при необходимости закрывать его должным образом) и вернуть метод start.

Это, как говорится, я бы порекомендовал не пытаться реализовать псевдо-HTTP-сервер самостоятельно - это просто дополнительный код, работа и обслуживание и могут разрываться различными способами, если он не соответствует RFC. Есть много встраиваемых легких HTTP-серверов, которые вы можете использовать. Как автор JLHTTP, я думаю, что это может быть хорошим совпадением для вашего варианта использования, но есть много других на выбор.

Использование JLHTTP 2.1, вам нужно что-то вроде этого:

public void startWebServer() { 
    String dir = "."; // local folder to serve website files from 
    HTTPServer server = new HTTPServer(9000); // pick a port, any port 
    HTTPServer.VirtualHost host = server.getVirtualHost(null); // default virtual host 
    host.addContext("/", new FileContextHandler(new File(dir), "/")); // serve website files from disk directory 
    host.addContext("/api/lights", (request, response) -> { 
     Map<String, String> params = request.getParams(); 
     String action = params.get("action"); 
     if (action == null) 
      action = ""; 
     switch (action) { 
      case "on": 
       connect.sendCommand("3N:100:A"); 
       return 200; // ok 
      case "off": 
       connect.sendCommand("3F:A"); 
       return 200; // ok 
      default: 
       return 400; // bad request 
     } 
    }, "GET", "POST"); // support both GET and POST requests 
    server.start(); 
} 

Примечание:

  • файлов сайта (HTML/JS/CSS/imags и т.д.) подается с диска - в примере используется текущий каталог, но вы должны изменить его на выделенный каталог, чтобы предотвратить непреднамеренный доступ к конфиденциальным файлам.
  • Клиентский код может использовать либо запрос POST, либо GET через форму, AJAX, url с параметрами запроса и т. Д., Если он отправляет соответствующий параметр и значение действия.
  • Вы также должны правильно закрыть приложение, соединение, HTTPServer и т. Д.
  • В этом примере принят один параметр включения/выключения. Если вам нужна большая гибкость на стороне клиента, вы можете передать отдельные параметры команды/устройства/значения и создать командную строку контроллера света в обработчике контекста.
  • После все работало, вы должны рассмотреть вопрос безопасности, а также, или какой-то ребенок в аудитории начнет баловаться с шоу :-)
+0

Я добавил JLTHTTP-сервер в свое приложение и работаю. – CelestialCoyote

Смежные вопросы