写点什么

使用 AI 搭建 SpringBoot 服务

作者:X.F
  • 2024-01-08
    美国
  • 本文字数:6070 字

    阅读完需:约 20 分钟

读前提示:这是一个类似于流水帐的记录。


Java 9 引入了交互式编程界面 JShell。这一工具被寄予厚望,OpenJDK 社区希望它可以降低 Java 语言的学习门槛,我在极客时间专栏《深入剖析 Java 新特性》里也有介绍。JShell 的确降低了学习门槛,但是和 Python 相比,因为Jupyter Notebook的存在,还是有一段不小的差距。怎么进一步降低学习的门槛,也是一个我自己比较头疼的问题。


我面临的问题主要有两个。 第一个是需要搭建一个服务框架,这个服务框架可以在线执行 Java 的代码片段。第二个是找到免费的服务器资源,可以接近免费地运行这个服务。


第二个问题依然是一个问题,虽然我也找到的免费的云资源,但是资源非常有限。幸运的是,第一个问题 AI 替我解决的很大一部分。所以,早起的鸟儿,现在就可以试一试这个服务的雏形了。


AI 怎么帮到我的呢?


我使用 Google 的 BARD 和 OpenAI 的 Chat。之所以使用两个,是方便互相对照结果。我把过程分为两个部分,浏览器端的代码和服务器端的代码。 问题也是按照这两个部分分别展开下去的。


我先问 Bard:

I would like to implement a web application. In the browser side, there is an input diagram, and users can input source code here. A run button that will submit the source code to web server, and the server will response with the evaluation (compiler and running) result, and show to the users in a new diagram bellow the source code. Please implement the browser code, including html and javascript.


Bard 的回答很详细,给出了代码:

