基于Swing和科大讯飞星火大模型开发的可视化聊天界面

最近很荣幸的申请到了科大讯飞星火大模型的内测资格(已经开放网页版可以直接用,类似于chatgpt那种),给了我400w的免费token,有效期一年,其中1.5版本和2.0版本各200w,于是自己想着基于星火大模型写一个简单的聊天界面,刚开始是基于springboot搭建的一个网页版的,但是页面布局啥的太难看,调了好长时间也就那样,最后就想到了还是用swing来做算了,废话不多说,上干货

首先第一步,要先去科大讯飞官网申请内测资格,通过了之后,会生成唯一的appId之类的东西,这个做开发的应该都知道,一般接入第三方开放平台,都是这种玩法,具体怎么申请,我就不说了,官网连接:讯飞开放平台-以语音交互为核心的人工智能开放平台

第二部就是用java的swing写一个简单的聊天界面,下面是最终的效果(很丑,勿喷):

下面直接上代码:

首先是聊天界面:

package com.tianjun.chat;

import com.google.gson.Gson;
import org.java_websocket.client.WebSocketClient;
import org.java_websocket.handshake.ServerHandshake;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.net.URI;
import java.util.List;
import java.util.concurrent.TimeUnit;

public class ChatBox extends JFrame {

    public static final Gson gson = new Gson();

    private static int mode_gen = 1;

    private JTextArea chatArea;
    private JTextField messageField;
    private WebSocketClient client;

    public ChatBox() {
        setTitle("科大讯飞星火大模型");
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setSize(1200, 900);

        chatArea = new JTextArea();
        chatArea.setLineWrap(true); // 自动换行
        chatArea.setWrapStyleWord(true); // 按单词边界换行
        chatArea.setEditable(false);
        chatArea.setMargin(new Insets(10, 10, 10, 10)); // 设置边距,使文本不贴边
        chatArea.setBackground(Color.WHITE); // 设置背景色,使文本区域更清晰可见
        chatArea.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5)); // 设置边框,使文本区域更美观
        JScrollPane scrollPane = new JScrollPane(chatArea);

        messageField = new JTextField();
        messageField.setPreferredSize(new Dimension(300, 50));
        messageField.addKeyListener(new KeyAdapter() {
            @Override
            public void keyPressed(KeyEvent e) {
                if (e.getKeyCode() == KeyEvent.VK_ENTER) {
                    doConnectAndSendMessage();
                }
            }
        });
        JButton sendButton = new JButton("Send");
        sendButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                doConnectAndSendMessage();
            }
        });
        Container container = getContentPane();
        container.setLayout(new BorderLayout());
        container.add(scrollPane, BorderLayout.CENTER);
        container.add(messageField, BorderLayout.SOUTH);
        container.add(sendButton, BorderLayout.EAST);
        setExtendedState(JFrame.MAXIMIZED_BOTH); // 最大化窗口
        setResizable(true); // 禁止调整窗口大小
        chatArea.setFont(new Font("微软雅黑", Font.PLAIN, 20));
        messageField.setFont(new Font("微软雅黑", Font.PLAIN, 20));
        chatArea.getDocument().putProperty("charset", "GBK");// 指定字符编码为 UTF-8
        messageField.getDocument().putProperty("charset", "GBK"); // 指定字符编码为 UTF-8
    }

    public void doConnectAndSendMessage() {
        mode_gen++;
        chatArea.setText("");
        String message = messageField.getText();
        if (!message.isEmpty()) {
            try {
                client = getClient();
                String myQuestion = mode_gen % 2 == 0 ? BigModelNewV2.getQuestion(message) : BigModelNewV1.getQuestion(message);
                client.send(myQuestion);
                messageField.setText("");
            } catch (Exception ex) {
                ex.printStackTrace();
            }
        }
    }

    private WebSocketClient getClient() throws Exception {
        String url = mode_gen % 2 == 0 ? BigModelNewV2.getAuthUrl().toString().replace("http://", "ws://").replace("https://", "wss://")
                : BigModelNewV1.getAuthUrl().toString().replace("http://", "ws://").replace("https://", "wss://");
        URI serverUri = new URI(url);
        WebSocketClient client = new WebSocketClient(serverUri) {
            @Override
            public void onOpen(ServerHandshake handshakedata) {
                String modelGen = mode_gen % 2 == 0 ? "第二代模型" : "第一代模型";
                chatArea.append(modelGen + "\n" + messageField.getText() + "\n");
            }

            @Override
            public void onMessage(String message) {
                ChatBox.JsonParse myJsonParse = gson.fromJson(message, ChatBox.JsonParse.class);
                if (myJsonParse.header.code != 0) {
                    System.out.println("发生错误,错误码为:" + myJsonParse.header.code);
                    System.out.println("本次请求的sid为:" + myJsonParse.header.sid);
                }
                List<Text> textList = myJsonParse.payload.choices.text;
                for (ChatBox.Text temp : textList) {
                    System.out.print(temp.content);
                    chatArea.append(temp.content);
                }
            }

            @Override
            public void onClose(int code, String reason, boolean remote) {
                chatArea.append("\nConnection closed\n");
            }

            @Override
            public void onError(Exception ex) {
                chatArea.append("Error: " + ex.getMessage() + "\n");
            }
        };
        client.connect();
        while (true) {
            TimeUnit.MILLISECONDS.sleep(100);
            if (client.isOpen()) {
                break;
            }
        }
        return client;
    }

    public void start() throws Exception {
        getClient();
        setVisible(true);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                ChatBox chatBox = new ChatBox();
                try {
                    chatBox.start();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }

    class JsonParse {
        Header header;
        Payload payload;
    }

    class Header {
        int code;
        int status;
        String sid;
    }

    class Payload {
        Choices choices;
    }

    class Choices {
        List<Text> text;
    }

    class Text {
        String role;
        String content;
    }
}

