基于HTTPS和JSON 的客户端请求以及服务器响应

149 阅读3分钟

任务要求

pdf

特性

  • 配置sqllite数据库,并且使用JDBC连接
  • 设置JSON数据格式(任务一)

[
    
    {
        "comments": [
            {
                "comment": "add a comment",
                "id": 6,
                "sent": "2022-11-26T07:57:47.123Z"
            }
        ],
        "latitude": 66.0580507136066,
        "description": "my name is zhangxinpeng",
        "id": 6,
        "sent": "2022-11-21T12:00:00.123Z",
        "username": "zhangxinpeng",
        "longitude": 27.469414591526057
    },
    
]

  • GET 请求获取所有数据
  • POST请求 向服务器上传新的信息并存储用户信息到sqlite数据库
  • POST请求携带查询参数进行sql语句筛查后服务器返回数据
  • 添加用户注册功能HTTPS实现
  • 给Coordinates添加description
  • 添加Coordinates评论
  • 良好的代码注释
  • 进行一些功能的测试类编写(Junit)
  • 用postman 进行客户端请求测试

how to use

  1. JDBC 连接sqlite

private boolean init() throws ClassNotFoundException {
    String dbName = "databaseName";
    String database = "jdbc:sqlite:" + dbName;
    Class.forName("org.sqlite.JDBC");
    try {
        if (this.dbConnection == null) {
            int flag = -1;
            this.dbConnection = DriverManager.getConnection(database);
            String createBasicDB = "create table if not exists data (username varchar(100) NOT NULL, latitude double NOT NULL,  longitude double, sent INTEGER NOT NULL, description varchar(200) NULL ) ";
            Statement createStatement = this.dbConnection.createStatement();
            flag = createStatement.executeUpdate(createBasicDB);

            createStatement.close();
            String sqlUser = "create table if not exists user(username varchar(100) NOT NULL primary key, password char(32) NOT NULL, email varchar(100) NOT NULL)";
            Statement createUserStatement = this.dbConnection.createStatement();
            flag = createUserStatement.executeUpdate(sqlUser);
            createUserStatement.close();
            String sqlComment = "create table if not exists comment(id integer not null, comment varchar(100) not null, sent integer not null)";
            Statement createCommentStatement = this.dbConnection.createStatement();
            createCommentStatement.executeUpdate(sqlComment);
            createCommentStatement.close();
            return true;
        }
    } catch (SQLException var9) {
        System.out.println(var9);
        exchand.handleException(var9);
    } catch (Exception e) {
        // TODO: handle exception
        e.printStackTrace();
    }
    return false;
}

  1. 根据任务要求创建相关数据库操作函数
  2. 服务器进行相关配置
  • HttpContext:监听上下文,在处理请求执行链的各个阶段中,会有一个对象在各个对象之间进行传递,也即会保存请求的上下文信息,这个对象就是HttpContext对象。
  • HttpHandler:上下文对应的http请求处理器
服务器监听器的上下文,需要配置用于匹配URI的公共路径和用来处理请求的HttpHandler
(可以创建多个 HttpContext,一个 HttpContext 对应一个 HttpHandler,不同的 URI
请求,根据添加的 HttpContext 监听器,分配到对应的 HttpHandler 处理请求)

3.1因此,我们需要重写请求处理器,一个示例如下:

public class CommentHandler implements HttpHandler {
    private CoordDatabase db;
    private MyExceptionHandler exHand;

    public CommentHandler(CoordDatabase db, MyExceptionHandler exHand) {
        this.db = db;
        this.exHand = exHand;
    }

    public void handle(HttpExchange t) throws IOException {
        System.out.println("commenthandler");
        if ("POST".equals(t.getRequestMethod())) {
           /* String jsonString = this.handleResponsePOST(t);
            JSONObject obj = new JSONObject(jsonString);*/
            JSONObject obj = this.handleResponsePOST(t);
            String s_sent = obj.getString("sent");
            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSX");
            LocalDateTime d_sent = LocalDateTime.parse(s_sent, formatter);
            long l_sent = d_sent.toInstant(ZoneOffset.of("Z")).toEpochMilli();
            this.db.saveComment(obj.getInt("id"), obj.getString("comment"), l_sent);
            t.sendResponseHeaders(200, 2L);
            OutputStream outputStream = t.getResponseBody();
            outputStream.write("OK".getBytes());
            outputStream.flush();
            outputStream.close();
        } else {
            this.handleResponse(t, "Not supported");
        }

    }
/*
    private String handleResponsePOST(HttpExchange httpExchange) throws IOException {
        InputStream stream = httpExchange.getRequestBody();
        String text = (String)(new BufferedReader(new InputStreamReader(stream, StandardCharsets.UTF_8))).lines().collect(Collectors.joining("\n"));
        return text;
    }*/


