SpringBoot对接Midjourney Api

提示:SpringBoot对接Midjourney Api

文章目录

目录

文章目录

后端代码

导包

controller层

工具类层

前端代码

申请API

测试结果



后端代码

导包

XML 复制代码
        <!--添加hutool的依赖-->
        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>5.8.16</version>
        </dependency>

        <!-- OkHttp -->
        <dependency>
            <groupId>com.squareup.okhttp3</groupId>
            <artifactId>okhttp</artifactId>
            <version>4.9.3</version>
        </dependency>

        <!-- Gson -->
        <dependency>
            <groupId>com.google.code.gson</groupId>
            <artifactId>gson</artifactId>
            <version>2.8.9</version>
        </dependency>

controller层

java 复制代码
    @PostMapping("/createimage")
    public Response createimage(String prompt){
        System.out.println(prompt);
        return new Response("0","success",ApiTestUtil.createImage(prompt));
    }

    @PostMapping("/fetch")
    public Response fetch(String jobId){
        String result = ApiTestUtil.fetch(jobId);
        return new Response("0","success",result);
    }

工具类层

java 复制代码
    public static String createImage(String prompt) {
        Map<String, Object> map = new HashMap<>();
        map.put("prompt", prompt);
        map.put("mode", "fast");
        map.put("hookUrl", "");
        String result = HttpRequest.post("https://api.ttapi.io/midjourney/v1/imagine")
                .body(JSONUtil.toJsonStr(map))
                .header("TT-API-KEY", "请替换你自己的key")
                .execute().body();
        System.out.println("绘图请求响应:" + result);
        return result;
    }

    public static String fetch(String jobId){
        String result = HttpRequest.get("https://api.ttapi.io/midjourney/v1/fetch?jobId=" + jobId)
                .header("TT-API-KEY", "请替换你自己的key")
                .execute().body();
        System.out.println("绘图结果:" + result);
        return result;
    }

前端代码

html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>AI Chat Interface</title>
  <!-- 引入 Vue 3 的 CDN -->
  <script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
  <!-- 引入 Font Awesome for avatars -->
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0-beta3/css/all.min.css">
  <style>
    /* 样式 */
    body {
      font-family: Avenir, Helvetica, Arial, sans-serif;
      background-color: #f4f4f9;
      margin: 0;
      padding: 0;
      display: flex;
      justify-content: center;
      align-items: center;
      height: 100vh;
    }

    .chat-container {
      display: flex;
      flex-direction: column;
      height: 80vh;
      width: 80vw;
      max-width: 600px;
      border: 1px solid #ccc;
      border-radius: 10px;
      overflow: hidden;
      background-color: #fff;
    }

    .chat-window {
      flex: 1;
      padding: 10px;
      overflow-y: auto;
      background-color: #f4f4f9;
      position: relative;
    }

    .chat-message {
      display: flex;
      margin-bottom: 10px;
      align-items: flex-start;
    }

    .message-left {
      flex-direction: row;
    }

    .message-right {
      flex-direction: row-reverse;
    }

    .avatar {
      width: 40px;
      height: 40px;
      border-radius: 50%;
      background-color: #007bff;
      display: flex;
      justify-content: center;
      align-items: center;
      color: white;
      font-weight: bold;
      margin: 0 10px;
      font-size: 20px;
    }

    .message-bubble {
      max-width: 70%;
      padding: 10px;
      border-radius: 20px;
      background-color: #007bff;
      color: white;
      word-wrap: break-word;
    }

    .message-left .message-bubble {
      background-color: #e4e6eb;
      color: black;
    }

    .chat-input {
      display: flex;
      padding: 10px;
      border-top: 1px solid #ccc;
      background-color: #fff;
    }

    .chat-input input {
      flex: 1;
      padding: 10px;
      border: 1px solid #ccc;
      border-radius: 20px;
      outline: none;
    }

    .chat-input button {
      margin-left: 10px;
      padding: 10px 20px;
      border: none;
      background-color: #007bff;
      color: white;
      border-radius: 20px;
      cursor: pointer;
      outline: none;
    }

    .chat-input button:hover {
      background-color: #0056b3;
    }

    .loading {
      position: relative;
      bottom: -20px;
      display: flex;
      align-items: center;
      justify-content: center;
    }

    /* Loader animation styles */
    .loader {
      position: relative;
      width: 2.5em;
      height: 2.5em;
      transform: rotate(165deg);
    }

    .loader:before, .loader:after {
      content: "";
      position: absolute;
      top: 50%;
      left: 50%;
      display: block;
      width: 0.5em;
      height: 0.5em;
      border-radius: 0.25em;
      transform: translate(-50%, -50%);
    }

    .loader:before {
      animation: before8 2s infinite;
    }

    .loader:after {
      animation: after6 2s infinite;
    }

    @keyframes before8 {
      0% {
        width: 0.5em;
        box-shadow: 1em -0.5em rgba(225, 20, 98, 0.75), -1em 0.5em rgba(111, 202, 220, 0.75);
      }

      35% {
        width: 2.5em;
        box-shadow: 0 -0.5em rgba(225, 20, 98, 0.75), 0 0.5em rgba(111, 202, 220, 0.75);
      }

      70% {
        width: 0.5em;
        box-shadow: -1em -0.5em rgba(225, 20, 98, 0.75), 1em 0.5em rgba(111, 202, 220, 0.75);
      }

      100% {
        box-shadow: 1em -0.5em rgba(225, 20, 98, 0.75), -1em 0.5em rgba(111, 202, 220, 0.75);
      }
    }

    @keyframes after6 {
      0% {
        height: 0.5em;
        box-shadow: 0.5em 1em rgba(61, 184, 143, 0.75), -0.5em -1em rgba(233, 169, 32, 0.75);
      }

      35% {
        height: 2.5em;
        box-shadow: 0.5em 0 rgba(61, 184, 143, 0.75), -0.5em 0 rgba(233, 169, 32, 0.75);
      }

      70% {
        height: 0.5em;
        box-shadow: 0.5em -1em rgba(61, 184, 143, 0.75), -0.5em 1em rgba(233, 169, 32, 0.75);
      }

      100% {
        box-shadow: 0.5em 1em rgba(61, 184, 143, 0.75), -0.5em -1em rgba(233, 169, 32, 0.75);
      }
    }
  </style>