这个类的主要作用就是构建聊天界面,发送消息和接收回显消息,接下来的两个类,一个是对应1.5版本的大模型,一个是对应2.0版本的大模型,这两个类的代码在讯飞官网样例可以直接下载,就是要里面的几个关键的appid和key替换为自己的就可以

package com.tianjun.chat;

import com.google.gson.Gson;
import okhttp3.*;
import org.apache.commons.lang3.StringUtils;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.io.IOException;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.TimeUnit;

public class BigModelNewV1 extends WebSocketListener {
    // 地址与鉴权信息
    public static final String hostUrl = "https://spark-api.xf-yun.com/v1.1/chat";
    public static final String appid = "";
    public static final String apiSecret = "";
    public static final String apiKey = "";

    // 环境治理的重要性  环保  人口老龄化  我爱我的祖国

    public static final Gson gson = new Gson();

    // 个性化参数
    private String userId;
    private Boolean wsCloseFlag;

    private static String requestJson = "{\n" +
            "  \"header\": {\n" +
            "    \"app_id\": \"" + appid + "\",\n" +
            "    \"uid\": \"" + UUID.randomUUID().toString().substring(0, 10) + "\"\n" +
            "  },\n" +
            "  \"parameter\": {\n" +
            "    \"chat\": {\n" +
            "      \"domain\": \"general\",\n" +
            "      \"temperature\": 0.5,\n" +
            "      \"max_tokens\": 1024\n" +
            "    }\n" +
            "  },\n" +
            "  \"payload\": {\n" +
            "    \"message\": {\n" +
            "      \"text\": [\n" +
            "        {\n" +
            "          \"role\": \"user\",\n" +
            "          \"content\": \"" + "${myQuestion}" + "\"\n" +
            "        }\n" +
            "      ]\n" +
            "    }\n" +
            "  }\n" +
            "}";

    public static String getQuestion(String myQuestion) {
        String question = requestJson.replace("${myQuestion}", myQuestion);
        System.err.println(question);
        return question;
    }

    // 构造函数
    public BigModelNewV1(String userId, Boolean wsCloseFlag) {
        this.userId = userId;
        this.wsCloseFlag = wsCloseFlag;
    }