<!DOCTYPE html><html lang="en"><head>    <meta charset="UTF-8">    <meta name="viewport" content="width=device-width, initial-scale=1.0">    <title>Code Playground</title>    <style>        .diagram {            border: 1px solid #ddd;            border-radius: 5px;            padding: 10px;            margin-bottom: 10px;        }        .output {            font-family: monospace;            background-color: #eee;            padding: 10px;            border: 1px solid #ddd;            border-radius: 5px;        }    </style></head><body>    <h1>Code Playground</h1>    <div class="diagram">        <label for="code">Enter your code:</label>        <textarea id="code" rows="10" cols="40"></textarea>    </div>    <button id="run-button">Run Code</button>    <div class="output" id="output"></div>
<script src="script.js"></script></body></html>
复制代码


const codeInput = document.getElementById('code');const runButton = document.getElementById('run-button');const outputElement = document.getElementById('output');
runButton.addEventListener('click', async () => { const code = codeInput.value; // Send the code to the server through an API call try { const response = await fetch('/api/run-code', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ code }) }); const data = await response.json(); // Display the compiler and running results outputElement.innerText = data.compilerOutput + '\n' + data.runOutput; } catch (error) { outputElement.innerText = `Error: ${error.message}`; }});
复制代码


还给出了解释:

----------

Explanation:

  • The HTML defines the user interface with an input diagram for code, a run button, and an output diagram.

  • The JavaScript listens for the click event on the run button.

  • When clicked, it fetches the code from the input field and sends it to the server through a POST request to the /api/run-code endpoint.

  • The script expects the server to return a JSON object containing the compiler output and the running output.

  • Finally, the script displays both outputs in the designated output element.

Please note:

  • This is a simplified example and doesn't implement server-side code. You'll need to develop a server-side API that receives the code, compiles it, executes it, and sends back the results in the expected format.

  • This example uses asynchronous functions and the Fetch API. Make sure your browser supports these features.

  • This code doesn't perform any security checks on the user input. Implement proper validation and sanitization on the server-side to prevent code injection vulnerabilities.

Feel free to adapt and extend this code to suit your specific needs and integrate it with your own server-side implementation.

----------


到此为止,我是很满意的。接下来,我想试试服务端的情况。


我的问题是:

Thank you! Now let's design and implement the server side. The code complier and executing are implemented in Java, and the client request is forward to Java server via web APIs. I would like to use web APIs to support the interactions. The web service APIs will provide a stateful JavaScript interface to interactively evaluate declarations, statements, and expressions of programming languages. The web service APIs should support a single snippet or multiple snippets evaluation on the same session. The evaluation result of a snippet depends on the previous snippets evaluation states.For example, there are two snippets in one web page.


  1st code snippet:    String helloWorld = "Hello world"; 

 2nd code snippet:    System.out.println(helloWorld);


A user could evaluate the snippets in order as displayed, or update one or more snippets for further evaluation.


Please design and implement the WebAPIs.


Bard 的回答还是很详细,但是没有给出代码

-------------------

Here's a design and implementation outline for the server-side Web API, considering the requirements you've specified:

API Design:

  1. Endpoint: /api/run-code (POST)

  2. Request Body:code: The code snippet to be evaluated (string).sessionId: An optional identifier for maintaining state across multiple evaluations (string).

  3. Response Body:compilerOutput: Output from the compilation process (string).runOutput: Output from running the code (string).sessionId: An updated session ID to be used for subsequent evaluations (string).

Server-Side Implementation (Java):

  1. Framework: Choose a suitable Java web framework like Spring Boot for building RESTful APIs.

  2. Dependency Injection: Use a dependency injection framework (Spring has one built-in) to manage compiler and execution components.

  3. Compiler and Execution Engine:Choose a suitable Java compiler library (e.g., JavaCompiler from javax.tools).Implement a code execution engine (using Java's process API or a sandboxed environment).

  4. Session Management:Choose a session management mechanism (e.g., Spring Session, in-memory storage, or a database).Store evaluation states (variables, classes, etc.) in the session.

  5. API Controller:Create a controller class to handle incoming requests to the /api/run-code endpoint.Retrieve the code and session ID from the request body.Retrieve the evaluation state from the session (if a session ID is provided).Compile the code using the compiler library.Execute the code using the execution engine, passing the evaluation state.Capture compiler and execution output.Update the evaluation state in the session.Return a response with the compiler output, execution output, and an updated session ID.

Additional Considerations:

  • Security:Implement robust input validation and sanitization to prevent code injection attacks.Consider using a sandboxed environment for code execution to limit potential harm.

  • Error Handling:Implement proper error handling and return meaningful error messages to the client.

  • Performance:Optimize code compilation and execution for efficient response times.

  • Scalability:Consider strategies for handling multiple concurrent users and evaluations.

Remember to adapt this outline to your specific requirements and chosen frameworks.

-------------------

这个问题的答案我不是很满意,但是我看到了关键信息,“Spring Boot for building RESTful APIs”。这正是我想要的东西。 接下来的几个问题,我主要聚焦在浏览器的代码。等浏览器端的代码,我基本满意之后,就有回到了服务端的代码。


我接着问,问题里的关键词,都是上面 Bard 的回答里找出来的:

I would like to use Spring for the server-side implementation. Would you please help to implement it in Java, including session management, API controller and dependency injection? Please show me the code in details. Thanks!


这一次,Bard 的回答就有代码了,而且还有很多详细的解释。这些解释对我来说是很有价值的。但是,我还想更快,于是我就接着问 Bard 是不是能把代码整理出来:

Could you join the effects together, and complete the server-side code?


哇,这次的回答我是满意了,整个代码结构展现的很完整:


Application.java:

package com.example.codeplayground;
import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;import org.springframework.session.data.redis.config.annotation.web.http.EnableRedisHttpSession;
@SpringBootApplication@EnableRedisHttpSession // Assuming Redis for session storagepublic class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); }}
复制代码


CodeExecutionController.java:

package com.example.codeplayground.controller;
import com.example.codeplayground.model.CodeExecutionRequest;import com.example.codeplayground.model.CodeExecutionResponse;import com.example.codeplayground.service.CodeExecutionService;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.http.ResponseEntity;import org.springframework.web.bind.annotation.PostMapping;import org.springframework.web.bind.annotation.RequestBody;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpSession;
@RestController@RequestMapping("/api")public class CodeExecutionController {
@Autowired private CodeExecutionService codeExecutionService;
@PostMapping("/run-code") public ResponseEntity<CodeExecutionResponse> runCode(@RequestBody CodeExecutionRequest request, HttpSession session) { SessionData sessionData = (SessionData) session.getAttribute("sessionData"); if (sessionData == null) { sessionData = new SessionData(); }
CodeExecutionResponse response = codeExecutionService.executeCode(request, sessionData);
session.setAttribute("sessionData", sessionData); return ResponseEntity.ok(response); }}
复制代码


CodeExecutionService.java:

package com.example.codeplayground.service;
import com.example.codeplayground.model.CodeExecutionRequest;import com.example.codeplayground.model.CodeExecutionResponse;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Service;
import javax.tools.JavaCompiler; // Example for Java compilation
// ... other dependencies for code execution
@Servicepublic class CodeExecutionService {
@Autowired private JavaCompiler compiler;
// ... other dependencies
public CodeExecutionResponse executeCode(CodeExecutionRequest request, SessionData sessionData) { // Compile code (example for Java) boolean compilationSuccess = compiler.run(null, null, null, request.getCode().split("\n")); if (!compilationSuccess) { return new CodeExecutionResponse("error", "Compilation failed"); }
// Execute code (implement this based on your execution engine) // ...
// Update session data (if applicable) // ...
return new CodeExecutionResponse("success", "Code executed successfully"); }}
复制代码


SessionData.java:

package com.example.codeplayground.model;
public class SessionData { // Store evaluation states (variables, classes, etc.)}
复制代码


CodeExecutionRequest.java and CodeExecutionResponse.java:

// CodeExecutionRequest (body of incoming request)public class CodeExecutionRequest {    private String language;    private String version;    private String context;    private String code;    private String sessionId;    // ... getters and setters}
// CodeExecutionResponse (response body)public class CodeExecutionResponse { private String status; private String message; // ... getters and setters}
复制代码


虽然 AI 没有把所有的事情做完,但是也极大地加速了我的上手过程。最后,我使用的服务和代码框架,基本就是按照 Google 的 BARD 和 OpenAI 的 Chat 的给出思路和代码结构来的。


如果你想看看最后的代码,这里是浏览器端这里是服务端端,都放在了 Github 上了。 呈现成果,可以参考网站:code.ivi.co。下面是两个截图:



我自己看,觉得现在的 AI 智商还是在线的。

发布于: 刚刚阅读数: 6
用户头像

X.F

关注

因为慢,所以快。 2018-04-29 加入

制订和维护Java安全规范。

评论

发布
暂无评论
使用AI搭建SpringBoot服务_AI_X.F_InfoQ写作社区