当前位置: 首页 > news >正文

IDEA实现纯java项目并打包jar(不使用Maven,Spring)

前言

在工作的过程中,我们一直有用MavenSpring,SpringBoot等去构建我们的java后端项目
又因为之前只是使用,对其原理不是很了解
然后突然想到,如果要构建一个不用MavenSpring要怎么实现?
最近工作稍微清闲一点,于是有时间研究一下,最终有了这篇文章

因此,本文章最终会教你实现如下

✨ 使用JDBC连接MySql
✨ 使用纯java实现GET,POST请求供外部接口调用
✨ 实现纯java项目实现简单的定时任务
✨ 使用纯Java启动我们的项目
✨ 使用IDEA打包jar包

要素

正常来说,我们肯定是应该使用Maven,Spring等去构建我们的项目,但是这篇文章的意义主要是为了了解纯java是如何实现一个后端系统的,为了后面的Maven,Spring构建有更深的了解

要实现一个最简单后端系统,我们首先需要可以联通我们的数据库,然后去进行增删改查,实现具体的逻辑,此外还可以添加定时任务进行点缀处理,当然如果自己的项目不涉及定时任务,这个也是可以省略

最终我实现的项目结构如下

PureJavaDemo  // 项目名称
├── lib // 依赖文件夹├── mysql-connector-java-8.0.15.jar  // mysql驱动依赖文件包
├── src├── com├── demo├── bean├── vo├── ResponseResult.java  // 统一响应实体类├── User.java // 表User的对象实体├── config // 配置相关代码├── router  // 路由相关代码├── RouteHandler.java  // 路由处理器├── RouteRegistry.java // 路由注册器├── DatabaseConnection.java // mysql数据库连接配置类├── controller // 路由控制层├── RequestRouter.java // 请求路由器├── UserRouteHandler.java // 表User相关逻辑请求路由├── dao // 数据库不同表增删改查dao层├── UserDao // User表增删改查├── schedule // 定时任务相关逻辑代码├── BaseTask.java // 定时任务基类├── TaskScheduler.java // 定时任务管理器├── UserCleanupTask.java // 用户清除定时任务├── service // 具体逻辑实现├── UserService.java // User相关逻辑具体实现├── util // 工具类├── JsonUtil.java // JSON字符处理工具类├── TimeUtil.java // 时间处理工具类				├── Main.java	// 项目启动类		

我实际项目截图如下
在这里插入图片描述

在我实际的纯java项目中,我只引入了一个mysql依赖包,实际上也可以如MavenSpring一样引入对应pom.xml里面的相关依赖来精简自己的项目逻辑

搭建项目

首先我们使用IDEA新建我们的项目

🎈 File -> New -> Project… 打开创建模块面板

在这里插入图片描述

🎈 选择java 创建java项目,直接点击Next,别的什么都不要动

在这里插入图片描述

🎈 一路Next,输入项目名称,然后点击Finish即可

在这里插入图片描述

🎈然后会创建一个默认什么都没有的项目

在这里插入图片描述

🎈 接着新建一个文件夹,取名lib,名称任意,一般叫这个;找mysql的驱动依赖文件,这里可以从我们的本地Maven库拿,或者从网上搜索获取mysql依赖,其他依赖同理,这里我演示如何从本地获取,前提是有下载过

我们找到我们其他Maven,Spring项目,看IDEA的MAVEN配置存放路径

🎈 File -> Setting -> 搜索Maven

在这里插入图片描述

🎈 然后复制路径打开文件夹,再看看我们的mysql的依赖层级,任意选择一个版本,按照自己需求,然后复制里面的jar格式的文件到自己项目的lib文件夹里面

在这里插入图片描述

        <dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.15</version></dependency>

在这里插入图片描述

在这里插入图片描述

🎈 OK之后,我们需要把把依赖文件添加到项目里面,这里指的是让项目识别到依赖
File -> Project Structure -> Libraries打开这里之后,点击+号选择依赖引入,引入之后会重新在这里,然后Apply应用就OK了

在这里插入图片描述

🎈 到这里搭建基本好了,然后按照我给出的项目进行建立对应的java文件代码

逻辑

那么接下来就需要正式实现我们的纯java项目,我这边以一个表为例:

CREATE TABLE `user` (`user_id` varchar(20) NOT NULL COMMENT '用户id',`avatar` longtext COMMENT '头像',`user_name` varchar(50) NOT NULL COMMENT '用户名',`password` varchar(50) NOT NULL COMMENT '密码',`create_time` datetime DEFAULT NULL COMMENT '创建时间',`update_time` datetime DEFAULT NULL COMMENT '更新时间',`is_admin` varchar(1) DEFAULT 'N' COMMENT '是否为管理员',`status` varchar(1) DEFAULT 'Y' COMMENT '是否生效',`silence` varchar(1) DEFAULT 'N' COMMENT '是否禁言',PRIMARY KEY (`user_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

我会实现查询接口,等项目启动之后使用POSTMAN进行调用

数据库连接

首先我们使用JDBC,连接我们的数据库

DatabaseConnection.java

package com.demo.config;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;public class DatabaseConnection {private static final String URL = "jdbc:mysql://localhost:3306/chat?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=UTC";private static final String USER = "root";private static final String PASSWORD = "root";static {try {Class.forName("com.mysql.cj.jdbc.Driver");//Class.forName("com.mysql.cj.jdbc.Driver", true, Thread.currentThread().getContextClassLoader());} catch (ClassNotFoundException e) {throw new RuntimeException("MySQL JDBC Driver not found", e);}}public static Connection getConnection() throws SQLException {return DriverManager.getConnection(URL, USER, PASSWORD);}public static void closeConnection(Connection conn) {if (conn != null) {try {conn.close();} catch (SQLException e) {e.printStackTrace();}}}
}

表增删改查

这个是映射User表的增删改查,通过传递数据库的连接实现增删改查,其他表的可以按照这个相同处理,同样要实现增删改查,需要把实体建立出来

User.java

package com.demo.bean;import java.util.Date;public class User {private String userId;private String avatar;private String userName;private String password;private Date createTime;private Date updateTime;private String isAdmin;private String status;private String silence;// Getters and Setterspublic String getUserId() { return userId; }public void setUserId(String userId) { this.userId = userId; }public String getAvatar() { return avatar; }public void setAvatar(String avatar) { this.avatar = avatar; }public String getUserName() { return userName; }public void setUserName(String userName) { this.userName = userName; }public String getPassword() { return password; }public void setPassword(String password) { this.password = password; }public Date getCreateTime() { return createTime; }public void setCreateTime(Date createTime) { this.createTime = createTime; }public Date getUpdateTime() { return updateTime; }public void setUpdateTime(Date updateTime) { this.updateTime = updateTime; }public String getIsAdmin() { return isAdmin; }public void setIsAdmin(String isAdmin) { this.isAdmin = isAdmin; }public String getStatus() { return status; }public void setStatus(String status) { this.status = status; }public String getSilence() { return silence; }public void setSilence(String silence) { this.silence = silence; }@Overridepublic String toString() {return "User{" +"userId='" + userId + '\'' +", userName='" + userName + '\'' +", avatar='" + avatar + '\'' +", password='" + password + '\'' +", createTime='" + createTime + "\'" +", updateTime='" + updateTime + "\'" +", isAdmin='" + isAdmin + "\'" +", status='" + status + "\'" +", silence='" + silence + "\'" +'}';}
}

UserDao.java

package com.demo.dao;
import com.demo.bean.User;
import java.sql.*;
import java.util.ArrayList;
import java.util.List;public class UserDao {// 查询所有用户public List<User> selectAllUsers(Connection conn) throws SQLException {List<User> users = new ArrayList<>();String sql = "SELECT * FROM user";try (PreparedStatement stmt = conn.prepareStatement(sql);ResultSet rs = stmt.executeQuery()) {while (rs.next()) {users.add(mapResultSetToUser(rs));}}return users;}// 根据用户ID查询用户public User selectUserByUserId(Connection conn, String userId) throws SQLException {String sql = "SELECT * FROM user WHERE user_id = ?";try (PreparedStatement stmt = conn.prepareStatement(sql)) {stmt.setString(1, userId);try (ResultSet rs = stmt.executeQuery()) {if (rs.next()) {return mapResultSetToUser(rs);}}}return null;}// 新增用户public int insertUser(Connection conn, User user) throws SQLException {String sql = "INSERT INTO user (" +"user_id, avatar, user_name, password, " +"create_time, update_time, is_admin, status, silence" +") VALUES (?, ?, ?, ?, NOW(), NOW(), ?, ?, ?)";try (PreparedStatement stmt = conn.prepareStatement(sql)) {stmt.setString(1, user.getUserId());stmt.setString(2, user.getAvatar());stmt.setString(3, user.getUserName());stmt.setString(4, user.getPassword());stmt.setString(5, user.getIsAdmin());stmt.setString(6, user.getStatus());stmt.setString(7, user.getSilence());return stmt.executeUpdate();}}// 根据用户ID删除用户public int deleteUserById(Connection conn, String userId) throws SQLException {String sql = "DELETE FROM user WHERE user_id = ?";try (PreparedStatement stmt = conn.prepareStatement(sql)) {stmt.setString(1, userId);return stmt.executeUpdate();}}// 更新用户信息public int updateUser(Connection conn, User user) throws SQLException {String sql = "UPDATE user SET " +"avatar = ?, " +"user_name = ?, " +"password = ?, " +"update_time = NOW(), " +"is_admin = ?, " +"status = ?, " +"silence = ? " +"WHERE user_id = ?";try (PreparedStatement stmt = conn.prepareStatement(sql)) {stmt.setString(1, user.getAvatar());stmt.setString(2, user.getUserName());stmt.setString(3, user.getPassword());stmt.setString(4, user.getIsAdmin());stmt.setString(5, user.getStatus());stmt.setString(6, user.getSilence());stmt.setString(7, user.getUserId());return stmt.executeUpdate();}}// 清理不活跃用户public int deleteInactiveUsers(Connection conn, int inactiveDays) throws SQLException {String sql = "DELETE FROM user WHERE status = 'N' AND create_time < DATE_SUB(NOW(), INTERVAL ? DAY)";try (PreparedStatement stmt = conn.prepareStatement(sql)) {stmt.setInt(1, inactiveDays);return stmt.executeUpdate();}}// 辅助方法:将ResultSet映射到User对象private User mapResultSetToUser(ResultSet rs) throws SQLException {User user = new User();user.setUserId(rs.getString("user_id"));user.setUserName(rs.getString("user_name"));user.setAvatar(rs.getString("avatar"));user.setPassword(rs.getString("password"));user.setCreateTime(rs.getTimestamp("create_time"));user.setUpdateTime(rs.getTimestamp("update_time"));user.setIsAdmin(rs.getString("is_admin"));user.setStatus(rs.getString("status"));user.setSilence(rs.getString("silence"));return user;}
}

简单User处理逻辑

在这里我使用了简单的统一响应类,去返回响应结果,相关代码是

ResponseResult.java

package com.demo.bean.vo;public class ResponseResult {private int code;private String message;private Object data;public ResponseResult(int code, String message, Object data) {this.code = code;this.message = message;this.data = data;}public int getCode() { return code; }public String getMessage() { return message; }public Object getData() { return data; }
}

UserService.java

package com.demo.service;
import com.demo.bean.User;
import com.demo.bean.vo.ResponseResult;
import com.demo.config.DatabaseConnection;
import com.demo.dao.UserDao;
import java.sql.Connection;
import java.util.List;public class UserService {private final UserDao userDao = new UserDao();public ResponseResult getAllUsers() {try (Connection conn = DatabaseConnection.getConnection()) {List<User> users = userDao.selectAllUsers(conn);return new ResponseResult(200, "Success", users);} catch (Exception e) {return new ResponseResult(500, "Error: " + e.getMessage(), null);}}public ResponseResult getUserById(String userId) {try (Connection conn = DatabaseConnection.getConnection()) {User user = userDao.selectUserByUserId(conn, userId);if (user != null) {return new ResponseResult(200, "Success", user);}return new ResponseResult(404, "User not found", null);} catch (Exception e) {return new ResponseResult(500, "Error: " + e.getMessage(), null);}}
}

工具类实现

因为为了尽可能减少引入依赖,我这边添加了工具类进行补充,实际可以添加更多依赖代替

JsonUtil.java

package com.demo.util;import java.lang.reflect.Field;
import java.text.SimpleDateFormat;
import java.util.Collection;
import java.util.Date;public class JsonUtil {private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");public static String toJson(Object obj) {if (obj == null) return "null";if (obj instanceof Collection) {return collectionToJson((Collection<?>) obj);} else if (obj instanceof String) {return "\"" + escapeJson((String) obj) + "\"";} else if (obj instanceof Number || obj instanceof Boolean) {return obj.toString();} else if (obj instanceof Date) {return "\"" + DATE_FORMAT.format((Date) obj) + "\"";} else {return objectToJson(obj);}}private static String objectToJson(Object obj) {StringBuilder sb = new StringBuilder("{");Field[] fields = obj.getClass().getDeclaredFields();boolean firstField = true;for (Field field : fields) {field.setAccessible(true);try {Object value = field.get(obj);if (value == null) continue;if (!firstField) {sb.append(",");}firstField = false;sb.append("\"").append(field.getName()).append("\":");if (value instanceof String || value instanceof Date) {sb.append("\"").append(escapeJson(value.toString())).append("\"");} else if (value instanceof Number || value instanceof Boolean) {sb.append(value);} else {sb.append(toJson(value));}} catch (IllegalAccessException e) {// 忽略无法访问的字段}}return sb.append("}").toString();}private static String collectionToJson(Collection<?> collection) {StringBuilder sb = new StringBuilder("[");boolean firstElement = true;for (Object item : collection) {if (!firstElement) {sb.append(",");}firstElement = false;sb.append(toJson(item));}return sb.append("]").toString();}private static String escapeJson(String input) {if (input == null) return "";return input.replace("\\", "\\\\").replace("\"", "\\\"").replace("\b", "\\b").replace("\f", "\\f").replace("\n", "\\n").replace("\r", "\\r").replace("\t", "\\t");}
}

TimeUtil.java

package com.demo.util;public class TimeUtil {/*** 计算距离下一个指定时间点的延迟时间* @param hour 小时 (0-23)* @param minute 分钟 (0-59)* @return 延迟毫秒数*/public static long calculateInitialDelay(int hour, int minute) {long now = System.currentTimeMillis();long next = java.time.LocalDate.now().atTime(hour, minute).atZone(java.time.ZoneId.systemDefault()).toInstant().toEpochMilli();if (now > next) {next += 24 * 60 * 60 * 1000; // 如果今天的时间已过,则计算明天的时间}return next - now;}
}

路由逻辑

这里路由指我们需要提供给外部访问的接口路径

RouteHandler.java

package com.demo.config.router;import com.demo.bean.vo.ResponseResult;import java.util.Map;public interface RouteHandler {ResponseResult handle(Map<String, String> params) throws Exception;
}

RouteRegistry.java

package com.demo.config.router;import com.sun.net.httpserver.HttpExchange;import java.util.HashMap;
import java.util.Map;public class RouteRegistry {private final Map<String, Map<String, RouteHandler>> routes = new HashMap<>();public void register(String method, String path, RouteHandler handler) {routes.computeIfAbsent(method, k -> new HashMap<>()).put(path, handler);}public RouteHandler findHandler(HttpExchange exchange) {String method = exchange.getRequestMethod();String path = exchange.getRequestURI().getPath();Map<String, RouteHandler> methodRoutes = routes.get(method);if (methodRoutes == null) {return null;}// 精确匹配RouteHandler handler = methodRoutes.get(path);if (handler != null) {return handler;}// 通配符匹配 (可选)for (Map.Entry<String, RouteHandler> entry : methodRoutes.entrySet()) {if (path.matches(entry.getKey().replace("*", ".*"))) {return entry.getValue();}}return null;}
}

RequestRouter.java

package com.demo.controller;
import com.demo.bean.vo.ResponseResult;
import com.demo.config.router.RouteHandler;
import com.demo.config.router.RouteRegistry;
import com.demo.util.JsonUtil;
import com.sun.net.httpserver.HttpExchange;
import com.sun.net.httpserver.HttpHandler;import java.io.IOException;
import java.io.OutputStream;
import java.net.URI;
import java.util.HashMap;
import java.util.Map;public class RequestRouter implements HttpHandler {private final RouteRegistry routeRegistry;public RequestRouter() {this.routeRegistry = new RouteRegistry();registerRoutes();}private void registerRoutes() {UserRouteHandler userHandler = new UserRouteHandler();// 注册用户相关路由routeRegistry.register("GET", "/user/selectAllUsers", userHandler::getAllUsers);routeRegistry.register("GET", "/user/selectUserByUserId", userHandler::getUserById);// 示例:注册其他路由// routeRegistry.register("POST", "/product/create", productHandler::createProduct);}@Overridepublic void handle(HttpExchange exchange) throws IOException {URI uri = exchange.getRequestURI();Map<String, String> params = parseQueryParams(uri.getQuery());ResponseResult result;try {RouteHandler handler = routeRegistry.findHandler(exchange);if (handler != null) {result = handler.handle(params);} else {result = new ResponseResult(404, "Endpoint not found: " + uri.getPath(), null);}} catch (Exception e) {result = new ResponseResult(500, "Internal error: " + e.getMessage(), null);e.printStackTrace();}sendResponse(exchange, result);}private void sendResponse(HttpExchange exchange, ResponseResult result) throws IOException {String response = JsonUtil.toJson(result);exchange.getResponseHeaders().add("Content-Type", "application/json");exchange.sendResponseHeaders(result.getCode(), response.getBytes().length);try (OutputStream os = exchange.getResponseBody()) {os.write(response.getBytes());}}private Map<String, String> parseQueryParams(String query) {Map<String, String> params = new HashMap<>();if (query != null) {for (String param : query.split("&")) {String[] pair = param.split("=");if (pair.length > 1) {params.put(pair[0], pair[1]);}}}return params;}
}

UserRouteHandler.java

package com.demo.controller;import com.demo.bean.vo.ResponseResult;
import com.demo.service.UserService;import java.util.Map;public class UserRouteHandler {private final UserService userService = new UserService();public ResponseResult getAllUsers(Map<String, String> params) throws Exception {return userService.getAllUsers();}public ResponseResult getUserById(Map<String, String> params) throws Exception {String userId = params.getOrDefault("userId", "");if (!userId.isEmpty()) {return userService.getUserById(userId);} else {return new ResponseResult(400, "Missing userId parameter", null);}}// 添加更多用户相关的方法// public ResponseResult createUser(Map<String, String> params) { ... }
}

定时任务

如果不加上定时任务,纯java项目是可以更精简一点,属于可有可无的,但是正常实际项目都会有定时功能的需求,因此还是加上

BaseTask.java

package com.demo.schedule;public abstract class BaseTask implements Runnable {protected final String taskName;public BaseTask(String taskName) {this.taskName = taskName;}@Overridepublic void run() {try {System.out.println("[" + taskName + "] 任务开始执行...");executeTask();System.out.println("[" + taskName + "] 任务执行完成");} catch (Exception e) {System.err.println("[" + taskName + "] 任务执行失败: " + e.getMessage());e.printStackTrace();}}protected abstract void executeTask() throws Exception;public String getTaskName() {return taskName;}
}

TaskScheduler.java

package com.demo.schedule;import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;public class TaskScheduler {private static final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(3);private static final TaskScheduler instance = new TaskScheduler();private TaskScheduler() {// 私有构造器}public static TaskScheduler getInstance() {return instance;}/*** 安排定时任务* @param task 要执行的任务* @param initialDelay 首次执行延迟时间* @param period 执行周期* @param unit 时间单位* @return 定时任务控制器*/public ScheduledFuture<?> scheduleAtFixedRate(Runnable task,long initialDelay,long period,TimeUnit unit) {return scheduler.scheduleAtFixedRate(task, initialDelay, period, unit);}/*** 安排延迟执行任务* @param task 要执行的任务* @param delay 延迟时间* @param unit 时间单位* @return 定时任务控制器*/public ScheduledFuture<?> schedule(Runnable task,long delay,TimeUnit unit) {return scheduler.schedule(task, delay, unit);}/*** 关闭定时任务管理器*/public void shutdown() {scheduler.shutdown();try {if (!scheduler.awaitTermination(60, TimeUnit.SECONDS)) {scheduler.shutdownNow();}} catch (InterruptedException e) {scheduler.shutdownNow();Thread.currentThread().interrupt();}}
}

UserCleanupTask.java

package com.demo.schedule;
import com.demo.dao.UserDao;
import com.demo.config.DatabaseConnection;
import java.sql.Connection;public class UserCleanupTask extends BaseTask {// 清理超过30天的未激活用户private static final int INACTIVE_DAYS = 30;public UserCleanupTask() {super("用户清理任务");}@Overrideprotected void executeTask() throws Exception {try (Connection conn = DatabaseConnection.getConnection()) {UserDao userDao = new UserDao();int deletedCount = userDao.deleteInactiveUsers(conn, INACTIVE_DAYS);System.out.println("清理了 " + deletedCount + " 个超过 "+ INACTIVE_DAYS + " 天未激活的用户");}}
}

启动类

启动类代表将整个项目进行启动,可以和我们的Maven项目,Spring项目一样,也是项目的入口

Main.java

package com.demo;import com.demo.controller.RequestRouter;
import com.demo.schedule.TaskScheduler;
import com.demo.schedule.UserCleanupTask;
import com.demo.util.TimeUtil;
import com.sun.net.httpserver.HttpServer;import java.io.IOException;
import java.net.InetSocketAddress;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;public class Main {public static void main(String[] args) throws IOException {int port = 8082;HttpServer server = HttpServer.create(new InetSocketAddress(port), 0);server.createContext("/", new RequestRouter());server.setExecutor(null);server.start();System.out.println("✅ Server started on port " + port);// 初始化定时任务initScheduledTasks();// 添加关闭钩子,确保关闭Runtime.getRuntime().addShutdownHook(new Thread(() -> {System.out.println("Shutting down application...");server.stop(0);TaskScheduler.getInstance().shutdown();System.out.println("Application shutdown complete");}));}private static void initScheduledTasks() {TaskScheduler scheduler = TaskScheduler.getInstance();// 每10分钟执行一次的用户清理任务ScheduledFuture<?> userCleanupTask = scheduler.scheduleAtFixedRate(new UserCleanupTask(),0,   // 初始延迟(立即开始)10,  // 每10分钟TimeUnit.MINUTES);// 每天凌晨2点执行的统计任务scheduler.scheduleAtFixedRate(() -> System.out.println("每日统计任务执行中..."),TimeUtil.calculateInitialDelay(2, 0), // 凌晨2点24, // 每天执行一次TimeUnit.HOURS);System.out.println("定时任务初始化完成");}
}

打包Jar并启动

启动

如上我们整个项目就处理完毕了,如果要求启动项目,那么要求我们的端口不能被占用,否则会报错:

Exception in thread “main” java.net.BindException: Address already in use: bind
at sun.nio.ch.Net.bind0(Native Method)
at sun.nio.ch.Net.bind(Net.java:433)
at sun.nio.ch.Net.bind(Net.java:425)
at sun.nio.ch.ServerSocketChannelImpl.bind(ServerSocketChannelImpl.java:223)
at sun.nio.ch.ServerSocketAdaptor.bind(ServerSocketAdaptor.java:74)
at sun.net.httpserver.ServerImpl.(ServerImpl.java:100)
at sun.net.httpserver.HttpServerImpl.(HttpServerImpl.java:50)
at sun.net.httpserver.DefaultHttpServerProvider.createHttpServer(DefaultHttpServerProvider.java:35)
at com.sun.net.httpserver.HttpServer.create(HttpServer.java:130)
at com.demo.Main.main(Main.java:10)

启动点击Main.java 右键选择Run Mian.main()或者Debug Mian.main()

启动之后控制台会打印一些数据
如我的项目会是这些

✅ Server started on port 8082
[用户清理任务] 任务开始执行…
定时任务初始化完成
清理了 0 个超过 30 天未激活的用户
[用户清理任务] 任务执行完成

在这里插入图片描述

在我的项目示例中我有两个外部调用接口
/user/selectAllUsers
/user/selectUserByUserId
此时我的表数据有这些:

在这里插入图片描述

INSERT INTO chat.`user` (user_id, avatar, user_name, password, create_time, update_time, is_admin, status, silence) VALUES('11', '11', '11', '11', '2025-07-14 00:00:00', '2025-07-14 00:00:00', 'N', 'Y', 'N');

此时调用接口:

http://localhost:8082/user/selectAllUsers

响应数据如下:
在这里插入图片描述

{"code": 200,"message": "Success","data": [{"userId": "11","avatar": "11","userName": "11","password": "11","createTime": "2025-07-14 08:00:00.0","updateTime": "2025-07-14 08:00:00.0","isAdmin": "N","status": "Y","silence": "N"}]
}

成功启动并且请求到了数据库表数据

打包jar

如上我们已经验证了项目正常启动,我们我们需要将其打包jar,使其可以在本机或者服务器正常部署使用
File -> Project Structure -> Artifacts打开到这个界面,然后点击+号,选择jar下的from modules with dependencies

在这里插入图片描述

Module会自动选择当前项目,Main Class需要选择Main.java,并且JAR files from dependencies 需要选择为copy to the output directory and link via mainfest
点击OK然后Apply

在这里插入图片描述
在这里插入图片描述

就会多出一个项目名称的jar包在这里
然后点击Build -> Build Artifacts再在新界面选择点击Build

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

等待打包完成,这个时候会在我们的out文件夹下的artifacts文件夹会看到我们刚刚打包后的jar包
关闭我们的项目,然后启动该jar包
java -jar PureJavaDemo.jar

在这里插入图片描述

在这里插入图片描述

可以看到如上截图成功执行了jar,往user表加些数据再次请求postman验证是否可用

在这里插入图片描述

{"code": 200,"message": "Success","data": [{"userId": "11","avatar": "11","userName": "11","password": "11","createTime": "2025-07-14 08:00:00.0","updateTime": "2025-07-14 08:00:00.0","isAdmin": "N","status": "Y","silence": "N"},{"userId": "22","avatar": "22","userName": "22","password": "22","createTime": "2025-07-14 08:00:00.0","updateTime": "2025-07-14 08:00:00.0","isAdmin": "N","status": "Y","silence": "N"}]
}

可以看到正常的访问,但是有一点需要注意,打包之后的jar需要和依赖放在同一个文件夹下

项目GIT

纯java后端项目DEMO

优缺点

综上,我们已经很清晰明了的知道java是怎么去运作我们的项目了,但是还是那句话,这个只是让你更好的学习和了解java,真正要开发一个项目还是选择Maven,Spring框架,如下我列举了一些纯java项目优缺点

优点
🧡 轻量: 启动快,内存占用第,无框架开销
🧡 自主掌控: 自主实现逻辑,可以深度理解底层机制(HTTP/TCP等)
🧡学习价值高: 对于掌握基础友好

缺点
🖤开发效率低: 手动实现路由,依赖注入等,重复造轮子,缺少标准项目结构
🖤维护成本高: 自行管理依赖版本,缺少自动化测试支持,扩展性差
🖤团队协作难: 无统一的开发规范,项目结构依赖个人风格

结语

如上为实现纯java项目的过程和代码,如有遗漏后续补充

http://www.lryc.cn/news/587910.html

相关文章:

  • Linux的相关学习
  • Oracle物化视图函数使用注意事项
  • Oracle 递归函数及 其他数据库 CTE 使用小计
  • SpringBoot集成SAP,本地IDEA启动和Windows服务器部署
  • 企业培训笔记:axios 发送 ajax 请求
  • iOS高级开发工程师面试——RunLoop
  • [Nagios Core] struct监控对象 | 配置.cfg加载为内存模型
  • CSS `:root` 伪类深入讲解
  • Reactor 模式详解
  • spring shell 基础使用
  • Transformer江湖录 第五章:江湖争锋 - BERT vs GPT
  • 20250714让荣品RD-RK3588开发板在Android13下长按关机
  • Bash常见条件语句和循环语句
  • vLLM与SGLang在自然语言处理领域的技术架构与性能对比研究
  • 从数据库到播放器:Java视频续播功能完整实现解析
  • cuda优化之softmax
  • 调用 System.runFinalizersOnExit() 的风险与解决方法
  • JavaScript 与 C语言基础知识差别
  • Spark 单机模式安装与测试全攻略​
  • 【HTML】五子棋(精美版)
  • 数据采集卡选型——PCIE和USB型采集卡对比
  • C++类模版与友元
  • java--ThreadLocal创建以及get源码解析
  • [Pytorch]深度学习-part1
  • QT跨平台应用程序开发框架(7)—— 常用输入类控件
  • 消费 Kafka 一个TOPIC数据,插入到另一个KAFKA的TOPIC
  • Docker配置国内镜像源
  • CompletableFuture 源码解析
  • Linux 系统下的 Sangfor VDI 客户端安装与登录完全攻略 (CentOS、Ubuntu、麒麟全线通用)
  • HTTP协议版本对比