    private JSONObject handleResponsePOST(HttpExchange httpExchange) throws IOException {

        InputStream stream = httpExchange.getRequestBody();
        String s = "";

        Map<String, String> map = new HashMap<>();
        BufferedReader br = new BufferedReader(new InputStreamReader(stream, StandardCharsets.UTF_8));
        while((s=br.readLine())!=null){
            if(s.contains("=")){
                String param[] = s.split("=");
                String key = param[1].replace(""", "");
                br.readLine();
                String value = br.readLine();
                map.put(key, value);


            }

        }
        String text = map.toString();
        // String text = (new BufferedReader(new InputStreamReader(stream, StandardCharsets.UTF_8))).lines().collect(Collectors.joining("\n"));
        //.lines().collect(Collectors.joining("\n"));

        return new JSONObject(map);
    }
    private void handleResponse(HttpExchange httpExchange, String requestParamValue) throws IOException {
        OutputStream outputStream = httpExchange.getResponseBody();
        StringBuilder htmlBuilder = new StringBuilder();
        htmlBuilder.append("<html>").append("<body>").append("<h1>").append("Returning payload ").append(requestParamValue).append("</h1>").append("</body>").append("</html>");
        String htmlResponse = htmlBuilder.toString();
        httpExchange.sendResponseHeaders(200, (long)htmlResponse.length());
        outputStream.write(htmlResponse.getBytes());
        outputStream.flush();
        outputStream.close();
    }
}

3.2 http实现

 HttpServerProvider provider = HttpServerProvider.provider();
 HttpServer server = provider.createHttpServer(new InetSocketAddress(8080),10);
 HttpContext coordinateContext = server.createContext("/coordinates", new CoordinateHandler(db, exchand));
 server.createContext("/registration", new RegistrationHandler(db, exchand));
 HttpContext commentContext = server.createContext("/comment", new CommentHandler(db, exchand));
 server.setExecutor((Executor)null);
 server.start();

3.3 https实现

  • http相较于http多了个创建SSL证书的过程
 com.sun.net.httpserver.HttpsServer server = com.sun.net.httpserver.HttpsServer.create(new InetSocketAddress(8080), 0);
         /*HttpHandler:上下文对应的http请求处理器*/
        HttpContext coordinateContext = server.createContext("/coordinates", new CoordinateHandler(db, exchand));

        server.createContext("/registration", new RegistrationHandler(db, exchand));

        HttpContext commentContext = server.createContext("/comment", new CommentHandler(db, exchand));

//        coordinateContext.setAuthenticator(authchecker);
//        commentContext.setAuthenticator(authchecker);


        char[] passphrase = "password".toCharArray();
        //https创建证书
        //建立证书库
        KeyStore ks = KeyStore.getInstance("JKS");
        //载入证书
        ks.load(new FileInputStream("./keystore.jks"), passphrase);
        //建立一个密钥管理工厂
        KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
        //初始工厂
        kmf.init(ks, passphrase);
        TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");
        tmf.init(ks);
        //建立证书实体
        SSLContext ssl = SSLContext.getInstance("TLS");
        //初始化证书
        ssl.init(kmf.getKeyManagers(), tmf.getTrustManagers(), (SecureRandom)null);
        //载入配置
        server.setHttpsConfigurator(new HttpsConfigurator(ssl) {
            public void configure(HttpsParameters params) {
            //获取远程地址
                InetSocketAddress remote = params.getClientAddress();
                System.out.println(remote);
                SSLContext c = this.getSSLContext();
                //取到默认参数
                SSLParameters sslparams = c.getDefaultSSLParameters();
                //验证
                params.setSSLParameters(sslparams);
            }
        });

        server.setExecutor((Executor)null);
        server.start();

4.postman 测试

image.png