    // 主函数
    public static void main(String[] args) throws Exception {
        Scanner reader = new Scanner(System.in);
        while (true) {
            String line = null;
            try {
                line = reader.nextLine();
            } catch (Exception e) {
                e.printStackTrace();
            }
            if (StringUtils.isBlank(line)) {
                continue;
            }
            WebSocket webSocket = webSocket();
            String myQuestion = getQuestion(line);
            System.err.println(webSocket.send(myQuestion));
            webSocket.close(1000, "");
            TimeUnit.SECONDS.sleep(2);
        }
    }

    public static String getAuthUrl() throws Exception {
        return getAuthUrl(hostUrl, apiKey, apiSecret);
    }

    public static WebSocket webSocket() throws Exception {
        // 构建鉴权url
        String authUrl = getAuthUrl(hostUrl, apiKey, apiSecret);
        OkHttpClient client = new OkHttpClient();
        String url = authUrl.toString().replace("http://", "ws://").replace("https://", "wss://");
        Request request = new Request.Builder().url(url).build();
        // 个性化参数入口,如果是并发使用,可以在这里模拟
        WebSocket webSocket = client.newWebSocket(request, new BigModelNewV1(1 + "",
                false));
        return webSocket;
    }


    @Override
    public void onOpen(WebSocket webSocket, Response response) {
        super.onOpen(webSocket, response);
    }

    @Override
    public void onMessage(WebSocket webSocket, String text) {
//         System.out.println(userId + "用来区分那个用户的结果" + text);
        JsonParse myJsonParse = gson.fromJson(text, JsonParse.class);
        if (myJsonParse.header.code != 0) {
            System.out.println("发生错误,错误码为:" + myJsonParse.header.code);
            System.out.println("本次请求的sid为:" + myJsonParse.header.sid);
            webSocket.close(1000, "");
        }
        List<Text> textList = myJsonParse.payload.choices.text;
        for (Text temp : textList) {
            System.out.print(temp.content);
        }
        if (myJsonParse.header.status == 2) {
            // 可以关闭连接,释放资源
            wsCloseFlag = true;
        }
    }

    @Override
    public void onFailure(WebSocket webSocket, Throwable t, Response response) {
        super.onFailure(webSocket, t, response);
        try {
            if (null != response) {
                int code = response.code();
                System.out.println("onFailure code:" + code);
                System.out.println("onFailure body:" + response.body().string());
                if (101 != code) {
                    System.out.println("connection failed");
                    System.exit(0);
                }
            }
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }


    // 鉴权方法
    public static String getAuthUrl(String hostUrl, String apiKey, String apiSecret) throws Exception {
        URL url = new URL(hostUrl);
        // 时间
        SimpleDateFormat format = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss z", Locale.US);
        format.setTimeZone(TimeZone.getTimeZone("GMT"));
        String date = format.format(new Date());
        // 拼接
        String preStr = "host: " + url.getHost() + "\n" +
                "date: " + date + "\n" +
                "GET " + url.getPath() + " HTTP/1.1";
        // System.err.println(preStr);
        // SHA256加密
        Mac mac = Mac.getInstance("hmacsha256");
        SecretKeySpec spec = new SecretKeySpec(apiSecret.getBytes(StandardCharsets.UTF_8), "hmacsha256");
        mac.init(spec);

        byte[] hexDigits = mac.doFinal(preStr.getBytes(StandardCharsets.UTF_8));
        // Base64加密
        String sha = Base64.getEncoder().encodeToString(hexDigits);
        // System.err.println(sha);
        // 拼接
        String authorization = String.format("api_key=\"%s\", algorithm=\"%s\", headers=\"%s\", signature=\"%s\"", apiKey, "hmac-sha256", "host date request-line", sha);
        // 拼接地址
        HttpUrl httpUrl = Objects.requireNonNull(HttpUrl.parse("https://" + url.getHost() + url.getPath())).newBuilder().//
                addQueryParameter("authorization", Base64.getEncoder().encodeToString(authorization.getBytes(StandardCharsets.UTF_8))).//
                addQueryParameter("date", date).//
                addQueryParameter("host", url.getHost()).//
                build();

        // System.err.println(httpUrl.toString());
        return httpUrl.toString();
    }

    //返回的json结果拆解
    class JsonParse {
        Header header;
        Payload payload;
    }

    class Header {
        int code;
        int status;
        String sid;
    }

    class Payload {
        Choices choices;
    }

    class Choices {
        List<Text> text;
    }

    class Text {
        String role;
        String content;
    }
}
package com.tianjun.chat;

import com.google.gson.Gson;
import okhttp3.*;
import org.apache.commons.lang3.StringUtils;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.io.IOException;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.TimeUnit;

public class BigModelNewV2 extends WebSocketListener {
    // 地址与鉴权信息
    public static final String hostUrl = "https://spark-api.xf-yun.com/v2.1/chat";
    public static final String appid = "";
    public static final String apiSecret = "";
    public static final String apiKey = "";