</head>
<body>
  <div id="app">
    <div class="chat-container">
      <div class="chat-window">
        <div v-for="(message, index) in messages" :key="index" class="chat-message" :class="{'message-left': message.isUser, 'message-right': !message.isUser}">
          <div class="avatar">
            <i :class="message.isUser ? 'fas fa-user' : 'fas fa-robot'"></i>
          </div>
          <div class="message-bubble">
            <img :src="imageUrl" alt="" style="width: 400px;height: 400px;">
          </div>
        </div>
        <div class="loading" v-if="loading">
          <div style="display: flex; align-items: center; justify-content: center;">
            <div class="loader"></div>
            <div style="margin-left: 10px; font-weight: bold; color: #e64c87;">加载中</div>
          </div>
        </div>
      </div>
      <div class="chat-input">
        <input v-model="userInput" @keydown.enter="sendMessage" placeholder="Type your question..." />
        <button @click="sendMessage">Send</button>
      </div>
    </div>
  </div>
  
  <script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
  <script>
    const { createApp } = Vue;

    createApp({
      data() {
        return {
          userInput: '我需要你给我画一只猫',
          messages: [
          ],
          loading: false,
          jobId:"",
          imageUrl:""
        };
      },
      methods: {
        sendMessage() {
          if (this.userInput.trim()) {
            // 添加用户的消息
            this.messages.push({ text: this.userInput, isUser: true });

            // 模拟AI回复
            this.simulateAIResponse(this.userInput);

            // 清空输入框
            this.userInput = '';
          }
        },
        
        async simulateAIResponse(userText) {
          this.loading = true;
          try {
            const res = await axios.post("http://localhost:8888/createimage", {
              "prompt": this.userInput
            }, { headers: { "Content-Type": "multipart/form-data" } });
            if(res.data.code == 0){
                this.jobId = JSON.parse(res.data.data).data.jobId;
                const result = await axios.post("http://localhost:8888/fetch",{
                    "jobId": this.jobId
            }, { headers: { "Content-Type": "multipart/form-data" } 
                });
                if(result.data.code == 0){
                   this.imageUrl = JSON.parse(result.data.data).data.discordImage
                   this.loading = false;
                }
            }
          } catch (error) {
            console.error("Error fetching AI response:", error);
          }
        },
      },
    }).mount('#app');
  </script>
</body>
</html>

申请API

https://ttapi.io/recharge

测试结果

这个主要对接了前一篇AI对话的博客,有需要自行去查找

参考博客地址:https://zhuanlan.zhihu.com/p/689296056

今日时间2024年8月29日,希望你天天开心,如有不会,请留言

相关推荐
方圆想当图灵10 分钟前
缓存之美:万文详解 Caffeine 实现原理(下)
java·redis·缓存
栗豆包25 分钟前
w175基于springboot的图书管理系统的设计与实现
java·spring boot·后端·spring·tomcat
等一场春雨1 小时前
Java设计模式 十四 行为型模式 (Behavioral Patterns)
java·开发语言·设计模式
萧若岚1 小时前
Elixir语言的Web开发
开发语言·后端·golang
Channing Lewis1 小时前
flask实现重启后需要重新输入用户名而避免浏览器使用之前已经记录的用户名
后端·python·flask
Channing Lewis2 小时前
如何在 Flask 中实现用户认证?
后端·python·flask
酱学编程2 小时前
java中的单元测试的使用以及原理
java·单元测试·log4j
我的运维人生2 小时前
Java并发编程深度解析:从理论到实践
java·开发语言·python·运维开发·技术共享
一只爱吃“兔子”的“胡萝卜”2 小时前
2.Spring-AOP
java·后端·spring
HappyAcmen2 小时前
Java中List集合的面试试题及答案解析
java·面试·list