如何从 Java 服务器读取 Java 脚本中的数据?

How to read data in JavaScript from a Java server?

我正在 运行 建立一个显示时间的简单服务器,当有人使用 telnet\putty 连接到它时,他可以看到时间。

我需要在 JavaScript 中编写一段代码,从服务器读取数据。 我该怎么做?

这是服务器代码

import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Calendar;




class ClientThread extends Thread {

   private final Socket _socket;

   public ClientThread( Socket socket ) {
      System.out.println( "New client" );
      _socket = socket;
      setDaemon( true );
      start();
   }

   @Override
   public void run() {
      try(
         final OutputStream outputFromServer = _socket.getOutputStream();
         final PrintWriter serverPrintOut = new PrintWriter(
            new OutputStreamWriter( outputFromServer, "utf-8" ), true ))
      {
         serverPrintOut.println( "Welcome to time server" );
         for(;;) {
            final long elapsed = System.currentTimeMillis() - MyServer.StartTime;
            serverPrintOut.println( elapsed );
            Thread.sleep( 1000L );
         }
      }
      catch( final InterruptedException ex) {/**/}
      catch( final IOException e ) {
         e.printStackTrace();
      }
   }
}

public class MyServer {

   static Calendar startTime = Calendar.getInstance();
   static long StartTime = System.currentTimeMillis();



   public static void main( String[] args ) throws IOException {
      try( ServerSocket serverSocket = new ServerSocket( 9991 )) {
         for(;;) {
            new ClientThread( serverSocket.accept());
         }
      }
   }
}

这就是我在 JavaScript

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
    <%--<script type="text/javascript" src="jsocket.js"></script>--%>
    <%--<script type='text/javascript'>--%>
        <%--// Host we are connecting to--%>
        <%--var host = '10.0.0.82';--%>
        <%--// Port we are connecting on--%>
        <%--var port = 9991;--%>

        <%--var socket = new JSocket();--%>

        <%--// When the socket is added the to document--%>
        <%--socket.onReady = function(){--%>
            <%--socket.connect(host, port);--%>
        <%--}--%>

        <%--// Connection attempt finished--%>
        <%--socket.onConnect = function(success, msg){--%>
            <%--if(success){--%>
                <%--// Send something to the socket--%>
                <%--socket.write('Hello world');--%>
            <%--}else{--%>
                <%--alert('Connection to the server could not be estabilished: ' + msg);--%>
            <%--}--%>
        <%--}--%>
        <%--socket.onData = function(data){--%>
            <%--alert('Received from socket: '+data);--%>
        <%--}--%>

        <%--// Setup our socket in the div with the id="socket"--%>
        <%--socket.setup('mySocket');--%>
    <%--</script>--%>
    <script src="socket.io.js"></script>
    <script>
//        var socket = io('http://10.0.0.82:9991');
//        socket.on('connect', function(){});
//        socket.on('event', function(data){});
//        socket.on('disconnect', function(){});


        var socket = io('10.0.0.82:9991');
        socket.on('news', function (data) {
            console.log(data);
            socket.emit('my other event', { my: 'data' });
        });
    </script>
</head>
<body>

</body>
</html>

但是当我 运行 JavaScript 代码时我得到错误 "Invalid http resonse" 我明白为什么(服务器不是 http) - 但我该如何克服这个问题? 什么会又快又容易- 更改 JavaScript 或使服务器成为 http ?

tl;博士

根据 1970-01-01T00:00Z 的 this Answer, here is the JavaScript for parsing a count of milliseconds since the epoch reference

var date = new Date( millisecondsSinceEpochReference );

其他建议

除了Java脚本代码,我还可以提供一些主要建议:Java Servlets,java.time classes 和 ISO 8601 格式。

Java Servlet

无需重新发明网络服务器。 Java Servlet技术的发明就是为了让这种工作变得非常简单。

编写一个简单的 servlet 应用程序,returns 您需要的字符串。只需几行代码。

import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;

@WebServlet ( "/now" )
public class NowServlet extends HttpServlet {

    public void doGet ( HttpServletRequest req , HttpServletResponse res )
        throws ServletException, IOException {

        res.setContentType( "text/plain" );
        PrintWriter out = res.getWriter();

        Instant instant = Instant.now();
        String output = instant.toString();

        out.println( output );
    }
}

然后 运行 您在任何兼容 Servlet 的服务器上的 servlet(web container) such as Apache Tomcat or Eclipse Jetty

如果你愿意,你可以制作一个 RESTful 网络服务。

java.time

您的 Java 后端正在使用可怕的旧日期时间 classes,这些日期时间多年前已被现代 java.time classes。

如果您坚持将某个时刻作为 epoch reference, here is code to get a count of milliseconds since 1970-01-01T00:00Z 的计数进行跟踪。

Instant.now().toEpochMilli() 

但我建议您交换文本而不是这个单纯的整数。继续阅读。

ISO 8601

将日期时间值作为文本交换时,请使用标准 ISO 8601 格式。这些格式实用且有用,旨在避免歧义,易于机器解析,也易于跨文化的人类阅读。

java.time classes 在 parsing/generating 字符串时默认使用这些标准格式。因此无需指定格式模式。

对于 UTC, use Instant class 中的值。

String output = Instant.now().toString() ;

2018-11-13T02:16:19.422836Z

您可以将这样的字符串解析回对象。

Instant instant = Instant.parse( "2018-11-13T02:16:19.422836Z" ) ;  

如果您的目的地限制为毫秒而不是 java.time nanoseconds 分辨率,t运行cate.

String output = 
    Instant
    .now()
    .truncatedTo( ChronoUnit.MILLIS )
    .toString() 
;

2018-11-13T02:18:05.333Z

可能想要交换特定地区人们使用的挂钟时间所见的价值(time zone). But generally speaking, the best practice is to exchange moments in UTC.

对于时区,使用ZonedDateTimeclass。此 class 上的 toString 方法通过在方括号中附加时区名称,明智地扩展了 ISO 8601 标准。

String output = 
    ZonedDateTime                          // Represent a moment as seen through the wall-clock time used by the people of a particular region (a time zone).
    .now(                                  // Capture the current moment.
        ZoneId.of( "America/Montreal" )    // Always specify proper zone name in `Continent/Region` format, never 2-4 letter pseudo-zones such as PST, EST, CEST, or IST.
    )                                      // Returns a `ZonedDateTime` object.
    .toString()                            // Generates text in ISO 8601 format extended to append the name of zone in square brackets.

2018-11-12T21:27:54.595139-05:00[America/Montreal]

您可以将这样的字符串解析回对象。

ZonedDateTime zdt = ZonedDateTime.parse( "2018-11-12T21:27:54.595139-05:00[America/Montreal]" ) ;

如果需要,运行如上所示分类。


关于java.time

java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.

Joda-Time project, now in maintenance mode, advises migration to the java.time classes.

要了解更多信息,请参阅 Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310

您可以直接与您的数据库交换 java.time 对象。使用 JDBC driver compliant with JDBC 4.2 或更高版本。不需要字符串,不需要 java.sql.* classes.

从哪里获得java.time classes?

ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval, YearWeek, YearQuarter, and more.