    // 环境治理的重要性  环保  人口老龄化  我爱我的祖国

    public static final Gson gson = new Gson();

    // 个性化参数
    private String userId;
    private Boolean wsCloseFlag;

    private static String requestJson = "{\n" +
            "  \"header\": {\n" +
            "    \"app_id\": \"" + appid + "\",\n" +
            "    \"uid\": \"" + UUID.randomUUID().toString().substring(0, 10) + "\"\n" +
            "  },\n" +
            "  \"parameter\": {\n" +
            "    \"chat\": {\n" +
            "      \"domain\": \"generalv2\",\n" +
            "      \"temperature\": 0.5,\n" +
            "      \"max_tokens\": 1024\n" +
            "    }\n" +
            "  },\n" +
            "  \"payload\": {\n" +
            "    \"message\": {\n" +
            "      \"text\": [\n" +
            "        {\n" +
            "          \"role\": \"user\",\n" +
            "          \"content\": \"" + "${myQuestion}" + "\"\n" +
            "        }\n" +
            "      ]\n" +
            "    }\n" +
            "  }\n" +
            "}";

    public static String getQuestion(String myQuestion) {
        String question = requestJson.replace("${myQuestion}", myQuestion);
        System.err.println(question);
        return question;
    }

    // 构造函数
    public BigModelNewV2(String userId, Boolean wsCloseFlag) {
        this.userId = userId;
        this.wsCloseFlag = wsCloseFlag;
    }

    // 主函数
    public static void main(String[] args) throws Exception {
        Scanner reader = new Scanner(System.in);
        while (true) {
            String line = null;
            try {
                line = reader.nextLine();
            } catch (Exception e) {
                e.printStackTrace();
            }
            if (StringUtils.isBlank(line)) {
                continue;
            }
            WebSocket webSocket = webSocket();
            String myQuestion = getQuestion(line);
            System.err.println(webSocket.send(myQuestion));
            webSocket.close(1000, "");
            TimeUnit.SECONDS.sleep(2);
        }
    }

    public static String getAuthUrl() throws Exception {
        return getAuthUrl(hostUrl, apiKey, apiSecret);
    }

    public static WebSocket webSocket() throws Exception {
        // 构建鉴权url
        String authUrl = getAuthUrl(hostUrl, apiKey, apiSecret);
        OkHttpClient client = new OkHttpClient();
        String url = authUrl.toString().replace("http://", "ws://").replace("https://", "wss://");
        Request request = new Request.Builder().url(url).build();
        // 个性化参数入口,如果是并发使用,可以在这里模拟
        WebSocket webSocket = client.newWebSocket(request, new BigModelNewV2(1 + "",
                false));
        return webSocket;
    }


