一、纯 Java 分层架构(IDEA 社区版普通 Java 项目,不用 Maven / 框架)

普通 Java 项目(lib 手动放 jar 包、src 源码目录),单文件写接口后期业务会完全乱掉。标准四层架构目录,拆分数据库工具、实体、DAO、Service、HTTP 路由服务,支持无限扩展接口、多表业务。

最终 src 目录结构

src
├── com
│   ├── config          # 配置类:数据库常量、跨域、服务端口
│   │   └── DBConfig.java
│   ├── util            # 工具类:数据库连接工具、JSON工具、响应封装工具
│   │   ├── DBUtil.java
│   │   ├── JsonUtil.java
│   │   └── HttpRespUtil.java
│   ├── entity          # 实体层:数据库表映射实体User
│   │   └── User.java
│   ├── dao             # 数据访问层:单独写每张表的SQL查询
│   │   └── UserDao.java
│   ├── service         # 业务层:处理业务逻辑,调用DAO
│   │   └── UserService.java
│   ├── server          # HTTP服务核心:路由分发、统一处理器、程序入口
│   │   ├── ApiServerMain.java   # 程序启动主类(替代原来TableApiServer)
│   │   ├── BaseHandler.java     # 基础统一处理器(封装跨域、统一返回格式)
│   │   └── UserHandler.java     # 用户模块专属接口处理器
└── 你原有旧文件(DBTest、HelloWorld等可保留或删除)

二、分层完整代码(按包顺序复制创建)

1. 配置包 com.config.DBConfig

统一管理数据库地址、账号、服务端口,不用到处改常量

package com.config;

public class DBConfig {
    // 数据库配置
    public static final String DB_URL = "jdbc:mysql://localhost:3306/demo_db?useSSL=false&serverTimezone=Asia/Shanghai";
    public static final String DB_USER = "root";
    public static final String DB_PWD = "你的数据库密码";
    // HTTP服务端口
    public static final int SERVER_PORT = 8090;
}

2. 工具包

2.1 com.util.DBUtil 数据库工具(全局获取连接、关闭资源,消除重复代码)
package com.util;

import com.config.DBConfig;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

