任务要求
特性
- 配置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
- 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;
}
- 根据任务要求创建相关数据库操作函数
- 服务器进行相关配置
- 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 测试