    public static void send(WebSocket webSocket) {
        try {
            // 等待服务端返回完毕后关闭
            Scanner reader = new Scanner(System.in);
            while (true) {
                String line = null;
                try {
                    line = reader.nextLine();
                } catch (Exception e) {
                    e.printStackTrace();
                }
                // 发送一行数据,并加上回车换行符
                // 将String类型的消息转换为ByteBuf类型的消息
                String myQuestion = getQuestion(line);
                System.err.println(webSocket.send(myQuestion));
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public void onOpen(WebSocket webSocket, Response response) {
        super.onOpen(webSocket, response);
    }

    @Override
    public void onMessage(WebSocket webSocket, String text) {
//         System.out.println(userId + "用来区分那个用户的结果" + text);
        JsonParse myJsonParse = gson.fromJson(text, JsonParse.class);
        if (myJsonParse.header.code != 0) {
            System.out.println("发生错误,错误码为:" + myJsonParse.header.code);
            System.out.println("本次请求的sid为:" + myJsonParse.header.sid);
            webSocket.close(1000, "");
        }
        List<Text> textList = myJsonParse.payload.choices.text;
        for (Text temp : textList) {
            System.out.print(temp.content);
        }
        if (myJsonParse.header.status == 2) {
            // 可以关闭连接,释放资源
            wsCloseFlag = true;
        }
    }

    @Override
    public void onFailure(WebSocket webSocket, Throwable t, Response response) {
        super.onFailure(webSocket, t, response);
        try {
            if (null != response) {
                int code = response.code();
                System.out.println("onFailure code:" + code);
                System.out.println("onFailure body:" + response.body().string());
                if (101 != code) {
                    System.out.println("connection failed");
                    System.exit(0);
                }
            }
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }


    // 鉴权方法
    public static String getAuthUrl(String hostUrl, String apiKey, String apiSecret) throws Exception {
        URL url = new URL(hostUrl);
        // 时间
        SimpleDateFormat format = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss z", Locale.US);
        format.setTimeZone(TimeZone.getTimeZone("GMT"));
        String date = format.format(new Date());
        // 拼接
        String preStr = "host: " + url.getHost() + "\n" +
                "date: " + date + "\n" +
                "GET " + url.getPath() + " HTTP/1.1";
        // System.err.println(preStr);
        // SHA256加密
        Mac mac = Mac.getInstance("hmacsha256");
        SecretKeySpec spec = new SecretKeySpec(apiSecret.getBytes(StandardCharsets.UTF_8), "hmacsha256");
        mac.init(spec);

        byte[] hexDigits = mac.doFinal(preStr.getBytes(StandardCharsets.UTF_8));
        // Base64加密
        String sha = Base64.getEncoder().encodeToString(hexDigits);
        // System.err.println(sha);
        // 拼接
        String authorization = String.format("api_key=\"%s\", algorithm=\"%s\", headers=\"%s\", signature=\"%s\"", apiKey, "hmac-sha256", "host date request-line", sha);
        // 拼接地址
        HttpUrl httpUrl = Objects.requireNonNull(HttpUrl.parse("https://" + url.getHost() + url.getPath())).newBuilder().//
                addQueryParameter("authorization", Base64.getEncoder().encodeToString(authorization.getBytes(StandardCharsets.UTF_8))).//
                addQueryParameter("date", date).//
                addQueryParameter("host", url.getHost()).//
                build();

        // System.err.println(httpUrl.toString());
        return httpUrl.toString();
    }

    //返回的json结果拆解
    class JsonParse {
        Header header;
        Payload payload;
    }

    class Header {
        int code;
        int status;
        String sid;
    }

    class Payload {
        Choices choices;
    }

    class Choices {
        List<Text> text;
    }

    class Text {
        String role;
        String content;
    }
}

ps:星火大模型是通过websocket接入的,但是每次发送一个问题之后服务端就会主动断开连接,所以每次发送问题的时候都需要重新建立连接,这个可能是考虑到服务端的压力才这么做的吧,官网下载下来的样例代码,pom依赖是有问题的,然后注意一下发送请求的时候1.5和2.0的请求参数部分domain的值不要搞错了,这个在官网也有说明,2.0的值是generalv2

,这个是我改过之后的pom文件(主要看依赖部分):

<?xml version="1.0" encoding="UTF-8"?>

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.tianjun.chat</groupId>
    <artifactId>chat</artifactId>
    <version>1.0-SNAPSHOT</version>

    <name>chat</name>
    <!-- FIXME change it to the project's website -->
    <url>http://www.example.com</url>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.67</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/com.google.code.gson/gson -->
        <dependency>
            <groupId>com.google.code.gson</groupId>
            <artifactId>gson</artifactId>
            <version>2.8.5</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.java-websocket/Java-WebSocket -->
        <dependency>
            <groupId>org.java-websocket</groupId>
            <artifactId>Java-WebSocket</artifactId>
            <version>1.3.8</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/com.squareup.okhttp3/okhttp -->
        <dependency>
            <groupId>com.squareup.okhttp3</groupId>
            <artifactId>okhttp</artifactId>
            <version>4.9.1</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/com.squareup.okio/okio -->
        <dependency>
            <groupId>com.squareup.okio</groupId>
            <artifactId>okio</artifactId>
            <version>2.10.0</version>
        </dependency>

        <dependency>
            <groupId>io.netty</groupId>
            <artifactId>netty-all</artifactId>
            <version>4.1.42.Final</version>
        </dependency>

        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-lang3</artifactId>
            <version>3.12.0</version>
        </dependency>

        <dependency>
            <groupId>org.asynchttpclient</groupId>
            <artifactId>async-http-client</artifactId>
            <version>2.12.3</version>
        </dependency>

        <dependency>
            <groupId>org.java-websocket</groupId>
            <artifactId>Java-WebSocket</artifactId>
            <version>1.5.3</version>
        </dependency>
    </dependencies>

    <build>
        <pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->
            <plugins>
                <!-- clean lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#clean_Lifecycle -->
                <plugin>
                    <artifactId>maven-clean-plugin</artifactId>
                    <version>3.1.0</version>
                </plugin>
                <!-- default lifecycle, jar packaging: see https://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_jar_packaging -->
                <plugin>
                    <artifactId>maven-resources-plugin</artifactId>
                    <version>3.0.2</version>
                </plugin>
                <plugin>
                    <artifactId>maven-compiler-plugin</artifactId>
                    <version>3.8.0</version>
                </plugin>
                <plugin>
                    <artifactId>maven-surefire-plugin</artifactId>
                    <version>2.22.1</version>
                </plugin>
                <plugin>
                    <artifactId>maven-jar-plugin</artifactId>
                    <version>3.0.2</version>
                </plugin>
                <plugin>
                    <artifactId>maven-install-plugin</artifactId>
                    <version>2.5.2</version>
                </plugin>
                <plugin>
                    <artifactId>maven-deploy-plugin</artifactId>
                    <version>2.8.2</version>
                </plugin>
                <!-- site lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#site_Lifecycle -->
                <plugin>
                    <artifactId>maven-site-plugin</artifactId>
                    <version>3.7.1</version>
                </plugin>
                <plugin>
                    <artifactId>maven-project-info-reports-plugin</artifactId>
                    <version>3.0.0</version>
                </plugin>
            </plugins>
        </pluginManagement>
        <plugins>
            <plugin>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.8.0</version>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-shade-plugin</artifactId>
                <version>3.2.1</version>
                <configuration>
                    <createDependencyReducedPom>false</createDependencyReducedPom>
                    <transformers>
                        <transformer
                                implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
                            <mainClass>com.tianjun.chat.ChatBox</mainClass> <!-- 修改为你的主类 -->
                        </transformer>
                    </transformers>
                </configuration>
                <executions>
                    <execution>
                        <phase>package</phase>
                        <goals>
                            <goal>shade</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-jar-plugin</artifactId>
                <version>3.2.0</version>  <!-- 可以根据实际需要选择合适的版本 -->
                <configuration>
                    <archive>
                        <manifest>
                            <addClasspath>true</addClasspath>
                            <classpathPrefix>lib/</classpathPrefix>
                            <mainClass>com.tianjun.chat.ChatBox</mainClass>  <!-- 将MainClass替换为你的主类名 -->
                        </manifest>
                    </archive>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

猜你喜欢

转载自blog.csdn.net/qq_17805707/article/details/133034307