public class DBUtil {
    // 获取数据库连接
    public static Connection getConn() {
        Connection conn = null;
        try {
            Class.forName("com.mysql.cj.jdbc.Driver");
            conn = DriverManager.getConnection(DBConfig.DB_URL, DBConfig.DB_USER, DBConfig.DB_PWD);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return conn;
    }

    // 统一关闭资源
    public static void close(Connection conn, PreparedStatement pstmt, ResultSet rs) {
        try {
            if (rs != null) rs.close();
            if (pstmt != null) pstmt.close();
            if (conn != null) conn.close();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
    // 无ResultSet重载(增删改使用)
    public static void close(Connection conn, PreparedStatement pstmt) {
        close(conn, pstmt, null);
    }
}
2.2 com.util.JsonUtil JSON 序列化工具(封装 FastJSON)
package com.util;
import com.alibaba.fastjson.JSON;

public class JsonUtil {
    // 对象转JSON字符串
    public static String toJson(Object obj) {
        return JSON.toJSONString(obj);
    }
}
2.3 com.util.HttpRespUtil HTTP 响应工具(统一返回 JSON 格式、封装跨域头)

前端接收统一格式:{code:200,msg:"成功",data:[列表数据]},规范接口返回

package com.util;

import com.sun.net.httpserver.HttpExchange;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.charset.StandardCharsets;
import java.util.List;

public class HttpRespUtil {
    // 设置全局跨域请求头
    public static void setCorsHeader(HttpExchange exchange) {
        exchange.getResponseHeaders().put("Access-Control-Allow-Origin", List.of("*"));
        exchange.getResponseHeaders().put("Access-Control-Allow-Methods", List.of("GET,POST,OPTIONS"));
        exchange.getResponseHeaders().put("Content-Type", List.of("application/json;charset=utf-8"));
    }

    // 统一输出JSON响应
    public static void sendJson(HttpExchange exchange, int code, String jsonStr) throws IOException {
        setCorsHeader(exchange);
        byte[] bytes = jsonStr.getBytes(StandardCharsets.UTF_8);
        exchange.sendResponseHeaders(code, bytes.length);
        try (OutputStream os = exchange.getResponseBody()) {
            os.write(bytes);
            os.flush();
        }
    }

    // 快捷成功返回
    public static void success(HttpExchange exchange, Object data) throws IOException {
        ResultVO vo = new ResultVO(200, "操作成功", data);
        sendJson(exchange, 200, JsonUtil.toJson(vo));
    }

    // 快捷失败返回
    public static void fail(HttpExchange exchange, String msg) throws IOException {
        ResultVO vo = new ResultVO(500, msg, null);
        sendJson(exchange, 200, JsonUtil.toJson(vo));
    }

    // 统一返回实体类
    public static class ResultVO {
        private Integer code;
        private String msg;
        private Object data;
        public ResultVO(Integer code, String msg, Object data) {
            this.code = code;
            this.msg = msg;
            this.data = data;
        }
        // getter/setter FastJSON序列化需要
        public Integer getCode() { return code; }
        public void setCode(Integer code) { this.code = code; }
        public String getMsg() { return msg; }
        public void setMsg(String msg) { this.msg = msg; }
        public Object getData() { return data; }
        public void setData(Object data) { this.data = data; }
    }
}

3. 实体层 com.entity.User 对应 user 数据库表

替代原来 HashMap 手动 put 字段,面向对象开发,后续扩展字段只改实体

package com.entity;

public class User {
    private Integer id;
    private String username;
    private Integer age;

    // 无参构造
    public User() {}
    // 全参构造
    public User(Integer id, String username, Integer age) {
        this.id = id;
        this.username = username;
        this.age = age;
    }

    // getter setter
    public Integer getId() { return id; }
    public void setId(Integer id) { this.id = id; }
    public String getUsername() { return username; }
    public void setUsername(String username) { this.username = username; }
    public Integer getAge() { return age; }
    public void setAge(Integer age) { this.age = age; }
}

4. DAO 层 com.dao.UserDao 纯数据库操作(只写 SQL,无业务逻辑)

package com.dao;

import com.entity.User;
import com.util.DBUtil;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.List;

public class UserDao {
    // 查询全部用户
    public List<User> findAll() {
        List<User> userList = new ArrayList<>();
        Connection conn = null;
        PreparedStatement pstmt = null;
        ResultSet rs = null;
        try {
            conn = DBUtil.getConn();
            String sql = "SELECT id, username, age FROM user";
            pstmt = conn.prepareStatement(sql);
            rs = pstmt.executeQuery();
            while (rs.next()) {
                User user = new User();
                user.setId(rs.getInt("id"));
                user.setUsername(rs.getString("username"));
                user.setAge(rs.getInt("age"));
                userList.add(user);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            DBUtil.close(conn, pstmt, rs);
        }
        return userList;
    }
}

5. Service 业务层 com.service.UserService 处理业务逻辑,调用 DAO

后续加分页、过滤、数据校验全部写在这里

package com.service;

import com.dao.UserDao;
import com.entity.User;
import java.util.List;

public class UserService {
    // 注入DAO
    private final UserDao userDao = new UserDao();

    // 获取全部用户列表
    public List<User> getUserList() {
        // 这里可以写业务:数据过滤、分页、数据转换等
        return userDao.findAll();
    }
}

6. HTTP 服务核心包 com.server

6.1 BaseHandler 基础父类(统一处理 OPTIONS 预检请求,解决 Vue 跨域报错)
package com.server;

import com.sun.net.httpserver.HttpHandler;
import com.util.HttpRespUtil;
import java.io.IOException;
import com.sun.net.httpserver.HttpExchange;

public abstract class BaseHandler implements HttpHandler {
    @Override
    public void handle(HttpExchange exchange) throws IOException {
        // 统一处理OPTIONS跨域预检请求
        if ("OPTIONS".equals(exchange.getRequestMethod())) {
            HttpRespUtil.setCorsHeader(exchange);
            exchange.sendResponseHeaders(204, -1);
            exchange.close();
            return;
        }
        // 子类实现业务处理
        doHandle(exchange);
    }
    // 子类重写这个方法写接口逻辑
    protected abstract void doHandle(HttpExchange exchange) throws IOException;
}
6.2 UserHandler 用户模块接口处理器(对应 /user/list 接口)
package com.server;

import com.entity.User;
import com.service.UserService;
import com.util.HttpRespUtil;
import com.sun.net.httpserver.HttpExchange;
import java.io.IOException;
import java.util.List;

public class UserHandler extends BaseHandler {
    private final UserService userService = new UserService();

    @Override
    protected void doHandle(HttpExchange exchange) throws IOException {
        try {
            // 调用业务层获取数据
            List<User> userList = userService.getUserList();
            // 统一返回标准JSON
            HttpRespUtil.success(exchange, userList);
        } catch (Exception e) {
            e.printStackTrace();
            HttpRespUtil.fail(exchange, "查询用户数据失败");
        }
    }
}
6.3 ApiServerMain 程序启动入口(唯一 main 方法,启动 HTTP 服务)
package com.server;

import com.config.DBConfig;
import com.sun.net.httpserver.HttpServer;
import java.io.IOException;
import java.net.InetSocketAddress;

public class ApiServerMain {
    public static void main(String[] args) throws IOException {
        // 创建服务
        HttpServer server = HttpServer.create(new InetSocketAddress(DBConfig.SERVER_PORT), 0);

        // 注册路由:路径 -> 对应处理器
        server.createContext("/user/list", new UserHandler());
        // 以后新增接口在这里追加,例如:
        // server.createContext("/user/add", new UserAddHandler());
        // server.createContext("/article/list", new ArticleHandler());

        server.setExecutor(null);
        server.start();
        System.out.println("✅ 后端HTTP服务启动成功!端口:" + DBConfig.SERVER_PORT);
        System.out.println("📌 用户列表接口地址:http://localhost:"+DBConfig.SERVER_PORT+"/user/list");
    }
}

三、项目运行方式

  1. 确认 lib 下三个 jar 包已添加到项目库(fastjson、mysql 驱动)
  2. 修改 DBConfig 里的数据库密码为你自己的
  3. 找到 com.server.ApiServerMain,右键运行 main 方法
  4. 浏览器访问:http://localhost:8090/user/list 返回标准 JSON 示例:

json

{"code":200,"msg":"操作成功","data":[{"id":1,"username":"张三","age":20},{"id":2,"username":"李四","age":22}]}

四、Vue2 前端适配修改(axios 请求、统一返回格式)

页面组件修改请求逻辑

<template>
  <div class="table-wrap">
    <h2>数据库表数据展示</h2>
    <table border="1" cellpadding="10">
      <thead>
        <tr>
          <th>ID编号</th>
          <th>用户名</th>
          <th>年龄</th>
        </tr>
      </thead>
      <tbody>
        <tr v-for="item in tableList" :key="item.id">
          <td>{{ item.id }}</td>
          <td>{{ item.username }}</td>
          <td>{{ item.age }}</td>
        </tr>
      </tbody>
    </table>
  </div>
</template>

<script>
export default {
  data() {
    return {
      tableList: []
    }
  },
  mounted() {
    // 请求新接口 /user/list
    this.$axios.get('/user/list').then(res => {
      // 后端统一格式:res.data.data 才是数组列表
      if(res.data.code === 200){
        this.tableList = res.data.data
      }else{
        alert(res.data.msg)
      }
    }).catch(err => {
      console.error('接口请求失败,请确认Java服务已启动', err)
    })
  }
}
</script>

更多推荐